text:
struct pancake
    funcSymbol::Symbol
    funcName::String
    parameterizedBlock::Expr
    sanitizedBlock::Expr
    verilogBlock::String
    juliaBlock::Expr
end

global funcStack = Array{pancake}(0)
global exSymbols = Array{Symbol}(0)
global exBlocks = Array{Expr}(0)

function loadJULIOGexpr(ex::Expr)

    # Remove the REPL line number indicators
    #   If they're not already obsolete, they will be, soon
    ex = removelinenumbers(ex)

    if ex.head == :Function
        push!(exSymbols, ex.args[1].args[1])
        push!(exBlocks, ex)
    else
        # ex.head must equal :block
        l = length(ex.args)
        for i = 1:l
            push!(exSymbols, ex.args[i].args[1].args[1])
            push!(exBlocks, ex.args[i])
        end
    end
end

function overwriteJULIOGexpr(ex::Expr)
    global exSymbols = Array{Symbol}(0)
    global exBlocks = Array{Expr}(0)

    # Remove the REPL line number indicators
    #   If they're not already obsolete, they will be, soon
    ex = removelinenumbers(ex)

    if ex.head == :Function
        push!(exSymbols, ex.args[1].args[1])
        push!(exBlocks, ex)
    else
        # ex.head must equal :block
        l = length(ex.args)
        for i = 1:l
            push!(exSymbols, ex.args[i].args[1].args[1])
            push!(exBlocks, ex.args[i])
        end
    end
end

function parsefile(filename::String)
    file = open(filename)
    str = readstring(file)
    return parse(str)
end

function removelinenumbers(ex::Expr)
    l = length(ex.args)
    i = 1
    while i <= l
        if isa(ex.args[i], Expr)
            if ex.args[i].head == :line
                deleteat!(ex.args, i)
                i = i - 1
                l = l - 1
            else
                ex.args[i] = removelinenumbers(ex.args[i])
            end
        end
        i = i + 1
    end
    return ex
end

# TODO Figure out how to remember hieararchy in funcStack
#       Will come in handy when I need to unroll recursion in verilog
macro block(func::Symbol, name::String, arguments::Expr)
    if !isdefined(:exSymbols)
        error("No expression loaded. Cannot call @block without loaded JULIOG")
    end
    if !in(func, exSymbols)
        error("No Symbol matching $(func) was found in loaded JULIOG expression")
    end

    if !isdefined(:funcStack)
        global funcStack = Array{pancake}(0)
    else
        global funcStack
    end

    ref = findlast(exSymbols .== func)
    blockToInterpret = exBlocks[ref]

    push!(funcStack, pancake(func, name, Expr(:function), Expr(:function), "", Expr(:function)))
    l = length(funcStack)

    # parameterize the block
    # solve for function statics
    parameterizedBlock = parameterize(blockToInterpret, arguments)
    # Print parameterizedBlock to a file
    # prettyprintPB(sanitizedBlock)

    funcStack[l] = pancake(func, name, parameterizedBlock, Expr(:function), "", Expr(:function))

    # Create Data structure of wires created
    # add wire instantiations when lacking
    sanitizedBlock, arrowDict = sanitize(parameterizedBlock)

    funcStack[l] = pancake(func, name, parameterizedBlock, sanitizedBlock, "", Expr(:function))

    # Convert the block to a string of verilog text
    verilogBlock = JuliogToVerilog(sanitizedBlock, arrowDict)
    # Print verilogBlock to a file
    # prettyprintJV(verilogBlock)

    funcStack[l] = pancake(func, name, parameterizedBlock, sanitizedBlock, verilogBlock, Expr(:function))

    #juliaBlock = JuliogToJulia(sanitizedBlock)
    juliaBlock = Expr(:function)
    # Print juliaBlock to a file
    # prettyprintJB(juliaBlock)

    #funcStack[l] = pancake(func, name, parameterizedBlock, sanitizedBlock, verilogBlock, juliaBlock)
    println("At end of @block")
end

# TODO write a pretty print function for exprs
# TODO write a print to file for verilog

max_stars_repo_name: trevortheblack/Juliog

max_issues_repo_name: trevortheblack/Juliog

max_forks_repo_name: trevortheblack/Juliog


text:
asfoldable(df::DataFrames.AbstractDataFrame) = DataFrames.eachrow(df)
# We can't use `Compat.eachrow` here.  See:
# https://github.com/JuliaData/DataFrames.jl/pull/2067

ext: jl


text:
using DashBootstrapComponents, DashHtmlComponents

progress = html_div([
    dbc_progress(value=25, color="success", className="mb-3"),
    dbc_progress(value=50, color="warning", className="mb-3"),
    dbc_progress(value=75, color="danger", className="mb-3"),
    dbc_progress(value=100, color="info"),
]);

max_stars_repo_name: harisbal/dash-bootstrap-components

max_issues_repo_name: harisbal/dash-bootstrap-components

max_forks_repo_name: harisbal/dash-bootstrap-components


text:
## validation of properties and code

# check validity of a function invocation
function validate_invocation(@nospecialize(ctx::CompilerContext))
    # get the method
    ms = Base.methods(ctx.f, ctx.tt)
    isempty(ms)   && compiler_error(ctx, "no method found")
    length(ms)!=1 && compiler_error(ctx, "no unique matching method")
    m = first(ms)

    # kernels can't return values
    if ctx.kernel
        rt = Base.return_types(ctx.f, ctx.tt)[1]
        if rt != Nothing
            compiler_error(ctx, "kernel returning a value"; return_type=rt)
        end
    end
end

## IR validation

const RUNTIME_FUNCTION = "call to the Julia runtime"
const UNKNOWN_FUNCTION = "call to an unknown function"

struct UnsupportedIRError <: Exception
    kind::String
    compiletrace::StackTraces.StackTrace
    meta::Any
end

UnsupportedIRError(kind) = UnsupportedIRError(kind, nothing)

# implement comparison, eg. for `unique(UnsupportedIRError[])`
Base.:(==)(x::UnsupportedIRError, y::UnsupportedIRError) =
    x.kind == y.kind && x.compiletrace == y.compiletrace && x.meta == y.meta

function Base.showerror(io::IO, err::UnsupportedIRError)
    print(io, "unsupported $(err.kind)")
    if err.kind == RUNTIME_FUNCTION || err.kind == UNKNOWN_FUNCTION
        print(io, " (", LLVM.name(err.meta), ")")
    end
end

function backtrace(inst)
    name = Ref{Cstring}()
    filename = Ref{Cstring}()
    line = Ref{Cuint}()
    col = Ref{Cuint}()

    depth = 0
    stack = StackTraces.StackFrame[]
    VERSION >= v"0.7.0-alpha.37" || return stack
    while LLVM.API.LLVMGetSourceLocation(LLVM.ref(inst), depth, name, filename, line, col) == 1
        frame = StackTraces.StackFrame(replace(unsafe_string(name[]), r";$"=>""), unsafe_string(filename[]), line[])
        push!(stack, frame)
        depth += 1
    end

    if !isempty(stack) && last(stack).func == :KernelWrapper
        pop!(stack)
    end

    stack
end

function validate_ir!(errors::Vector{>:UnsupportedIRError}, mod::LLVM.Module)
    for f in functions(mod)
        validate_ir!(errors, f)
    end
    return errors
end

function validate_ir!(errors::Vector{>:UnsupportedIRError}, f::LLVM.Function)
    for bb in blocks(f), inst in instructions(bb)
        if isa(inst, LLVM.CallInst)
            validate_ir!(errors, inst)
        end
    end

    return errors
end

const special_fns = ["vprintf", "__nvvm_reflect"]

function validate_ir!(errors::Vector{>:UnsupportedIRError}, inst::LLVM.CallInst)
    dest_f = called_value(inst)
    dest_fn = LLVM.name(dest_f)
    lib = first(filter(lib->startswith(lib, "libjulia"), map(path->splitdir(path)[2], Libdl.dllist())))
    runtime = Libdl.dlopen(lib)
    if isa(dest_f, GlobalValue)
        if isdeclaration(dest_f) && intrinsic_id(dest_f) == 0 && !(dest_fn in special_fns)
            compiletrace = backtrace(inst)
            if Libdl.dlsym_e(runtime, dest_fn) != C_NULL
                push!(errors, UnsupportedIRError(RUNTIME_FUNCTION, compiletrace, dest_f))
            else
                push!(errors, UnsupportedIRError(UNKNOWN_FUNCTION, compiletrace, dest_f))
            end
        end
    elseif isa(dest_f, InlineAsm)
        # let's assume it's valid ASM
    end

    return errors
end

validate_ir(args...) = validate_ir!(Vector{UnsupportedIRError}(), args...)


text:
#md# This is a more symmetrical and accurate way to generate comparison wordclouds, but it may be more time consuming.
#md# ### Prepare two wordcloud objects
using WordCloud

stwords = ["us"];
cs = WordCloud.randomscheme() #:Set1_8#
as = WordCloud.randomangles() #(0,90,45,-45)#
dens = 0.5 #not too high
wca = wordcloud(
    processtext(open(pkgdir(WordCloud)*"/res/Barack Obama's First Inaugural Address.txt"), stopwords=WordCloud.stopwords_en ∪ stwords),
    colors = cs,
    angles = as,
    density = dens,
    backgroundcolor = :maskcolor,
    run = x->nothing, #turn off the initword! and placewords! in advance
)
wcb = wordcloud(
    processtext(open(pkgdir(WordCloud)*"/res/Donald Trump's Inaugural Address.txt"), stopwords=WordCloud.stopwords_en ∪ stwords),
    mask = getsvgmask(wca),
    colors = cs,
    angles = as,
    density = dens,
    backgroundcolor = :maskcolor,
    maskcolor = getmaskcolor(wca),
    font = getparameter(wca, :font),
    run = x->nothing,
)
#md# ### Make the same words the same style
samewords = getwords(wca) ∩ getwords(wcb)
println(length(samewords), " same words")
@assert !hasparameter(wca, :uniquewords)
@assert !hasparameter(wcb, :uniquewords)
setparameter!(wca, setdiff(getwords(wca), samewords), :uniquewords)
setparameter!(wcb, setdiff(getwords(wcb), samewords), :uniquewords)
for w in samewords
    setcolors!(wcb, w, getcolors(wca, w))
    setangles!(wcb, w, getangles(wca, w))
end
#md# ### Put the same words at same position
initwords!(wca)
initwords!(wcb)
keep(wca, samewords) do
    placewords!(wca)
    fit!(wca, 1000)
end
pin(wca, samewords) do
    placewords!(wca) #place other words
end
centers = getpositions(wca, samewords, type=getcenter)
setpositions!(wcb, samewords, centers, type=setcenter!) #manually initialize the position,
pin(wcb, samewords) do
    placewords!(wcb) #place other words
end
#md# ### Fit them all
function syncposition(samewords, pos, wca, wcb)
    pos2 = getpositions(wca, samewords, type=getcenter)
    if pos != pos2
        setpositions!(wcb, samewords, pos2, type=setcenter!)
        setstate!(wcb, :placewords!)
    end
    pos2
end
function pinfit!(wc, samewords, ep1, ep2)
    pin(wc, samewords) do
        fit!(wc, ep1)
    end
    fit!(wc, ep2, teleporting=getparameter(wc, :uniquewords)) #only teleport the unique words
end
pos = getpositions(wca, samewords, type=getcenter)
while getparameter(wca, :epoch) < 2000 && getparameter(wcb, :epoch) < 2000
    global pos
    pinfit!(wca, samewords, 200, 50)
    pos = syncposition(samewords, pos, wca, wcb)
    pinfit!(wcb, samewords, 200, 50)
    pos = syncposition(samewords, pos, wcb, wca)
    if getstate(wca) == getstate(wcb) == :fit!
        break
    end
end
println("Takes $(getparameter(wca, :epoch)) and $(getparameter(wca, :epoch)) epochs")
WordCloud.printcollisions(wca)
WordCloud.printcollisions(wcb)
#md#
ma = paint(wca)
mb = paint(wcb)
h,w = size(ma)
space = fill(mb[1], (h, w÷20))
try mkdir("address_compare2") catch end
println("results are saved in address_compare2")
WordCloud.save("address_compare2/compare2.png", [ma space mb])
#eval# try rm("address_compare2", force=true, recursive=true) catch end
gif = WordCloud.GIF("address_compare2")
record(wca, "Obama", gif)
record(wcb, "Trump", gif)
WordCloud.Render.generate(gif, framerate=1)
wca, wcb
#eval# runexample(:compare2)
#md# ![](address_compare2/compare2.png)
#md# ![](address_compare2/result.gif)


text:
#XXX not finished yet
using CommonRLInterface

const RL = CommonRLInterface

mutable struct TicTacToe <: AbstractEnv
    board::Matrix{Int} # 0 = untaken, 1 = x, 2 = o
end

TicTacToe() = TicTacToe(zeros(Int, 3, 3))

iswinner(b, p) = any(all(b[i,:].==p) for i in 1:3) ||
                 any(all(b[:,i].==p) for i in 1:3) ||
                 all(b[i,i]==p for i in 1:3) ||
                 all(b[i,4-i]==p for i in 1:3)

other(p) = mod1(p+1,2)

RL.reset!(env::TicTacToe) = fill!(env.board, 0)
RL.actions(env::TicTacToe, player=0) = vec([(i, j) for i in 1:3, j in 1:3])
# symmetrical observations for both players: +1 for your square, -1 for other square
RL.observe(env::TicTacToe) = zeros(Int, 3, 3) + (env.board.==player(env)) - (env.board.==other(player(env)))
RL.terminated(env::TicTacToe) = any(iswinner(env.board, p) for p in 1:2) || all(env.board .!= 0)

function RL.act!(env::TicTacToe, a)
    p = player(env)
    winner = 0
    if env.board[a...] == 0
        env.board[a...] = p
        for pp in players(env)
            if iswinner(env.board, pp)
                winner = pp
            end
        end
    else
        # if you take an illegal action, you lose
        winner = other(p)
    end

    if winner == 1
        return (1, -1)
    elseif winner == 2
        return (-1, 1)
    end
    return (0, 0)
end

@provide RL.players(env::TicTacToe) = 1:2
@provide function RL.player(env::TicTacToe)
    if sum(env.board)%3 == 0
        return 1
    else
        return 2
    end
end

@provide RL.render(env::TicTacToe) = env

function Base.show(io::IO, ::MIME"text/plain", env::TicTacToe)
    chars = [' ', 'x', 'o']
    for i in 1:3
        for j in 1:3
            print(io, '|'*chars[env.board[i,j]+1])
        end
        println(io, '|')
    end
end

@provide RL.UtilityStyle(::TicTacToe) = ZeroSum()


text:
module AtmosDycore

export solve!, getrhsfunction

using Requires

abstract type AbstractAtmosDiscretization end

"""
    getrhsfunction(disc::AbstractAtmosDiscretization)

The spatial discretizations are of the form ``Q̇ = f(Q)``, and this function
returns the handle to right-hand side function ``f`` of the `disc`
"""
getrhsfunction(disc::AbstractAtmosDiscretization) =
throw(MethodError(getrhsfunction, typeof(disc)))

include("VanillaAtmosDiscretizations.jl")

end # module

max_stars_repo_name: christophernhill-dev/CLIMA

max_issues_repo_name: christophernhill-dev/CLIMA

max_forks_repo_name: christophernhill-dev/CLIMA


text:
facts("TopListArchive") do

  context("Constructing a small archive and adding to it") do

    a = TopListArchive(1, 3)

    @fact a.size  => 3
    @fact a.count => 0

    add_candidate!(a, 1.0, [0.0])
    @fact a.size              => 3
    @fact a.count             => 1
    @fact best_fitness(a)     => 1.0
    @fact best_candidate(a)   => [0.0]
    @fact last_top_fitness(a) => 1.0
    @fact delta_fitness(a)    => Inf

    add_candidate!(a, 2.0, [1.0])
    @fact a.size            => 3
    @fact a.count           => 2
    @fact best_fitness(a)   => 1.0
    @fact best_candidate(a) => [0.0]
    @fact last_top_fitness(a) => 2.0
    @fact delta_fitness(a)    => Inf

    add_candidate!(a, 0.5, [2.0])
    @fact a.size            => 3
    @fact a.count           => 3
    @fact best_fitness(a)   => 0.5
    @fact best_candidate(a) => [2.0]
    @fact last_top_fitness(a) => 2.0
    @fact delta_fitness(a)    => 0.5

    add_candidate!(a, 0.8, [4.0])
    @fact a.size            => 3
    @fact a.count           => 3
    @fact best_fitness(a)   => 0.5
    @fact best_candidate(a) => [2.0]
    @fact last_top_fitness(a) => 1.0

    expected = ((0.8 - 0.5) / ((1 - 0.05)^(-2/1) - 1))
    @fact width_of_confidence_interval(a, 0.05) => expected
    @fact fitness_improvement_potential(a, 0.05) => (expected / 0.50)

    add_candidate!(a, 0.4, [1.9])
    @fact a.size            => 3
    @fact a.count           => 3
    @fact best_fitness(a)   => 0.4
    @fact best_candidate(a) => [1.9]
    @fact last_top_fitness(a) => 0.8

    expected = ((0.5 - 0.4) / ((1 - 0.05)^(-2/1) - 1))
    @fact width_of_confidence_interval(a, 0.05) => expected
    @fact fitness_improvement_potential(a, 0.05) => (expected / 0.40)
  end

  context("magnitude_class for positive fitness values") do

    @fact BlackBoxOptim.magnitude_class(1.0)      => (1.0, 0.0)
    @fact BlackBoxOptim.magnitude_class(10.0)     => (1.0, 1.0)
    @fact BlackBoxOptim.magnitude_class(1e2)      => (1.0, 2.0)
    @fact BlackBoxOptim.magnitude_class(1e102)    => (1.0, 102.0)
    @fact BlackBoxOptim.magnitude_class(1e-1)     => (1.0, -1.0)
    @fact BlackBoxOptim.magnitude_class(1e-2)     => (1.0, -2.0)
    @fact BlackBoxOptim.magnitude_class(1e-9)     => (1.0, -9.0)
    @fact BlackBoxOptim.magnitude_class(1e-12)    => (1.0, -12.0)

    @fact BlackBoxOptim.magnitude_class(2.0)      => (1.0, 0.3)
    @fact BlackBoxOptim.magnitude_class(20.0)     => (1.0, 1.3)
    @fact BlackBoxOptim.magnitude_class(200.0)    => (1.0, 2.3)

    @fact BlackBoxOptim.magnitude_class(5.0)      => (1.0, 0.6)
    @fact BlackBoxOptim.magnitude_class(50.0)     => (1.0, 1.6)
    @fact BlackBoxOptim.magnitude_class(500.0)    => (1.0, 2.6)

  end

  context("magnitude_class for negative fitness values") do

    @fact BlackBoxOptim.magnitude_class(-1.0)      => (-1.0, 0.0)
    @fact BlackBoxOptim.magnitude_class(-10.0)     => (-1.0, 1.0)
    @fact BlackBoxOptim.magnitude_class(-1e2)      => (-1.0, 2.0)
    @fact BlackBoxOptim.magnitude_class(-1e102)    => (-1.0, 102.0)
    @fact BlackBoxOptim.magnitude_class(-1e-1)     => (-1.0, -1.0)
    @fact BlackBoxOptim.magnitude_class(-1e-2)     => (-1.0, -2.0)
    @fact BlackBoxOptim.magnitude_class(-1e-9)     => (-1.0, -9.0)
    @fact BlackBoxOptim.magnitude_class(-1e-12)    => (-1.0, -12.0)

    @fact BlackBoxOptim.magnitude_class(-2.0)      => (-1.0, 0.3)
    @fact BlackBoxOptim.magnitude_class(-20.0)     => (-1.0, 1.3)
    @fact BlackBoxOptim.magnitude_class(-200.0)    => (-1.0, 2.3)

    @fact BlackBoxOptim.magnitude_class(-5.0)      => (-1.0, 0.6)
    @fact BlackBoxOptim.magnitude_class(-50.0)     => (-1.0, 1.6)
    @fact BlackBoxOptim.magnitude_class(-500.0)    => (-1.0, 2.6)

  end

end


text:
using Test
using LinearAlgebra
using MPI
using Random
using StaticArrays

using ClimateMachine
using ClimateMachine.Atmos
using ClimateMachine.BalanceLaws
using ClimateMachine.ConfigTypes
using ClimateMachine.DGMethods
using ClimateMachine.DGMethods.NumericalFluxes
using ClimateMachine.Mesh.Grids
using ClimateMachine.Mesh.Topologies
using ClimateMachine.Orientations
using Thermodynamics.TemperatureProfiles
using ClimateMachine.TurbulenceClosures
using ClimateMachine.VariableTemplates

using CLIMAParameters
using CLIMAParameters.Planet: planet_radius
struct EarthParameterSet <: AbstractEarthParameterSet end
const param_set = EarthParameterSet()

"""
    main()

Run this test problem
"""
function main()
    ClimateMachine.init()
    ArrayType = ClimateMachine.array_type()

    mpicomm = MPI.COMM_WORLD

    polynomialorder = 5
    numelem_horz = 10
    numelem_vert = 5

    @testset "remainder model" begin
        for FT in (Float64,)# Float32)
            result = test_run(
                mpicomm,
                polynomialorder,
                numelem_horz,
                numelem_vert,
                ArrayType,
                FT,
            )
        end
    end
end

function test_run(
    mpicomm,
    polynomialorder,
    numelem_horz,
    numelem_vert,
    ArrayType,
    FT,
)

    # Structure to pass around to setup the simulation
    setup = RemainderTestSetup{FT}()

    # Create the cubed sphere mesh
    _planet_radius::FT = planet_radius(param_set)
    vert_range = grid1d(
        _planet_radius,
        FT(_planet_radius + setup.domain_height),
        nelem = numelem_vert,
    )
    topology = StackedCubedSphereTopology(mpicomm, numelem_horz, vert_range)

    grid = DiscontinuousSpectralElementGrid(
        topology,
        FloatType = FT,
        DeviceArray = ArrayType,
        polynomialorder = polynomialorder,
        meshwarp = equiangular_cubed_sphere_warp,
    )
    T_profile = IsothermalProfile(param_set, setup.T_ref)

    # This is the base model which defines all the data (all other DGModels
    # for substepping components will piggy-back off of this models data)
    fullphysics = AtmosPhysics{FT}(
        param_set;
        ref_state = HydrostaticState(T_profile),
        turbulence = Vreman(FT(0.23)),
        moisture = DryModel(),
    )
    fullmodel = AtmosModel{FT}(
        AtmosLESConfigType,
        fullphysics;
        orientation = SphericalOrientation(),
        init_state_prognostic = setup,
        source = (Gravity(),),
    )
    dg = DGModel(
        fullmodel,
        grid,
        RusanovNumericalFlux(),
        CentralNumericalFluxSecondOrder(),
        CentralNumericalFluxGradient(),
    )
    Random.seed!(1235)
    Q = init_ode_state(dg, FT(0); init_on_cpu = true)

    acousticmodel = AtmosAcousticGravityLinearModel(fullmodel)

    acoustic_dg = DGModel(
        acousticmodel,
        grid,
        RusanovNumericalFlux(),
        CentralNumericalFluxSecondOrder(),
        CentralNumericalFluxGradient();
        direction = EveryDirection(),
        state_auxiliary = dg.state_auxiliary,
    )
    vacoustic_dg = DGModel(
        acousticmodel,
        grid,
        RusanovNumericalFlux(),
        CentralNumericalFluxSecondOrder(),
        CentralNumericalFluxGradient();
        direction = VerticalDirection(),
        state_auxiliary = dg.state_auxiliary,
    )
    hacoustic_dg = DGModel(
        acousticmodel,
        grid,
        RusanovNumericalFlux(),
        CentralNumericalFluxSecondOrder(),
        CentralNumericalFluxGradient();
        direction = HorizontalDirection(),
        state_auxiliary = dg.state_auxiliary,
    )

    # Create some random data to check the wavespeed function with
    nM = rand(3)
    nM /= norm(nM)
    state_prognostic = Vars{vars_state(dg.balance_law, Prognostic(), FT)}(rand(
        FT,
        number_states(dg.balance_law, Prognostic()),
    ))
    state_auxiliary = Vars{vars_state(dg.balance_law, Auxiliary(), FT)}(rand(
        FT,
        number_states(dg.balance_law, Auxiliary()),
    ))
    full_wavespeed = wavespeed(
        dg.balance_law,
        nM,
        state_prognostic,
        state_auxiliary,
        FT(0),
        (EveryDirection(),),
    )
    acoustic_wavespeed = wavespeed(
        acoustic_dg.balance_law,
        nM,
        state_prognostic,
        state_auxiliary,
        FT(0),
        (EveryDirection(),),
    )

    # Evaluate the full tendency
    full_tendency = similar(Q)
    dg(full_tendency, Q, nothing, 0; increment = false)

    # Evaluate various splittings
    split_tendency = similar(Q)

    # Check pulling acoustic model out
    @testset "full acoustic" begin
        rem_dg = remainder_DGModel(
            dg,
            (acoustic_dg,);
            numerical_flux_first_order = (
                dg.numerical_flux_first_order,
                (acoustic_dg.numerical_flux_first_order,),
            ),
        )
        rem_dg(split_tendency, Q, nothing, 0; increment = false)
        acoustic_dg(split_tendency, Q, nothing, 0; increment = true)
        A = Array(full_tendency.data)
        B = Array(split_tendency.data)
        # Test that we have a fully discrete splitting
        @test all(isapprox.(
            A,
            B,
            rtol = sqrt(eps(FT)),
            atol = 10 * sqrt(eps(FT)),
        ))

        # Test that wavespeeds are split by direction
        every_wavespeed = full_wavespeed .- acoustic_wavespeed
        horz_wavespeed = -zero(FT)
        vert_wavespeed = -zero(FT)
        @test all(
            every_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(),),
            ),
        )
        @test all(
            horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (HorizontalDirection(),),
            ),
        )
        @test all(
            vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (VerticalDirection(),),
            ),
        )
        @test all(
            every_wavespeed .+ horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), HorizontalDirection()),
            ),
        )
        @test all(
            every_wavespeed .+ vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), VerticalDirection()),
            ),
        )
    end

    # Check pulling acoustic model but as two pieces
    @testset "horizontal and vertical acoustic" begin
        rem_dg = remainder_DGModel(
            dg,
            (hacoustic_dg, vacoustic_dg);
            numerical_flux_first_order = (
                dg.numerical_flux_first_order,
                (
                    hacoustic_dg.numerical_flux_first_order,
                    vacoustic_dg.numerical_flux_first_order,
                ),
            ),
        )
        rem_dg(split_tendency, Q, nothing, 0; increment = false)
        vacoustic_dg(split_tendency, Q, nothing, 0; increment = true)
        hacoustic_dg(split_tendency, Q, nothing, 0; increment = true)
        A = Array(full_tendency.data)
        B = Array(split_tendency.data)
        # Test that we have a fully discrete splitting
        @test all(isapprox.(
            A,
            B,
            rtol = sqrt(eps(FT)),
            atol = 10 * sqrt(eps(FT)),
        ))

        # Test that wavespeeds are split by direction
        every_wavespeed = full_wavespeed
        horz_wavespeed = -acoustic_wavespeed
        vert_wavespeed = -acoustic_wavespeed
        @test all(
            every_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(),),
            ),
        )
        @test all(
            horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (HorizontalDirection(),),
            ),
        )
        @test all(
            vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (VerticalDirection(),),
            ),
        )
        @test all(
            every_wavespeed .+ horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), HorizontalDirection()),
            ),
        )
        @test all(
            every_wavespeed .+ vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), VerticalDirection()),
            ),
        )
    end

    # Check pulling horizontal acoustic model
    @testset "horizontal acoustic" begin
        rem_dg = remainder_DGModel(
            dg,
            (hacoustic_dg,);
            numerical_flux_first_order = (
                dg.numerical_flux_first_order,
                (hacoustic_dg.numerical_flux_first_order,),
            ),
        )
        rem_dg(split_tendency, Q, nothing, 0; increment = false)
        hacoustic_dg(split_tendency, Q, nothing, 0; increment = true)
        A = Array(full_tendency.data)
        B = Array(split_tendency.data)
        # Test that we have a fully discrete splitting
        @test all(isapprox.(
            A,
            B,
            rtol = sqrt(eps(FT)),
            atol = 10 * sqrt(eps(FT)),
        ))

        # Test that wavespeeds are split by direction
        every_wavespeed = full_wavespeed
        horz_wavespeed = -acoustic_wavespeed
        vert_wavespeed = -zero(eltype(FT))
        @test all(
            every_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(),),
            ),
        )
        @test all(
            horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (HorizontalDirection(),),
            ),
        )
        @test all(
            vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (VerticalDirection(),),
            ),
        )
        @test all(
            every_wavespeed .+ horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), HorizontalDirection()),
            ),
        )
        @test all(
            every_wavespeed .+ vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), VerticalDirection()),
            ),
        )
    end

    # Check pulling vertical acoustic model
    @testset "vertical acoustic" begin
        rem_dg = remainder_DGModel(
            dg,
            (vacoustic_dg,);
            numerical_flux_first_order = (
                dg.numerical_flux_first_order,
                (vacoustic_dg.numerical_flux_first_order,),
            ),
        )
        rem_dg(split_tendency, Q, nothing, 0; increment = false)
        vacoustic_dg(split_tendency, Q, nothing, 0; increment = true)
        A = Array(full_tendency.data)
        B = Array(split_tendency.data)
        # Test that we have a fully discrete splitting
        @test all(isapprox.(
            A,
            B,
            rtol = sqrt(eps(FT)),
            atol = 10 * sqrt(eps(FT)),
        ))

        # Test that wavespeeds are split by direction
        every_wavespeed = full_wavespeed
        horz_wavespeed = -zero(eltype(FT))
        vert_wavespeed = -acoustic_wavespeed
        @test all(
            every_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(),),
            ),
        )
        @test all(
            horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (HorizontalDirection(),),
            ),
        )
        @test all(
            vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (VerticalDirection(),),
            ),
        )
        @test all(
            every_wavespeed .+ horz_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), HorizontalDirection()),
            ),
        )
        @test all(
            every_wavespeed .+ vert_wavespeed .≈ wavespeed(
                rem_dg.balance_law,
                nM,
                state_prognostic,
                state_auxiliary,
                FT(0),
                (EveryDirection(), VerticalDirection()),
            ),
        )
    end
end

Base.@kwdef struct RemainderTestSetup{FT}
    domain_height::FT = 10e3
    T_ref::FT = 300
end

function (setup::RemainderTestSetup)(problem, bl, state, aux, localgeo, t)
    FT = eltype(state)

    # Vary around the reference state by 10% and a random velocity field
    state.ρ = (4 + rand(FT)) / 5 + aux.ref_state.ρ
    state.ρu = 2 * (@SVector rand(FT, 3)) .- 1
    state.energy.ρe = (4 + rand(FT)) / 5 + aux.ref_state.ρe

    nothing
end

main()


text:
#!/usr/bin/env julia

include("Collatz.jl")

module CollatzTest

    using Base.Test
    import Collatz
    using Collatz: collatz

    @testset "Collatz.Iter" begin
        @testset "should return iterator" begin
            iter = @inferred collatz(4)
            @test isa(iter, Collatz.Iter)
            @test iter.value == 4
        end

    end

    @testset "collatz tests" begin
        @testset "should be iterable" begin
            @test [n for n in collatz(5)] == [5, 16, 8, 4, 2, 1]
        end

        @testset "should fail on zero" begin
            @test_throws InexactError collatz(0)
        end

        @testset "should fail on negative integer" begin
            @test_throws InexactError collatz(-1)
        end

        @testset "should fail on non integer" begin
            @test_throws MethodError collatz(1.0)
        end
    end
end

max_stars_repo_name: cacilhas/misc

max_issues_repo_name: cacilhas/misc

max_forks_repo_name: cacilhas/misc


text:
module RemoteObjects

using Distributed, UUIDs, InteractiveUtils, Sockets, Serialization

export RemoteObject, mimic, @remote

const DEFAULT_WORKER = Ref(2)
const LOCALS = Dict{UUID,Any}()
const FINALIZER_QUEUE = Channel{Tuple{Int,UUID}}(Inf)

mutable struct RemoteObject{T}
    rtype::Type{T}
    uuid::UUID
    id::Int
end
# FIXME: Allow specifying worker id
function RemoteObject(::Type{T}, #=id::Int,=# x...; kwargs...) where T
    id = DEFAULT_WORKER[]
    uuid = remotecall_fetch(init_object, id, T, x...; kwargs...)
    robj = RemoteObject(T, uuid, id)
    finalizer(robj) do _
        put!(FINALIZER_QUEUE, (id, uuid))
    end
    return robj
end

include("remoteserver.jl")

function init_object(::Type{T}, x...; kwargs...) where T
    uuid = uuid4()
    object = T(x...; kwargs...)
    LOCALS[uuid] = object
    return uuid
end

finalize_object(uuid::UUID) = delete!(LOCALS, uuid)

macro remote(ex)
    remotecall_fetch(remote, DEFAULT_WORKER[], ex)
end
function remote(ex)
    obj = Main.eval(ex)
    uuid = uuid4()
    LOCALS[uuid] = obj
    return RemoteObject(typeof(obj), uuid, myid())
end
function remote(f, x...)
    obj = f(x...)
    uuid = uuid4()
    LOCALS[uuid] = obj
    return RemoteObject(typeof(obj), uuid, myid())
end

function Base.fetch(robj::RemoteObject)
    if robj.id > 0
        return remotecall_fetch(RemoteObjects._unwrap, robj.id, robj.uuid)
    else
        conn = CONNS[-robj.id]
        serialize(conn.conn, (cmd=:get, data=robj.uuid))
        blob = deserialize(conn.conn)
        return blob.result
    end
end
_unwrap(robj::RemoteObject) = _unwrap(robj.uuid)
_unwrap(uuid::UUID) = LOCALS[uuid]

### Mimicry

"""
    mimic(::Type{T}) where T

Reads all methods defined on T, and defines those for RemoteObject{T} such that
they call the original method on the target object remotely. If the `force`
kwarg is `true`, then a failure to mimic a method will throw an error.
"""
function mimic(::Type{T}; force=false, debug=false) where T
    for method in methodswith(T)
        try
            debug && @show method
            f = method.sig.parameters[1]
            mod = method.module
            name = Symbol(string(f.instance))
            syms = Symbol.(split(method.slot_syms, '\0')[2:end-1])
            params = method.sig.parameters[2:end]
            args = [Expr(:(::), syms[idx], x===T ? RemoteObject : x) for (idx,x) in enumerate(params)]
            # FIXME: Support kwargs
            cargs = [x===T ? :(RemoteObjects._unwrap($(syms[idx]))) : syms[idx] for (idx,x) in enumerate(params)]
            if myid() == 1
                # FIXME: Support RemoteServer
                ex = :($mod.$name($(args...)) = remotecall_fetch($(f.instance), $(DEFAULT_WORKER[]), $(syms...)))
            else
                ex = :($mod.$name($(args...)) = RemoteObjects.remote($(f.instance), $(cargs...)))
            end
            debug && @show ex
            Main.eval(ex)
            debug && @info "Mimicked $method"
        catch err
            if force
                println("Error during mimic($T):")
                rethrow(err)
            else
                debug && @warn "Failed to mimic $method"
            end
        end
    end
end

### Convenience methods

struct RemoteIO <: IO
    chan::RemoteChannel
end
RemoteIO(id::Int) =
    RemoteIO(RemoteChannel(()->Channel(typemax(Int)), id))
Base.write(rio::RemoteIO, x::UInt8) = (put!(rio.chan, x); 1)
Base.take!(rio::RemoteIO) = take!(rio.chan)
Base.isready(rio::RemoteIO) = isready(rio.chan)

function Base.show(io::IO, r::RemoteObject)
    if r.id > 0
        if myid() == 1
            rio = RemoteIO(r.id)
            remotecall_wait(Base.show, r.id, rio, r)
            # TODO: This is pretty inefficient, instead send whole strings
            buf = UInt8[]
            while isready(rio)
                push!(buf, take!(rio))
            end
            print(io, String(buf))
        else
            println(io, "RemoteObject (worker $(myid())):")
            try
                Base.show(io, _unwrap(r))
            catch err
                print(io, "Error during show")
                # FIXME: Send error too
            end
        end
    else
        conn = CONNS[-r.id]
        serialize(conn.conn, (cmd=:show, data=r.uuid))
        println(io, "RemoteObject (conn $(conn.host):$(conn.port)):")
        print(io, deserialize(conn.conn).result)
    end
end

function __init__()
    @async begin
        while true
            id, uuid = take!(FINALIZER_QUEUE)
            try
                if id > 0
                    # Distributed worker
                    id in workers() || continue
                    remotecall_fetch(finalize_object, id, uuid)
                else
                    # RemoteServer
                    conn = CONNS[-id]
                    serialize(conn.conn, (cmd=:finalize, data=uuid))
                    result = deserialize(conn.conn)
                end
            catch err
                #@warn "Failed to finalize RemoteObject on $id: $uuid"
                showerror(stderr, err, catch_backtrace())
            end
        end
    end
end

end # module


text:
# MFCC

function mfcc(x::StridedVector{Cdouble}, order=13, samplerate=16000;
              α::Float64=0.97,
              eps::Float64=1.0,
              windowlen::Int=length(x),
              framelen::Int=length(x),
              numfilterbunks::Int=20,
              cepslift::Int=22,
              usedft::Bool=true,
              usehamming::Bool=true,
              czero::Bool=false,
              power::Bool=false)
    if order+1 > numfilterbunks
        throw(ArgumentError("order+1 must be less than or equal to the number of filterbanks"))
    end

    # order of MFCC + 0-th + power
    cc = zeros(order+2)

    ccall((:mfcc, libSPTK), Void,
          (Ptr{Cdouble}, Ptr{Cdouble}, Cdouble, Cdouble, Cdouble,
           Cint, Cint, Cint, Cint, Cint, Bool, Bool),
          x, cc, samplerate, α, eps,
          windowlen, framelen, order+1, numfilterbunks, cepslift,
          usedft, usehamming)

    # after ccall we get
    # mfcc[0], mfcc[1], mfcc[2], ... mfcc[m-1], E(C0), Power

    if !czero && power
        cc[endof(cc)-1] = cc[endof(cc)]
    end

    if !power
        cc = cc[1:endof(cc)-1]
    end

    if !czero
        cc = cc[1:endof(cc)-1]
    end

    cc
end


text:
### A Pluto.jl notebook ###
# v0.12.20

using Markdown
using InteractiveUtils

# ╔═╡ 7c7e9c40-6805-11eb-1016-4d344df3bf4b
begin
  using Test
  using BenchmarkTools

  using PlutoUI
end

# ╔═╡ ed2b997a-680a-11eb-1ab6-ab8d60e5c570
md"""
### Exploration

Feb 2021
"""

# ╔═╡ 9dd99a26-6804-11eb-0ed2-f919ade51b5d
md"""
Given the triangle of consecutive odd numbers:
```sh
                1
             3      5
           7     9     11
        13    15    17    19
     21    23    25    27     29
  31    33    35    37    39      41
...
```

Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:

```
row_sum_odd_numbers(1) # 1
row_sum_odd_numbers(2) # 3 + 5 = 8
```

Can we build this triangle?

 - n = 1, [1]
 - n = 2, [3, 5]                [n+1, n+3] n is even
 - n = 3, [7, 9, 11]            [n+4, n+6, n+8] n is odd
 - n = 4, [13, 15, 17, 19]      [n+9, n+11, n+13, n+15] n is even
 - n = 5, [21, 23, 25, 27, 29]  [n+16, n+18, n+20, n+22, n+24]
 - n = 6, [31, 33, 35, 37, 39, 41]
 - n = 7, [43, 45, 47, 49, 51, 53 55]

Notice the upper limit is given by: $n^2 + n-1$ which can be cheked on the follwoing (this is not a demonstration, but one can devise a recurrence)...

- $n = 1 \Rightarrow n^2 + n-1 = 1^2 + 0 = 1$
- $n = 2 \Rightarrow n^2 + n-1 = 2^2 + 1 = 5$
- $n = 3 \Rightarrow n^2 + n-1 = 3^2 + 2 = 11$
- $n = 4 \Rightarrow n^2 + n-1 = 4^2 + 3 = 19$
- $n = 5 \Rightarrow n^2 + n-1 = 5^2 + 4 = 29$
- $n = 6 \Rightarrow n^2 + n-1 = 6^2 + 5 = 41$
- $n = 7 \Rightarrow n^2 + n-1 = 7^2 + 6 = 55$
...

Also notice that the lower bound is then given by formulae: $(n-1)^2 + n-2 + 2 \equiv (n-1)^2 + n$

  - $n = 1 \Rightarrow (n-1)^2 + n = 0 + 1 = 1$
  - $n = 2 \Rightarrow (n-1)^2 + n = 1 + 2 = 3$
  - $n = 3 \Rightarrow (n-1)^2 + n = 4 + 3 = 7$
  - $n = 4 \Rightarrow (n-1)^2 + n = 9 + 4 = 13$
  - $n = 5 \Rightarrow (n-1)^2 + n = 16 + 5 = 21$
...
"""

# ╔═╡ a2253dfa-6805-11eb-14ca-a58592832cdf
"""
Calc. sequence of odd integer from (n-1)^2 + n..n^2 + (n-1)
"""
function gen_odd_seq(n::T) where T <: Integer
	T[ix for ix in (n-1)^2+n:2:n^2+(n-1)]
end

# type stable - check with @code_warntype

# ╔═╡ 78c6f476-6805-11eb-0e0c-a91004763e37
@code_warntype gen_odd_seq(2)  # check output in console...

# ╔═╡ 682aaed2-6805-11eb-1f27-3524bd18d209
begin
	a = gen_odd_seq(1)
	@test a == [1]
end

# ╔═╡ 15cba046-6806-11eb-20ba-fdf803dbb982
begin
 	a₂ = gen_odd_seq(3);
 	println(a₂)             # output console: [7, 9, 11]
end

# ╔═╡ 4d965c50-6806-11eb-11cf-63bd5e1cd90e
begin
 	a₁₀ = gen_odd_seq(10)
	@test a₁₀ == Int[91, 93, 95, 97, 99, 101, 103, 105, 107, 109]
end

# ╔═╡ e77f2c18-6809-11eb-0cd2-51ecbc12c92d
with_terminal() do
	println(length(gen_odd_seq(20)))
end

# ╔═╡ 5a2d25f8-6805-11eb-31d4-13603bb1aecb
Base.return_types(gen_odd_seq, (Int64,))

# ╔═╡ 4d2d7f7e-6805-11eb-036c-17d06e49738a
function row_sum_odd_numbers(n::T) where T <: Integer
  gen_odd_seq(n) |> ary -> sum(ary)
end

# ╔═╡ 417d8e62-6805-11eb-0543-5f35fdd51d93
begin
	@test row_sum_odd_numbers(1) == 1
	@test row_sum_odd_numbers(2) == 8
	@test row_sum_odd_numbers(42) == 74088
end

# ╔═╡ 340787ba-6805-11eb-1ca4-b3f04158a7d0
with_terminal() do
	@code_warntype row_sum_odd_numbers(5)
end

# ╔═╡ 5991b3f0-6807-11eb-1cda-a58ecc2bfe2f
md"""
## Performance
"""

# ╔═╡ 1afed860-6805-11eb-0856-2f71aa247f42
with_terminal() do
	@btime for i in 1:10_000
    	row_sum_odd_numbers(i)
	end
end

# Note: a lot of allocations!

# ╔═╡ 2424d02a-6808-11eb-345d-4b364881f4fb
# A new version more efficient ?
function row_sum_odd_numbers_2(n::T) where T <: Integer
  s = zero(eltype(n))   # pre-alloc
  for ix in (n-1)^2+n:2:n^2+(n-1)
      s += ix
  end
  s
end

# ╔═╡ 174bd250-6805-11eb-0eba-eb84d09ef7ea
with_terminal() do
	@btime for i in 1:10_000
    	row_sum_odd_numbers_2(i)
	end
end

# Note: faster, still more memory allocations!

# ╔═╡ f00c8acc-6808-11eb-038a-574e118b5025
function alloc_gen_odd_seq_sum(m::T) where T <: Integer
    ary = Vector{T}(undef, m)                        ## Allocate

    gen_fn = function (n::T) where T <: Integer      ## Populate
        for (ix, v) ∈ enumerate((n-1)^2+n:2:n^2+(n-1))
            ary[ix] = v
        end
    end

    sum_fn = function (n::T) where T <: Integer      ## Sum...
		gen_fn(n) |> ary -> sum(ary)
	end

	sum_fn
end

# ╔═╡ 100fd7d6-6805-11eb-0631-99a070466ac5
with_terminal() do
	@btime for ix in 1:10_000
    	alloc_gen_odd_seq_sum(ix)
	end
end

# ╔═╡ 9e4b2dfc-680a-11eb-26e6-299d32fbb6b0

# ╔═╡ Cell order:
# ╟─ed2b997a-680a-11eb-1ab6-ab8d60e5c570
# ╟─9dd99a26-6804-11eb-0ed2-f919ade51b5d
# ╠═7c7e9c40-6805-11eb-1016-4d344df3bf4b
# ╠═a2253dfa-6805-11eb-14ca-a58592832cdf
# ╠═78c6f476-6805-11eb-0e0c-a91004763e37
# ╠═682aaed2-6805-11eb-1f27-3524bd18d209
# ╠═15cba046-6806-11eb-20ba-fdf803dbb982
# ╠═4d965c50-6806-11eb-11cf-63bd5e1cd90e
# ╠═e77f2c18-6809-11eb-0cd2-51ecbc12c92d
# ╠═5a2d25f8-6805-11eb-31d4-13603bb1aecb
# ╠═4d2d7f7e-6805-11eb-036c-17d06e49738a
# ╠═417d8e62-6805-11eb-0543-5f35fdd51d93
# ╠═340787ba-6805-11eb-1ca4-b3f04158a7d0
# ╟─5991b3f0-6807-11eb-1cda-a58ecc2bfe2f
# ╠═1afed860-6805-11eb-0856-2f71aa247f42
# ╠═2424d02a-6808-11eb-345d-4b364881f4fb
# ╠═174bd250-6805-11eb-0eba-eb84d09ef7ea
# ╠═f00c8acc-6808-11eb-038a-574e118b5025
# ╠═100fd7d6-6805-11eb-0631-99a070466ac5
# ╠═9e4b2dfc-680a-11eb-26e6-299d32fbb6b0

max_stars_repo_name: pascal-p/julia-notebooks

max_issues_repo_name: pascal-p/julia-notebooks

max_forks_repo_name: pascal-p/julia-notebooks


text:
"""
This struct holds the market price data for each product.
    energy_price: Dictionary of zonal energy prices with hourly resolution for each scenario.
    reserveup_price: Dictionary of zonal reserve up prices with hourly resolution for each scenario.
    reservedown_price: Dictionary of zonal reserve down prices with hourly resolution for each scenario.
    capacity_price: Dictionary of annual capacity prices for each scenario.
    rec_price: Dictionary of annual REC prices for each scenario.
"""

mutable struct MarketPrices
    energy_price::Union{Nothing, Dict{String, AxisArrays.AxisArray{Float64, 3}}}
    reserveup_price::Union{Nothing, Dict{String, AxisArrays.AxisArray{Float64, 3}}}
    reservedown_price::Union{Nothing, Dict{String, AxisArrays.AxisArray{Float64, 3}}}
    capacity_price::Union{Nothing, Dict{String, AxisArrays.AxisArray{Float64, 1}}}
    rec_price::Union{Nothing, Dict{String, AxisArrays.AxisArray{Float64, 1}}}
end

function MarketPrices()
    return MarketPrices(nothing, nothing, nothing, nothing, nothing)
end

get_energy_price(prices::MarketPrices) = prices.energy_price
get_reserveup_price(prices::MarketPrices) = prices.reserveup_price
get_reservedown_price(prices::MarketPrices) = prices.reservedown_price
get_capacity_price(prices::MarketPrices) = prices.capacity_price
get_rec_price(prices::MarketPrices) = prices.rec_price

get_prices(prices::MarketPrices, prod::T) where T<: Product = nothing
get_prices(prices::MarketPrices, prod::Energy) = get_energy_price(prices)
get_prices(prices::MarketPrices, prod::OperatingReserve{ReserveUpEMIS}) = get_reserveup_price(prices)
get_prices(prices::MarketPrices, prod::OperatingReserve{ReserveDownEMIS}) = get_reservedown_price(prices)
get_prices(prices::MarketPrices, prod::Capacity) = get_capacity_price(prices)
get_prices(prices::MarketPrices, prod::REC) = get_rec_price(prices)

function set_energy_price!(prices::MarketPrices, scenario_name::String, energy_price::AxisArrays.AxisArray{Float64, 3})
    if !isnothing(prices.energy_price)
        prices.energy_price[scenario_name] = energy_price
    else
        prices.energy_price = Dict(scenario_name => energy_price)
    end
    return
end

function set_reserveup_price!(prices::MarketPrices, scenario_name::String, reserveup_price::AxisArrays.AxisArray{Float64, 3})
    if !isnothing(prices.reserveup_price)
        prices.reserveup_price[scenario_name] = reserveup_price
    else
        prices.reserveup_price = Dict(scenario_name => reserveup_price)
    end
    return
end

function set_reservedown_price!(prices::MarketPrices, scenario_name::String, reservedown_price::AxisArrays.AxisArray{Float64, 3})
    if !isnothing(prices.reservedown_price)
        prices.reservedown_price[scenario_name] = reservedown_price
    else
        prices.reservedown_price = Dict(scenario_name => reservedown_price)
    end
    return
end

function set_capacity_price!(prices::MarketPrices, scenario_name::String, capacity_price::AxisArrays.AxisArray{Float64, 1})
    if !isnothing(prices.capacity_price)
        prices.capacity_price[scenario_name] = capacity_price
    else
        prices.capacity_price = Dict(scenario_name => capacity_price)
    end
    return
end

function set_rec_price!(prices::MarketPrices, scenario_name::String, rec_price::AxisArrays.AxisArray{Float64, 1})
    if !isnothing(prices.rec_price)
        prices.rec_price[scenario_name] = rec_price
    else
        prices.rec_price = Dict(scenario_name => rec_price)
    end
    return
end


text:
## Simple utils

# Note: to avoid dynamic dispatch, many of these are coded as a single method using isa statements

function scopeof(@nospecialize(x))::Union{Method,Module}
    (isa(x, Method) || isa(x, Module)) && return x
    isa(x, FrameCode) && return x.scope
    isa(x, Frame) && return x.framecode.scope
    error("unknown scope for ", x)
end

function moduleof(@nospecialize(x))
    s = scopeof(x)
    return isa(s, Module) ? s : s.module
end

function Base.nameof(frame::Frame)
    s = frame.framecode.scope
    isa(s, Method) ? s.name : nameof(s)
end

_Typeof(x) = isa(x, Type) ? Type{x} : typeof(x)

function to_function(@nospecialize(x))
    isa(x, GlobalRef) ? getfield(x.mod, x.name) : x
end

@static if isdefined(Base, :get_world_counter)
    import Base: get_world_counter
else
    get_world_counter() = ccall(:jl_get_world_counter, UInt, ())
end

"""
    method = whichtt(tt)

Like `which` except it operates on the complete tuple-type `tt`.
"""
function whichtt(@nospecialize(tt))
    # TODO: provide explicit control over world age? In case we ever need to call "old" methods.
    m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tt, get_world_counter())
    m === nothing && return nothing
    isa(m, Method) && return m
    return m.func::Method
end

instantiate_type_in_env(arg, spsig, spvals) =
    ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), arg, spsig, spvals)

function sparam_syms(meth::Method)
    s = Symbol[]
    sig = meth.sig
    while sig isa UnionAll
        push!(s, Symbol(sig.var.name))
        sig = sig.body
    end
    return s
end

separate_kwargs(args...; kwargs...) = (args, values(kwargs))

pc_expr(src::CodeInfo, pc) = src.code[pc]
pc_expr(framecode::FrameCode, pc) = pc_expr(framecode.src, pc)
pc_expr(frame::Frame, pc) = pc_expr(frame.framecode, pc)
pc_expr(frame::Frame) = pc_expr(frame, frame.pc)

function is_type_definition(stmt)
    if isa(stmt, Expr)
        head = stmt.head
        return head === :struct_type || head === :abstract_type || head === :primitive_type
    end
    return false
end

function find_used(code::CodeInfo)
    used = BitSet()
    stmts = code.code
    for stmt in stmts
        scan_ssa_use!(used, stmt)
        if is_type_definition(stmt)
            # these are missed by Core.Compiler.userefs, see https://github.com/JuliaLang/julia/pull/30936
            for a in stmt.args
                scan_ssa_use!(used, a)
            end
        end
    end
    return used
end

function scan_ssa_use!(used::BitSet, @nospecialize(stmt))
    if isa(stmt, SSAValue)
        push!(used, stmt.id)
    end
    iter = Core.Compiler.userefs(stmt)
    iterval = Core.Compiler.iterate(iter)
    while iterval !== nothing
        useref, state = iterval
        val = Core.Compiler.getindex(useref)
        if isa(val, SSAValue)
            push!(used, val.id)
        end
        iterval = Core.Compiler.iterate(iter, state)
    end
end

function hasarg(predicate, args)
    predicate(args) && return true
    for a in args
        predicate(a) && return true
        if isa(a, Expr)
            hasarg(predicate, a.args) && return true
        elseif isa(a, QuoteNode)
            predicate(a.value) && return true
        elseif isa(a, GlobalRef)
            predicate(a.name) && return true
        end
    end
    return false
end

function wrap_params(expr, sparams::Vector{Symbol})
    isempty(sparams) && return expr
    params = []
    for p in sparams
        hasarg(isidentical(p), expr.args) && push!(params, p)
    end
    return isempty(params) ? expr : Expr(:where, expr, params...)
end

function scopename(tn::TypeName)
    modpath = Base.fullname(tn.module)
    if isa(modpath, Tuple{Symbol})
        return Expr(:., modpath[1], QuoteNode(tn.name))
    end
    ex = Expr(:., modpath[end-1], QuoteNode(modpath[end]))
    for i = length(modpath)-2:-1:1
        ex = Expr(:., modpath[i], ex)
    end
    return Expr(:., ex, QuoteNode(tn.name))
end

## Predicates

isidentical(x) = Base.Fix2(===, x)   # recommended over isequal(::Symbol) since it cannot be invalidated

# is_goto_node(@nospecialize(node)) = isa(node, GotoNode) || isexpr(node, :gotoifnot)

if isdefined(Core, :GotoIfNot)
    is_GotoIfNot(@nospecialize(node)) = isa(node, Core.GotoIfNot)
    is_gotoifnot(@nospecialize(node)) = is_GotoIfNot(node)
else
    is_GotoIfNot(@nospecialize(node)) = false
    is_gotoifnot(@nospecialize(node)) = isexpr(node, :gotoifnot)
end

if isdefined(Core, :ReturnNode)
    is_ReturnNode(@nospecialize(node)) = isa(node, Core.ReturnNode)
    is_return(@nospecialize(node)) = is_ReturnNode(node)
    get_return_node(@nospecialize(node)) = (node::Core.ReturnNode).val
else
    is_ReturnNode(@nospecialize(node)) = false
    is_return(@nospecialize(node)) = isexpr(node, :return)
    get_return_node(@nospecialize(node)) = node.args[1]
end

is_loc_meta(@nospecialize(expr), @nospecialize(kind)) = isexpr(expr, :meta) && length(expr.args) >= 1 && expr.args[1] === kind

"""
    is_global_ref(g, mod, name)

Tests whether `g` is equal to `GlobalRef(mod, name)`.
"""
is_global_ref(@nospecialize(g), mod::Module, name::Symbol) = isa(g, GlobalRef) && g.mod === mod && g.name == name

is_quotenode(@nospecialize(q), @nospecialize(val)) = isa(q, QuoteNode) && q.value == val
is_quotenode_egal(@nospecialize(q), @nospecialize(val)) = isa(q, QuoteNode) && q.value === val

function is_quoted_type(@nospecialize(a), name::Symbol)
    if isa(a, QuoteNode)
        T = a.value
        if isa(T, UnionAll)
            T = Base.unwrap_unionall(T)
        end
        isa(T, DataType) && return T.name.name === name
    end
    return false
end

function is_function_def(@nospecialize(ex))
    (isexpr(ex, :(=)) && isexpr(ex.args[1], :call)) || isexpr(ex, :function)
end

function is_call(@nospecialize(node))
    isexpr(node, :call) ||
        (isexpr(node, :(=)) && (isexpr(node.args[2], :call)))
end

is_call_or_return(@nospecialize(node)) = is_call(node) || is_return(node)

is_dummy(bpref::BreakpointRef) = bpref.stmtidx == 0 && bpref.err === nothing

if VERSION >= v"1.4.0-DEV.304"
    function unpack_splatcall(stmt)
        if isexpr(stmt, :call) && length(stmt.args) >= 3 && is_quotenode_egal(stmt.args[1], Core._apply_iterate)
            return true, stmt.args[3]
        end
        return false, nothing
    end
else
    function unpack_splatcall(stmt)
        if isexpr(stmt, :call) && length(stmt.args) >= 2 && is_quotenode_egal(stmt.args[1], Core._apply)
            return true, stmt.args[2]
        end
        return false, nothing
    end
end

function is_bodyfunc(@nospecialize(arg))
    if isa(arg, QuoteNode)
        arg = arg.value
    end
    if isa(arg, Function)
        fname = String((typeof(arg).name::Core.TypeName).name)
        return startswith(fname, "##") && match(r"#\d+$", fname) !== nothing
    end
    return false
end

"""
Determine whether we are calling a function for which the current function
is a wrapper (either because of optional arguments or because of keyword arguments).
"""
function is_wrapper_call(@nospecialize(expr))
    isexpr(expr, :(=)) && (expr = expr.args[2])
    isexpr(expr, :call) && any(x->x==SlotNumber(1), expr.args)
end

is_generated(meth::Method) = isdefined(meth, :generator)

"""
    is_doc_expr(ex)

Test whether expression `ex` is a `@doc` expression.
"""
function is_doc_expr(@nospecialize(ex))
    docsym = Symbol("@doc")
    if isexpr(ex, :macrocall)
        ex::Expr
        a = ex.args[1]
        is_global_ref(a, Core, docsym) && return true
        isa(a, Symbol) && a == docsym && return true
        if isexpr(a, :.)
            mod, name = (a::Expr).args[1], (a::Expr).args[2]
            return mod === :Core && isa(name, QuoteNode) && name.value === docsym
        end
    end
    return false
end

is_leaf(frame::Frame) = frame.callee === nothing

function is_vararg_type(x)
    @static if isa(Vararg, Type)
        if isa(x, Type)
            (x <: Vararg && !(x <: Union{})) && return true
            if isa(x, UnionAll)
                x = Base.unwrap_unionall(x)
            end
            return isa(x, DataType) && nameof(x) == :Vararg
        end
    else
        return isa(x, typeof(Vararg))
    end
    return false
end

## Location info

# These getters improve inference since fieldtype(CodeInfo, :linetable)
# and fieldtype(CodeInfo, :codelocs) are both Any
const LineTypes = Union{LineNumberNode,Core.LineInfoNode}
function linetable(arg)
    if isa(arg, Frame)
        arg = arg.framecode
    end
    if isa(arg, FrameCode)
        arg = arg.src
    end
    return (arg::CodeInfo).linetable::Union{Vector{Core.LineInfoNode},Vector{Any}}  # issue #264
end
linetable(arg, i::Integer) = linetable(arg)[i]::Union{Expr,LineTypes}

function codelocs(arg)
    if isa(arg, Frame)
        arg = arg.framecode
    end
    if isa(arg, FrameCode)
        arg = arg.src
    end
    return (arg::CodeInfo).codelocs::Vector{Int32}
end
codelocs(arg, i::Integer) = codelocs(arg)[i]  # for consistency with linetable (but no extra benefit here)

function lineoffset(framecode::FrameCode)
    offset = 0
    scope = framecode.scope
    if isa(scope, Method)
        _, line1 = whereis(scope)
        offset = line1 - scope.line
    end
    return offset
end

function getline(ln::Union{LineTypes,Expr})
    _getline(ln::LineTypes) = ln.line
    _getline(ln::Expr)      = ln.args[1] # assuming ln.head === :line
    return Int(_getline(ln))::Int
end
# work around compiler error on 1.2
@static if v"1.2.0" <= VERSION < v"1.3"
    getfile(ln) = begin
        path = if isexpr(ln, :line)
            String(ln.args[2])
        else
            try
                file = String(ln.file)
                isfile(file)
                file
            catch err
                ""
            end
        end
        CodeTracking.maybe_fixup_stdlib_path(path)
    end
else
    function getfile(ln::Union{LineTypes,Expr})
        _getfile(ln::LineTypes) = ln.file::Symbol
        _getfile(ln::Expr)      = ln.args[2]::Symbol # assuming ln.head === :line
        return CodeTracking.maybe_fixup_stdlib_path(String(_getfile(ln)))
    end
end

function firstline(ex::Expr)
    for a in ex.args
        isa(a, LineNumberNode) && return a
        if isa(a, Expr)
            line = firstline(a)
            isa(line, LineNumberNode) && return line
        end
    end
    return nothing
end

"""
    loc = whereis(frame, pc::Int=frame.pc)

Return the file and line number for `frame` at `pc`.  If this cannot be
determined, `loc == nothing`. Otherwise `loc == (filepath, line)`.
"""
function CodeTracking.whereis(framecode::FrameCode, pc::Int)
    codeloc = codelocation(framecode.src, pc)
    codeloc == 0 && return nothing
    lineinfo = linetable(framecode, codeloc)
    m = framecode.scope
    return isa(m, Method) ? whereis(lineinfo, m) : (getfile(lineinfo), getline(lineinfo))
end
CodeTracking.whereis(frame::Frame, pc::Int=frame.pc) = whereis(frame.framecode, pc)

"""
    line = linenumber(framecode, pc)

Return the "static" line number at statement index `pc`. The static line number
is the location at the time the method was most recently defined.
See [`CodeTracking.whereis`](@ref) for dynamic line information.
"""
function linenumber(framecode::FrameCode, pc)
    codeloc = codelocation(framecode.src, pc)
    codeloc == 0 && return nothing
    return getline(linetable(framecode, codeloc))
end
linenumber(frame::Frame, pc=frame.pc) = linenumber(frame.framecode, pc)

function getfile(framecode::FrameCode, pc)
    codeloc = codelocation(framecode.src, pc)
    codeloc == 0 && return nothing
    return getfile(linetable(framecode, codeloc))
end
getfile(frame::Frame, pc=frame.pc) = getfile(frame.framecode, pc)

function codelocation(code::CodeInfo, idx::Int)
    codeloc = codelocs(code)[idx]
    while codeloc == 0 && (code.code[idx] === nothing || isexpr(code.code[idx], :meta)) && idx < length(code.code)
        idx += 1
        codeloc = codelocs(code)[idx]
    end
    return codeloc
end

function compute_corrected_linerange(method::Method)
    _, line1 = whereis(method)
    offset = line1 - method.line
    src = JuliaInterpreter.get_source(method)
    lastline = linetable(src)[end]::LineTypes
    return line1:getline(lastline) + offset
end

function method_contains_line(method::Method, line::Integer)
    # Check to see if this method really contains that line. Methods that fill in a default positional argument,
    # keyword arguments, and @generated sections may not contain the line.
    return line in compute_corrected_linerange(method)
end

function toplevel_code_contains_line(framecode::FrameCode, line::Integer)
    return getline(linetable(framecode, 1)) <= line <= getline(last(linetable(framecode)))
end

"""
    stmtidx = statementnumber(frame, line::Integer)

Return the index of the first statement in `frame`'s `CodeInfo` that corresponds to
static line number `line`.
"""
function statementnumber(framecode::FrameCode, line::Integer)
    sortby(lin) = isa(lin, Int) ? lin : getline(lin)  # for comparison to x=Int(line)

    lt = linetable(framecode)
    lineidx = searchsortedfirst(lt, Int(line); by=sortby)::Int
    1 <= lineidx <= length(lt) || throw(ArgumentError("line $line not found in $(framecode.scope)"))
    return searchsortedfirst(codelocs(framecode), lineidx)
end
statementnumber(frame::Frame, line) = statementnumber(frame.framecode, line)

"""
    framecode, stmtidx = statementnumber(method, line)

Return the index of the first statement in `framecode` that corresponds to the given
static line number `line` in `method`.
"""
function statementnumber(method::Method, line; line1=whereis(method)[2])
    linec = line - line1 + method.line  # line number at time of compilation
    framecode = get_framecode(method)
    return framecode, statementnumber(framecode, linec)
end

## Printing

function framecode_lines(src::CodeInfo)
    buf = IOBuffer()
    if isdefined(Base.IRShow, :show_ir_stmt)
        lines = String[]
        src = replace_coretypes!(copy_codeinfo(src); rev=true)
        reverse_lookup_globalref!(src.code)
        io = IOContext(buf, :displaysize => displaysize(stdout),
                       :SOURCE_SLOTNAMES => Base.sourceinfo_slotnames(src))
        used = BitSet()
        cfg = Core.Compiler.compute_basic_blocks(src.code)
        for stmt in src.code
            Core.Compiler.scan_ssa_use!(push!, used, stmt)
        end
        line_info_preprinter = Base.IRShow.lineinfo_disabled
        line_info_postprinter = Base.IRShow.default_expr_type_printer
        bb_idx = 1
        for idx = 1:length(src.code)
            bb_idx = Base.IRShow.show_ir_stmt(io, src, idx, line_info_preprinter, line_info_postprinter, used, cfg, bb_idx)
            push!(lines, chomp(String(take!(buf))))
        end
        return lines
    end
    show(buf, src)
    code = filter!(split(String(take!(buf)), '\n')) do line
        !(line == "CodeInfo(" || line == ")" || isempty(line) || occursin("within `", line))
    end
    code .= replace.(code, Ref(r"\$\(QuoteNode\((.+?)\)\)" => s"\1"))
    return code
end
framecode_lines(framecode::FrameCode) = framecode_lines(framecode.src)

breakpointchar(framecode, stmtidx) =
    isassigned(framecode.breakpoints, stmtidx) ? breakpointchar(framecode.breakpoints[stmtidx]) : ' '

function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements(framecode), kwargs...)
    iscolor = get(io, :color, false)
    ndstmt = ndigits(nstatements(framecode))
    lt = linetable(framecode)
    offset = lineoffset(framecode)
    ndline = isempty(lt) ? 0 : ndigits(getline(lt[end]) + offset)
    nullline = " "^ndline
    src = copy_codeinfo(framecode.src)
    replace_coretypes!(src; rev=true)
    code = framecode_lines(src)
    isfirst = true
    for (stmtidx, stmtline) in enumerate(code)
        stmtidx ∈ range || continue
        bpc = breakpointchar(framecode, stmtidx)
        isfirst || print(io, '\n')
        isfirst = false
        print(io, bpc, ' ')
        if iscolor
            color = stmtidx == pc ? Base.warn_color() : :normal
            printstyled(io, lpad(stmtidx, ndstmt); color=color, kwargs...)
        else
            print(io, lpad(stmtidx, ndstmt), stmtidx == pc ? '*' : ' ')
        end
        line = linenumber(framecode, stmtidx)
        print(io, ' ', line === nothing ? nullline : lpad(line, ndline), "  ", stmtline)
    end
end

"""
    local_variables = locals(frame::Frame)::Vector{Variable}

Return the local variables as a vector of [`Variable`](@ref).
"""
function locals(frame::Frame)
    vars, var_counter = Variable[], Int[]
    varlookup = Dict{Symbol,Int}()
    data, code = frame.framedata, frame.framecode
    slotnames = code.src.slotnames::SlotNamesType
    for (sym, counter, val) in zip(slotnames, data.last_reference, data.locals)
        counter == 0 && continue
        val = something(val)
        if val isa Core.Box && !isdefined(val, :contents)
            continue
        end
        var = Variable(val, sym)
        idx = get(varlookup, sym, 0)
        if idx > 0
            if counter > var_counter[idx]
                vars[idx] = var
                var_counter[idx] = counter
            end
        else
            varlookup[sym] = length(vars)+1
            push!(vars, var)
            push!(var_counter, counter)
        end
    end
    scope = code.scope
    if scope isa Method
        syms = sparam_syms(scope)
        for i in 1:length(syms)
            if isassigned(data.sparams, i)
                push!(vars, Variable(data.sparams[i], syms[i], true))
            end
        end
    end
    for var in vars
        if var.name === Symbol("#self#")
            for field in fieldnames(typeof(var.value))
                field = field::Symbol
                if isdefined(var.value, field)
                    push!(vars, Variable(getfield(var.value, field), field, false, true))
                end
            end
        end
    end
    return vars
end

function print_vars(io::IO, vars::Vector{Variable})
    for v in vars
        v.name == Symbol("#self#") && (isa(v.value, Type) || sizeof(v.value) == 0) && continue
        print(io, '\n', v)
    end
end

"""
    eval_code(frame::Frame, code::Union{String, Expr})

Evaluate `code` in the context of `frame`, updating any local variables
(including type parameters) that are reassigned in `code`, however, new local variables
cannot be introduced.

```jldoctest
julia> foo(x, y) = x + y;

julia> frame = JuliaInterpreter.enter_call(foo, 1, 3);

julia> JuliaInterpreter.eval_code(frame, "x + y")
4

julia> JuliaInterpreter.eval_code(frame, "x = 5");

julia> JuliaInterpreter.finish_and_return!(frame)
8
```

When variables are captured in closures (and thus gets wrapped in a `Core.Box`)
they will be automatically unwrapped and rewrapped upon evaluating them:

```jldoctest
julia> function capture()
           x = 1
           f = ()->(x = 2) # x captured in closure and is thus a Core.Box
           f()
           x
       end;

julia> frame = JuliaInterpreter.enter_call(capture);

julia> JuliaInterpreter.step_expr!(frame);

julia> JuliaInterpreter.step_expr!(frame);

julia> JuliaInterpreter.locals(frame)
2-element Vector{JuliaInterpreter.Variable}:
 #self# = capture
 x = Core.Box(1)

julia> JuliaInterpreter.eval_code(frame, "x")
1

julia> JuliaInterpreter.eval_code(frame, "x = 2")
2

julia> JuliaInterpreter.locals(frame)
2-element Vector{JuliaInterpreter.Variable}:
 #self# = capture
 x = Core.Box(2)
```

"Special" values like SSA values and slots (shown in lowered code as e.g. `%3` and `@_4`
respectively) can be evaluated using the syntax `var"%3"` and `var"@_4"` respectively.
"""
function eval_code end

eval_code(frame::Frame, command::AbstractString) = eval_code(frame, Base.parse_input_line(command))
function eval_code(frame::Frame, expr)
    code = frame.framecode
    data = frame.framedata
    isexpr(expr, :toplevel) && (expr = expr.args[end])

    if isexpr(expr, :toplevel)
      expr = Expr(:block, expr.args...)
    end
    # see https://github.com/JuliaLang/julia/issues/31255 for the Symbol("") check
    vars = filter(v -> v.name != Symbol(""), locals(frame))
    defined_ssa = findall(x -> x!=0, [isassigned(data.ssavalues, i) for i in 1:length(data.ssavalues)])
    defined_locals = findall(x -> x isa Some, data.locals)
    res = gensym()
    eval_expr = Expr(:let,
                     Expr(:block, map(x->Expr(:(=), x...), [(v.name, QuoteNode(v.value isa Core.Box ? v.value.contents : v.value)) for v in vars])...,
                     map(x->Expr(:(=), x...), [(Symbol("%$i"), QuoteNode(data.ssavalues[i])) for i in defined_ssa])...,
                     map(x->Expr(:(=), x...), [(Symbol("@_$i"), QuoteNode(data.locals[i].value)) for i in defined_locals])...),
        Expr(:block,
            Expr(:(=), res, expr),
            Expr(:tuple, res, Expr(:tuple, [v.name for v in vars]...))
        ))
    eval_res, res = Core.eval(moduleof(frame), eval_expr)
    j = 1
    for (i, v) in enumerate(vars)
        if v.isparam
            data.sparams[j] = res[i]
            j += 1
        elseif v.is_captured_closure
            selfidx = findfirst(v -> v.name === Symbol("#self#"), vars)
            @assert selfidx !== nothing
            self = vars[selfidx].value
            closed_over_var = getfield(self, v.name)
            if closed_over_var isa Core.Box
                setfield!(closed_over_var, :contents, res[i])
            end
            # We cannot rebind closed over variables that the frontend identified as constant
        else
            slot_indices = code.slotnamelists[v.name]
            idx = argmax(data.last_reference[slot_indices])
            slot_idx = slot_indices[idx]
            data.last_reference[slot_idx] = (frame.assignment_counter += 1)
            data.locals[slot_idx] = Some{Any}(v.value isa Core.Box ? Core.Box(res[i]) : res[i])
        end
    end
    eval_res
end

function show_stackloc(io::IO, frame)
    indent = ""
    fr = root(frame)
    shown = false
    while fr !== nothing
        print(io, indent, scopeof(fr))
        if fr === frame
            println(io, ", pc = ", frame.pc)
            shown = true
        else
            print(io, '\n')
        end
        indent *= "  "
        fr = fr.callee
    end
    if !shown
        println(io, indent, scopeof(frame), ", pc = ", frame.pc)
    end
end
show_stackloc(frame) = show_stackloc(stdout, frame)

# Printing of stacktraces and errors with Frame
function Base.StackTraces.StackFrame(frame::Frame)
    scope = scopeof(frame)
    if scope isa Method
        method = scope
        method_args = something.(frame.framedata.locals[1:method.nargs])
        atypes = Tuple{mapany(_Typeof, method_args)...}
        sig = method.sig
        sparams = Core.svec(frame.framedata.sparams...)
        mi = specialize_method(method, atypes, sparams)
        fname = frame.framecode.scope.name
    else
        mi = frame.framecode.src
        fname = gensym()
    end
    Base.StackFrame(
        fname,
        Symbol(getfile(frame)),
        @something(linenumber(frame), getline(linetable(frame, 1))),
        mi,
        false,
        false,
        C_NULL
    )
end

function Base.show_backtrace(io::IO, frame::Frame)
    stackframes = Tuple{Base.StackTraces.StackFrame, Int}[]
    while frame !== nothing
        push!(stackframes, (Base.StackTraces.StackFrame(frame), 1))
        frame = JuliaInterpreter.caller(frame)
    end
    print(io, "\nStacktrace:")
    try invokelatest(Base.update_stackframes_callback[], stackframes) catch end
    frame_counter = 0
    nd = ndigits(length(stackframes))
    for (i, (last_frame, n)) in enumerate(stackframes)
        frame_counter += 1
        if isdefined(Base, :print_stackframe)
            println(io)
            Base.print_stackframe(io, i, last_frame, n, nd, Base.info_color())
        else
            Base.show_trace_entry(IOContext(io, :backtrace => true), last_frame, n, prefix = string(" [", frame_counter, "] "))
        end
    end
end

function Base.display_error(io::IO, er, frame::Frame)
    printstyled(io, "ERROR: "; bold=true, color=Base.error_color())
    showerror(IOContext(io, :limit => true), er, frame)
    println(io)
end

function static_eval(ex)
    try
        eval(ex)
    catch
        nothing
    end
end


text:
export segy_write

function segy_write(file::String, block::SeisBlock)

    # Open buffer for writing
    s = open(file, "w")

    # Write FileHeader
    write_fileheader(s, block.fileheader)

    # Write Data
    ns,ntraces = size(block.data)
    for t in 1:ntraces
        write_trace(s, block, t)
    end

    close(s)
end


text:
@testset "postgresql" begin
    dsn = ODBC.DSN("PgSQL-test")

    @testset "basic queries" begin
        dbs = DataFrame(ODBC.Query(dsn, "SELECT datname FROM pg_database WHERE datistemplate = false;"))
        data = DataFrame(ODBC.Query(dsn, "SELECT table_schema, table_name FROM information_schema.tables ORDER BY table_schema,table_name;"))
    end

    @testset "test1" begin
        ODBC.execute!(dsn, "drop table if exists test1")
        ODBC.execute!(dsn, "create table test1
                            (test_bigint bigint,
                             test_decimal decimal,
                             test_int integer,
                             test_numeric numeric,
                             test_smallint smallint,
                             test_float real,
                             test_real double precision,
                             test_money money,
                             test_date date,
                             test_timestamp timestamp,
                             test_time time,
                             test_char char(1),
                             test_varchar varchar(16),
                             test_bytea bytea,
                             test_boolean boolean,
                             test_text text,
                             test_array integer[]
                            )")
        data = DataFrame(ODBC.Query(dsn, "select * from information_schema.tables where table_name = 'test1'"))
        println("Postgres table 'test1' schema:")
        println()
        ODBC.execute!(dsn, "insert into test1 VALUES
                            (1, -- bigint,
                             1.2, -- decimal,
                             2, -- integer,
                             1.4, -- numeric,
                             3, -- smallint,
                             1.6, -- real,
                             1.8, -- double precision,
                             2.0, -- money,
                             '2016-01-01', -- date,
                             '2016-01-01 01:01:01', -- timestamp,
                             '01:01:01', -- time,
                             'A', -- char(1),
                             'hey there sailor', -- varchar(16),
                             NULL, -- bytea,
                             TRUE, -- boolean,
                             'hey there abraham', -- text,
                             ARRAY[1, 2, 3] -- integer array
                            )")
        data = DataFrame(ODBC.Query(dsn, "select * from test1"))
        @test size(data) == (1,17)
        @test Tables.schema(data).types == (
            Union{Int64, Missing},
            Union{DecFP.Dec64, Missing},
            Union{Int32, Missing},
            Union{DecFP.Dec64, Missing},
            Union{Int16, Missing},
            Union{Float32, Missing},
            Union{Float64, Missing},
            Union{Float64, Missing},
            Union{ODBC.API.SQLDate, Missing},
            Union{ODBC.API.SQLTimestamp, Missing},
            Union{ODBC.API.SQLTime, Missing},
            Union{String, Missing},
            Union{String, Missing},
            Union{Array{UInt8,1}, Missing},
            Union{String, Missing},
            Union{String, Missing},
            Union{String, Missing},
        )
        println("Postgres table 'test1':")
        show(data)
        println()

        ODBC.execute!(dsn, "drop table if exists test1")
    end

    ODBC.disconnect!(dsn)
end


text:
# include the functions of the module
using LinearAlgebra

include("simula01.jl")
include("mac.jl")
include("modalparam1.jl")
include("modalparami.jl")

max_stars_repo_name: javiercara/ModalParam

max_issues_repo_name: javiercara/ModalParam

max_forks_repo_name: javiercara/ModalParam


text:
@testset "unit tests" begin
    @testset "projection" begin
        x0 = Line(Point(0, 10), O)
        p = Point(10, 20)
        @test projection(p, x0) == Point(0, 20)

        y0 = Line(Point(10, 0), O)
        @test projection(p, y0) == Point(10, 0)
    end

    @testset "translation" begin
        video = Video(500, 500)
        # dummy action doesn't need a real function
        action = Action(1:100, () -> 1, Translation(Point(1, 1), Point(100, 100)))
        # needs internal translation as well
        push!(action.internal_transitions, Javis.InternalTranslation(O))
        Javis.compute_transformation!(action, video, 1)
        @test action.internal_transitions[1].by == Point(1, 1)
        Javis.compute_transformation!(action, video, 50)
        @test action.internal_transitions[1].by == Point(50, 50)
        Javis.compute_transformation!(action, video, 100)
        @test action.internal_transitions[1].by == Point(100, 100)
    end

    @testset "scaling" begin
        video = Video(500, 500)
        # dummy action doesn't need a real function
        action = Action(0:100, () -> 1, Scaling(0.0, 1.0))
        # needs internal scaling as well
        push!(action.internal_transitions, Javis.InternalScaling((0, 0)))
        Javis.compute_transformation!(action, video, 0)
        @test action.internal_transitions[1].scale == (0.0, 0.0)
        Javis.compute_transformation!(action, video, 50)
        @test action.internal_transitions[1].scale == (0.5, 0.5)
        Javis.compute_transformation!(action, video, 100)
        @test action.internal_transitions[1].scale == (1.0, 1.0)
    end

    @testset "Relative frames" begin
        video = Video(500, 500)
        action = Action(Rel(10), (args...) -> 1, Translation(Point(1, 1), Point(100, 100)))
        # dummy action doesn't need a real function
        test_file = javis(
            video,
            [
                Action(1:100, (args...) -> 1, Translation(Point(1, 1), Point(100, 100))),
                action,
            ],
        )
        @test Javis.get_frames(action) == 101:110
        rm(test_file)
    end

    @testset "translation from origin" begin
        video = Video(500, 500)
        # dummy action doesn't need a real function
        action = Action(1:100, () -> 1, Translation(Point(99, 99)))
        # needs internal translation as well
        push!(action.internal_transitions, Javis.InternalTranslation(O))

        Javis.compute_transformation!(action, video, 1)
        @test action.internal_transitions[1].by == O
        Javis.compute_transformation!(action, video, 50)
        @test action.internal_transitions[1].by == Point(49, 49)
        Javis.compute_transformation!(action, video, 100)
        @test action.internal_transitions[1].by == Point(99, 99)

        video = Video(500, 500)
        # dummy action doesn't need a real function
        action = Action(1:100, () -> 1, Translation(99, 99))
        # needs internal translation as well
        push!(action.internal_transitions, Javis.InternalTranslation(O))

        Javis.compute_transformation!(action, video, 1)
        @test action.internal_transitions[1].by == O
        Javis.compute_transformation!(action, video, 50)
        @test action.internal_transitions[1].by == Point(49, 49)
        Javis.compute_transformation!(action, video, 100)
        @test action.internal_transitions[1].by == Point(99, 99)
    end

    @testset "rotations" begin
        video = Video(500, 500)
        # dummy action doesn't need a real function
        action = Action(1:100, () -> 1, Rotation(2π))
        # needs internal translation as well
        push!(action.internal_transitions, Javis.InternalRotation(0.0, O))

        Javis.compute_transformation!(action, video, 1)
        @test action.internal_transitions[1].angle == 0.0
        Javis.compute_transformation!(action, video, 100)
        @test action.internal_transitions[1].angle == 2π

        video = Video(500, 500)
        # dummy action doesn't need a real function
        action = Action(1:100, () -> 1, Rotation(2π, Point(2.0, 5.0)))
        # needs internal translation as well
        push!(action.internal_transitions, Javis.InternalRotation(0.0, O))

        Javis.compute_transformation!(action, video, 1)
        @test action.internal_transitions[1].angle == 0.0
        @test action.internal_transitions[1].center == Point(2.0, 5.0)
        Javis.compute_transformation!(action, video, 100)
        @test action.internal_transitions[1].angle == 2π
        @test action.internal_transitions[1].center == Point(2.0, 5.0)
    end

    @testset "Frames errors" begin
        video = Video(500, 500)
        # throws because the frames of the first action need to be defined explicitly
        @test_throws ArgumentError javis(
            video,
            [Action((args...) -> 1, Translation(Point(1, 1), Point(100, 100)))],
        )
        # throws because the frames of the first action need to be defined explicitly
        @test_throws ArgumentError javis(
            video,
            [Action(Rel(10), (args...) -> 1, Translation(Point(1, 1), Point(100, 100)))],
        )
        # throws because :some is not supported as Symbol for `frames`
        @test_throws ArgumentError javis(
            video,
            [
                Action(1:100, (args...) -> 1, Translation(Point(1, 1), Point(100, 100))),
                Action(
                    :some,
                    :id,
                    (args...) -> 1,
                    Translation(Point(1, 1), Point(100, 100)),
                ),
            ],
        )
    end

    @testset "Unspecified symbol error" begin
        video = Video(500, 500)
        # throws because the frames of the first action need to be defined explicitly
        @test_throws ErrorException javis(
            video,
            [
                Action(1:100, (args...) -> 1),
                Action(1:100, (args...) -> line(O, pos(:non_existent), :stroke)),
            ],
        )

        video = Video(500, 500)
        # throws because the frames of the first action need to be defined explicitly
        @test_throws ErrorException javis(
            video,
            [
                Action(1:100, (args...) -> 1),
                Action(1:100, (args...) -> line(O, ang(:non_existent), :stroke)),
            ],
        )
    end

    @testset "Frame computation" begin

        actions = [
            BackgroundAction(1:50, (args...) -> 1),
            Action(:atom, (args...) -> 1, subactions = [SubAction(Scaling(1, 2))]),
        ]
        demo = Video(500, 500)
        javis(demo, actions; pathname = "")
        @test Javis.get_frames(actions[1]) == 1:50
        @test Javis.get_frames(actions[2]) == 1:50
        @test Javis.get_frames(actions[2].subactions[1]) == 1:50

        actions = [
            BackgroundAction(1:50, (args...) -> 1),
            Action(:atom, (args...) -> 1, subactions = [SubAction((args...) -> 1)]),
        ]
        demo = Video(500, 500)
        javis(demo, actions; pathname = "")
        @test Javis.get_frames(actions[1]) == 1:50
        @test Javis.get_frames(actions[2]) == 1:50
        @test Javis.get_frames(actions[2].subactions[1]) == 1:50

        actions = [
            BackgroundAction(1:50, (args...) -> 1),
            Action(
                Rel(-19:0),
                :atom,
                (args...) -> 1,
                subactions = [
                    SubAction(1:10, Scaling(1, 2)),
                    SubAction(Rel(10), Scaling(1, 2)),
                ],
            ),
        ]
        demo = Video(500, 500)
        javis(demo, actions; pathname = "")
        @test Javis.get_frames(actions[1]) == 1:50
        @test Javis.get_frames(actions[2]) == 31:50
        @test Javis.get_frames(actions[2].subactions[1]) == 1:10
        @test Javis.get_frames(actions[2].subactions[2]) == 11:20
    end
end


text:
module Faust

export DSPBlock, compile, init!, compute!, setparams!

include("llvm-c-dsp.jl")

FaustFloat = Union{Float32, Float64}

mutable struct DSPBlock{T <: FaustFloat}
    factory::Ptr{llvm_dsp_factory}
    dsp::Ptr{llvm_dsp}
    ui::UIGlue
    block_size::Int
    samplerate::Int
    inputs::Matrix{T}
    outputs::Matrix{T}
    function DSPBlock(factory, floattype)
        d = new{floattype}(factory, C_NULL)
        function f(d)
            if d.dsp != C_NULL
                deleteCDSPInstance(d.dsp)
            end
            if d.factory != C_NULL
                deleteCDSPFactory(d.factory)
            end
        end
        finalizer(f, d)
    end
end

"""
    compile(code; name="score", argv=[], target="", opt=-1)

Compiles `code` to a `DSPBlock`.

# Arguments
- `argv::Vector{String}`: List of args to the Faust compiler, e.g.
    "-double": double precision
    "-vec": vectorize code.
- `target::String`: target for which to build LLVM IR. Defaults to current machine.
- `opt::Integer`: -1 is "highest level available".

# Examples
```julia-repl
julia> d = compile("import(\"stdfaust.lib\"); process = os.osc(freq) : *(0.25) <: _, _;")
```
"""
function compile(code; name="score", argv=[], target="", opt=-1)
    factory = createCDSPFactoryFromString(name, code, argv, target, opt)
    floattype = "-double" in argv ? Float64 : Float32
    DSPBlock(factory, floattype)
end

"""
    init!(d; block_size=256, samplerate=44100)

Initializes the DSPBlock `d` for use.

Must be called before `compute!`. The old DSP instance will be deleted,
so this can be called repeatedly and will reset internal states, etc.
"""
function init!(d::DSPBlock{T}; block_size=256, samplerate=44100) where T <: FaustFloat
    if d.dsp != C_NULL
        deleteCDSPInstance(d.dsp)
    end

    d.block_size = block_size
    d.samplerate = samplerate

    d.dsp = createCDSPInstance(d.factory)
    initCDSPInstance(d.dsp, d.samplerate)
    d.ui = UIGlue()
    buildUserInterfaceCDSPInstance(d.dsp, d.ui)
    input_channels = getNumInputsCDSPInstance(d.dsp)
    output_channels = getNumOutputsCDSPInstance(d.dsp)
    d.inputs = zeros(T, block_size, input_channels)
    d.outputs = zeros(T, block_size, output_channels)
    d
end

"""
    compute!(d)

Computes `d.block_size` samples of signal and returns `d.outputs` (d.block_size, n_outputs).

`d.inputs` should be assigned an incoming signals matrix of dims (d.block_size, n_inputs)
before calling this function.

# Examples
```julia-repl
julia> d = init!(compile("import(\"stdfaust.lib\"); process = os.oscs(440);"));
julia> compute!(d)
256×1 Matrix{Float32}:
1.0
0.99607
0.9882256
0.9764974
0.96093166
0.9415895
0.9185469
⋮
-0.99841714
-1.0004897
-0.9986304
-0.99284655
-0.98316085
-0.96961135
-0.9522513
```
"""
function compute!(d::DSPBlock{T}) where T <: FaustFloat
    computeCDSPInstance(d.dsp, d.block_size, d.inputs, d.outputs)
end

"""
    setparams!(d, params)

Sets the parameters on `d` using keys from `params`.

One can extract the available params as UIRange structs from `d.ui.ranges`
after iniialization.

# Examples
```julia-repl
julia> d = init!(compile("process = nentry(\"v\", 0, 0, 1, 0.001);"))
julia> d.ui.ranges
Dict{String, Faust.UIRange} with 1 entry:
  "/score/v" => UIRange(0.0, 0.0, 1.0, 0.001)
julia> setparams!(d, Dict("/score/v" => 0.5f0))
```
"""
function setparams!(d::DSPBlock{T}, params) where T <: FaustFloat
    for (k, v) in params
        unsafe_store!(d.ui.paths[k], v)
    end
end

end


text:
"""
```
binarize!(UnimodalRosin(), img)
```

Binarizes the unimodal image passed into the `img` parameter into background (`Gray(0)`)
pixels, and foreground (`Gray(1)`) pixels using Rosin's algorithm.

# Arguments

## `img`
An `AbstractGray` image which is to be binarized into background (`Gray(0)`)
and foreground (`Gray(1)`) pixels.

# Output
Modifies the `img` parameter to become the binarized image.

# Details
This algorithm first selects the bin in the histogram with the highest frequency.
The algorithm then searches from the location of the maximum bin to the last bin
of the histogram for the first bin with a frequency of 0 (known as the minimum bin.).
A line is then drawn that passes through both the maximum and minimum bins. The
bin with the greatest orthogonal distance to the line is chosen as the threshold
value.

## Assumptions
This algorithm assumes that:

* The histogram is unimodal
* There is always at least one bin that has a frequency of 0. If not, the
algorithm will use the last bin as the minimum bin.
* If the histogram includes multiple bins with a frequency of 0, the algorithm
will select the first zero bin as its minimum.
* If there are multiple bins with the greatest orthogonal distance, the leftmost
bin is selected as the threshold.

# Example

Compute the threshold for the "moonsurface" image in the TestImages package.
```julia

using ImageBinarization

img = testimage("moonsurface")
binarize!(UnimodalRosin(),img)
```

# Reference
[1] P. L. Rosin, “Unimodal thresholding,” Pattern Recognition, vol. 34, no. 11, pp. 2083–2096, Nov. 2001.

# See Also
"""
function binarize(algorithm::UnimodalRosin,  img::AbstractArray{T,2}) where T <: AbstractGray
  binarize!(algorithm, copy(img))
end

function binarize!(algorithm::UnimodalRosin,  img::AbstractArray{T,2}) where T <: AbstractGray
  edges, counts = build_histogram(img,  256)
  t = find_threshold(HistogramThresholding.UnimodalRosin(), counts[1:end], edges)
  map!(img,img) do val
    val < t ? Gray(0) : Gray(1)
  end
end


text:
"""
    barcode_img(pattern; img_height = 50)

Return an image of type `Matrix{Gray{Bool}}` where the number of rows is specified
by `img_height` and where the rows are filled with the `binary_pattern`. Displaying
the image reveals the barcode.

You can save the generated image via `FileIO.save`, using any format accepted by `FileIO`.
"""
function barcode_img(pattern::AbstractString; img_height = 50)
    img =
        Gray.(
            [
                fill(true, 1, length(pattern))
                repeat(reshape([c == ('0') for c in pattern], 1, :), img_height, 1)
                fill(true, 1, length(pattern))
            ],
        )
    return img
end

function barcode_positions(pattern::AbstractString)
    x = Int[]
    w = Int[]

    ind = 1

    while ind ≤ length(pattern)
        if pattern[ind] == '1'
            push!(x, ind)
            next_ind = findnext(==('0'), pattern, ind)
            push!(w, next_ind - ind)
            ind = next_ind
        else
            ind += 1
        end
    end
    return x, w
end

function barcode_widths(pattern::AbstractString)
    w = ""

    ind = findfirst(==('1'), pattern)
    while ind !== nothing
        c = pattern[ind]
        next_ind = findnext(!=(c), pattern, ind)
        next_ind !== nothing && (w *= string(next_ind - ind))
        ind = next_ind
    end
    w = w[begin:end-1] # drop the ending `11`, which is a bar with width 2
    return w
end


text:
module Generate

include("generate-types.jl")
include("string-case.jl")

end # end module Generate


text:
Float96(x::Float96) = x
Float48(x::Float48) = x

Float96(x::Float64, y::Float64) = two_sum(x, y)
Float48(x::Float24, y::Float24) = two_sum(x, y)

#=
    TwoFloat{T}(a, b) --> (a, b)

    TwoFloat( a, b )  --> two_sum(a, b)
    TwoFloat((a, b))  --> two_hilo_sum(a, b)
=#

struct TwoFloat{T} <: AbstractFloat
    hi::T
    lo::T

    function TwoFloat{T}(a::T, b::T) where {T}
        return new{T}(a,b)
    end
end

function TwoFloat(a::T, b::T) where {T}
    a, b = two_sum(a, b)
    return TwoFloat{T}(a, b)
end

function TwoFloat(ab::Tuple{T,T}) where {T}
    a, b = two_hilo_sum(a, b)
    return TwoFloat{T}(a, b)
end

@inline function two_sum(a::T, b::T) where {T}
   hi = a + b
   v  = hi - a
   lo = (a - (hi - v)) + (b - v)
   return hi, lo
end

@inline function two_hilo_sum(a::T, b::T) where {T}
   hi = a + b
   lo = b - (hi - a)
   return hi, lo
end

@inline function two_div(a::T, b::T) where {T}
    hi = a / b
    lo = fma(-hi, b, a)
    lo /= b
    return hi, lo
end

@inline function two_prod(a::T, b::T) where {T}
   hi = a * b
   lo = fma(a, b, -hi)
   hi, lo
end

Base.:(==)(x::TwoFloat{T}, y::TwoFloat{T}) where {T} =
   (x.hi === y.hi) && (x.lo === y.lo)
Base.:(!=)(x::TwoFloat{T}, y::TwoFloat{T}) where {T} =
   (x.hi !=== y.hi) || (x.lo !=== y.lo)
Base.:(<=)(x::TwoFloat{T}, y::TwoFloat{T}) where {T} =
   (x.hi < y.hi) || ((x.hi === y.hi) & (x.lo <= y.lo))
Base.:(>=)(x::TwoFloat{T}, y::TwoFloat{T}) where {T} =
   (x.hi > y.hi) || ((x.hi === y.hi) & (x.lo >= y.lo))
Base.:(<)(x::TwoFloat{T}, y::TwoFloat{T}) where {T} =
   (x.hi < y.hi) || ((x.hi === y.hi) & (x.lo < y.lo))
Base.:(>)(x::TwoFloat{T}, y::TwoFloat{T}) where {T} =
   (x.hi > y.hi) || ((x.hi === y.hi) & (x.lo > y.lo))

Base.isequal(x::TwoFloat, y::TwoFloat) =
    isequal(x.hi ,y.hi) & isequal(x.lo, y.lo)
Base.isless(x::TwoFloat, y::TwoFloat) =
    ifelse(!isequal(x.hi,y.hi), isless(x.hi,y.hi), isless(x.lo,y.lo))

Base.hash(x::TwoFloat, h::UInt) = hash(x.lo, hash(x.hi, h))
Base.eltype(x::Type{TwoFloat{T}}) where {T} = T

Base.length(x::TwoFloat{T}) where {T} = 2
Base.nfields(x::TwoFloat{T}) where {T} = 2
Base.fieldcount(::Type{TwoFloat{T}}) where {T} = 2
Base.fieldnames(::Type{TwoFloat{T}}) where {T} = (:hi, :lo)

Base.firstindex(x::TwoFloat{T}) where {T} = 1
Base.lastindex(x::TwoFloat{T})  where {T} = 2
Base.first(x::TwoFloat{T}) where {T} = x.hi
Base.last(x::TwoFloat{T})  where {T} = x.lo

Base.getindex(x::TwoFloat, i::Int) = getfield(x, i)
Base.getindex(x::TwoFloat, i::Real) = getfield(x, convert(Int, i))
Base.getindex(x::TwoFloat, i::Symbol) = getfield(x, i)

Base.iterate(x::TwoFloat{T}, iter=1) where {T} =
    iter > lastidex(x) ? nothing : (getfield(x, iter), iter + 1)
Base.indexed_iterate(x::TwoFloat{T}, i::Int, state=1) where {T} =
    (getfield(t, i), i+1)

Base.prevind(x::TwoFloat{T}, i::Integer) where{T} = Int(i)-1
Base.nextind(x::TwoFloat{T}, i::Integer) where {T} = Int(i)+1

Base.convert(::Type{TwoFloat{T}}, x::TwoFloat{T}) where {T} = x
function Base.convert(::Type{TwoFloat{T1}}, x::TwoFloat{T2}) where {T1,T2}
    TwoFloat{T1}(convert(T1, x[1]), convert(T1, x[2]))
end
Base.promote_rule(::Type{TwoFloat{T1}}, ::Type{TwoFloat{T2}) where {T1,T2} =
    TwoFloat{promote_type(T1, T2)}

"""
    refresh(a::TwoFloat)

resets the canonical form
- a = refine(a)
"""
refresh(a::TwoFloat{T}) where {T} = two_sum(a.hi, a.lo)

"""
    renorm(a::TwoFloat)

*unchecked assumption*: abs(a[1]) >= abs(a[2])
- a = renorm(a)
"""
renorm(a::TwoFloat{T}) where {T} = two_hilo_sum(a.hi, a.lo)