text:
"""
module example001()
{
    function r_from_dia(d) = d / 2;

    module rotcy(rot, r, h) {
        rotate(90, rot)
            cylinder(r = r, h = h, center = true);
    }

    difference() {
        sphere(r = r_from_dia(size));
        rotcy([0, 0, 0], cy_r, cy_h);
        rotcy([1, 0, 0], cy_r, cy_h);
        rotcy([0, 1, 0], cy_r, cy_h);
    }

    size = 50;
    hole = 25;

    cy_r = r_from_dia(hole);
    cy_h = r_from_dia(size * 2.5);
}

example001();

"""

using Descartes
using GeometryBasics: Mesh

function example001()

    r_from_dia(d) = d / 2;

    size = 50
    hole = 25

    cy_r = r_from_dia(hole)
    cy_h = r_from_dia(size * 2.5)

    function rotcy(rot, r, h)
        rotate(pi/2, rot)Cylinder(r, h, center=true)
    end

    diff(
        Sphere(r_from_dia(size)),
        rotcy([0, 0, 0], cy_r, cy_h),
        rotcy([1, 0, 0], cy_r, cy_h),
        rotcy([0, 1, 0], cy_r, cy_h))
end

m = Mesh(example001())
#save("example001.ply", m)
#Descartes.visualize(m)

ext: jl


text:
using Oceananigans
using Statistics
using Random
using UnicodePlots

function two_dimensional_turbulence(ν=1e-4; Nx=128, architecture=CPU(), advection=WENO5())
    Random.seed!(123)
    Lx = 2π

    model = NonhydrostaticModel(timestepper = :RungeKutta3,
                                architecture = architecture,
                                grid = RegularRectilinearGrid(size=(Nx, Nx), halo=(3, 3), extent=(Lx, Lx), topology=(Periodic, Periodic, Flat)),
                                advection = advection,
                                buoyancy = nothing,
                                tracers = nothing,
                                closure = IsotropicDiffusivity(ν=ν))

    u, v, w = model.velocities
    uᵢ = rand(size(u)...)
    vᵢ = rand(size(v)...)

    uᵢ .-= mean(uᵢ)
    vᵢ .-= mean(vᵢ)

    set!(model, u=uᵢ, v=vᵢ)

    progress(sim) = @info "(ν = $ν) iteration: $(sim.model.clock.iteration), time: $(round(Int, sim.model.clock.time))"

    simulation = Simulation(model, Δt=0.1, stop_time=30, iteration_interval=50, progress=progress)

    run!(simulation)

    return Array(interior(model.velocities.u))[:, :, 1]
end

u_reference = two_dimensional_turbulence()

fig = heatmap(u_reference)

display(fig)

viscosities = [1e-5, 2e-5, 5e-5, 8e-5, 9e-5, 1.1e-5, 1.2e-4, 2e-4, 5e-4, 1e-3]
errors = zeros(0)

for ν in viscosities
    u = two_dimensional_turbulence(ν)

    error = norm(u - u_reference) / norm(u_reference)

    push!(errors, error)
end

fig = scatterplot(viscosities, errors)

display(fig)


text:
# TODO: test evaluation

using Weave.Mustache
using Weave: parse_inlines, InlineText, InlineCode

@testset "`parse_inlines` basic" begin

@test filter(parse_inlines("text")) do chunk
    chunk isa InlineCode
end |> isempty

@test filter(parse_inlines("text")) do chunk
    chunk isa InlineText &&
    chunk.content == "text"
end |> length === 1

@test filter(parse_inlines("`j code`")) do chunk
    chunk isa InlineCode &&
    chunk.ctype === :inline &&
    chunk.content == "code"
end |> length == 1

@test filter(parse_inlines("! code")) do chunk
    chunk isa InlineCode &&
    chunk.ctype === :line &&
    chunk.content == "code"
end |> length == 1

@test filter(parse_inlines("text ! maybe_intended_to_be_code")) do chunk # invalid inline chunk
    chunk isa InlineText &&
    chunk.content == "maybe_intended_to_be_code"
end |> isempty

end

@testset "`parse_inlines` multiple lines" begin

str = """
- item1
- `j code`
- item2
"""
chunks = parse_inlines(str)

let chunk = chunks[1]
    @test chunk isa InlineText
    @test occursin("- item1", chunk.content)
end

let chunk = chunks[2]
    @test chunk isa InlineCode
    @test occursin("code", chunk.content)
end

let chunk = chunks[3]
    @test chunk isa InlineText
    @test occursin("- item2", chunk.content)
end

end

@testset "`parse_inlines` unicode handling" begin

str = """
- eng1 `j :eng1`
- eng2`j :eng2`
- 日本語1 `j :日本語1`
- 日本語2`j :日本語2`
"""
chunks = parse_inlines(str)

@test filter(chunks) do chunk
    chunk isa InlineCode &&
    chunk.number === 1 &&
    chunk.content == ":eng1"
end |> length === 1

@test filter(chunks) do chunk
    chunk isa InlineCode &&
    chunk.number === 2 &&
    chunk.content == ":eng2"
end |> length === 1

@test filter(chunks) do chunk
    chunk isa InlineCode &&
    chunk.number === 3 &&
    chunk.content == ":日本語1"
end |> length === 1

@test filter(chunks) do chunk
    chunk isa InlineCode &&
    chunk.number === 4 &&
    chunk.content == ":日本語2"
end |> length === 1

end


text:
using IfElse
using Test

x = 2
@test IfElse.ifelse(x>0,1,-1) == Core.ifelse(x>0,1,-1)


text:
import LightGraphs: tree
@testset "BFS" begin
    g5 = SimpleDiGraph(4)
    add_edge!(g5, 1, 2); add_edge!(g5, 2, 3); add_edge!(g5, 1, 3); add_edge!(g5, 3, 4)
    g6 = smallgraph(:house)

    for g in testdigraphs(g5)
        z = @inferred(bfs_tree(g, 1))
        t = bfs_parents(g, 1)
        @test t == [1, 1, 1, 3]
        @test nv(z) == 4 && ne(z) == 3 && !has_edge(z, 2, 3)
    end
    for g in testgraphs(g6)
        @test @inferred(gdistances(g, 2)) == @inferred(gdistances(g, 2; sort_alg = MergeSort)) == [1, 0, 2, 1, 2]
        @test @inferred(gdistances(g, [1, 2])) == [0, 0, 1, 1, 2]
        @test @inferred(gdistances(g, [])) == fill(typemax(eltype(g)), 5)
    end

    gx = SimpleGraph(5)
    add_edge!(gx, 1, 2); add_edge!(gx, 1, 4)
    add_edge!(gx, 2, 3); add_edge!(gx, 2, 5)
    add_edge!(gx, 3, 4)

    for g in testgraphs(gx)
        @test @inferred(is_bipartite(g))
    end

    # import LightGraphs: TreeBFSVisitorVector, bfs_tree!, tree

    function istree(parents::Vector{T}, maxdepth, n::T) where T<:Integer
        flag = true
        for i in one(T):n
            s = i
            depth = 0
            while parents[s] > 0 && parents[s] != s
                s = parents[s]
                depth += 1
                if depth > maxdepth
                    return false
                end
            end
        end
        return flag
    end

    for g in testgraphs(g6)
        n = nv(g)
        parents = bfs_parents(g, 1)
        @test length(parents) == n
        t1 = @inferred(bfs_tree(g, 1))
        t2 = tree(parents)
        @test t1 == t2
        @test is_directed(t2)
        @test typeof(t2) <: AbstractGraph
        @test ne(t2) < nv(t2)
    end

    gx = SimpleGraph(6)
    d = nv(gx)
    for (i, j) in [(1, 2), (2, 3), (2, 4), (4, 5), (3, 5)]
        add_edge!(gx, i, j)
    end
    for g in testgraphs(gx)
        @test has_path(g, 1, 5)
        @test has_path(g, 1, 2)
        @test has_path(g, 1, 5; exclude_vertices=[3])
        @test has_path(g, 1, 5; exclude_vertices=[4])
        @test !has_path(g, 1, 5; exclude_vertices=[3, 4])
        @test has_path(g, 5, 1)
        @test has_path(g, 5, 1; exclude_vertices=[3])
        @test has_path(g, 5, 1; exclude_vertices=[4])
        @test !has_path(g, 5, 1; exclude_vertices=[3, 4])

        # Edge cases
        @test !has_path(g, 1, 6)
        @test !has_path(g, 6, 1)
        @test has_path(g, 1, 1) # inseparable
        @test !has_path(g, 1, 2; exclude_vertices=[2])
        @test !has_path(g, 1, 2; exclude_vertices=[1])
    end
end


text:
abstract type MonitorActivity end

mutable struct Monitor <: MonitorActivity
    spikes::AbstractArray
    voltage::AbstractArray
    recovery::AbstractArray
end
mutable struct WeightMonitor <: MonitorActivity
    spikes::AbstractArray
    voltage::AbstractArray
    weight::AbstractArray
end

function Monitor(; record_weight=false)
    if record_weight
        return WeightMonitor([], [], [])
    else
        return Monitor([], [], [])
    end
end

function record!(monitor::Monitor, network::SpikingNetwork)
    push!(monitor.spikes, network.spikes |> copy)
    push!(monitor.voltage, network.voltage |> copy)
    if typeof(network.neurons) <: Izhikevich
        push!(monitor.recovery, network.recovery |> copy)
    end
    return
end

function record!(monitor::WeightMonitor, network::SpikingNetwork)
    push!(monitor.spikes, network.spikes |> copy)
    push!(monitor.voltage, network.voltage |> copy)
    push!(monitor.weight, network.weight |> copy)
    return
end

function reset!(monitor::Monitor)
    monitor.spikes = []
    monitor.voltage = []
    monitor.recovery = []
    return
end

function reset!(monitor::WeightMonitor)
    monitor.spikes = []
    monitor.voltage = []
    monitor.weight = []
    return
end

"""
Returns a specific field from monitor. The output shape is: (batch_size, #neurons, time)
# Examples
```julia-repl
julia> get(network, :spikes)
```
"""
function Base.get(monitor::MonitorActivity, field::Symbol)
    return convert(Array, VectorOfArray(getfield(monitor, field)))
end

function save(monitor::MonitorActivity, filename::AbstractString)
    save_object(filename, monitor)
end

function raster(monitor::MonitorActivity; batch=1)
    spikes_array = get(monitor, :spikes)
    return [(i[3], i[2]) for i in findall(spikes_array) if i[1] == batch]
end

function Base.getindex(monitor::MonitorActivity, idx::Union{UnitRange{Int},Vector{Int},Int})
    typeof(monitor)([getfield(monitor, property)[idx] for property in propertynames(monitor)]...)
end


text:
# MIT License
# Copyright (c) 2017: Xavier Gandibleux, Anthony Przybylski, Gauthier Soleilhac, and contributors.

function _varname(v::JuMP.VariableRef)
    name = JuMP.name(v)
    for (pat, sub) in [("[", "_"), ("]", ""), (",", "_")]
        name = replace(name, pat => sub)
    end
    name
end

function writeMOP(m, fname::AbstractString, genericnames = false)

    open(fname, "w") do f

        print_short = x -> Base.Grisu.print_shortest(f, x)

        print(f, "NAME   vOptModel\n")

        cstrEqualTo, cstrGreaterThan, cstrLessThan, cstrInterval = [JuMP.all_constraints(m, JuMP.GenericAffExpr{Float64,JuMP.VariableRef}, set_type)
            for set_type in (MOI.EqualTo{Float64}, MOI.GreaterThan{Float64}, MOI.LessThan{Float64}, MOI.Interval{Float64})]
        numRows = sum(length, (cstrEqualTo, cstrGreaterThan, cstrLessThan, cstrInterval))

        md = getvOptData(m)

        print(f, "OBJSENSE\n")
        if md.objSenses[1] == MOI.MIN_SENSE
            print(f, " MIN\n")
        else
            print(f, " MAX\n")
        end

        flippedObj = [sense != md.objSenses[1] for sense in md.objSenses]
        if any(flippedObj)
            @info "MOP format does not support different optimisation senses. Flipping objective coefficients."
        end

        # Objective and constraint names
        print(f, "ROWS\n")
        for i = 1:length(md.objs)
            print(f, " N  OBJ$i\n")
        end

        dictCstrIndex = Dict{JuMP.ConstraintRef, Int}()
        cstr_index = 1
        for cstrRef in cstrLessThan
            print(f, " L  CON$cstr_index\n")
            push!(dictCstrIndex, cstrRef => cstr_index)
            cstr_index += 1
        end
        for cstrRef in cstrEqualTo
            print(f, " E  CON$cstr_index\n")
            push!(dictCstrIndex, cstrRef => cstr_index)
            cstr_index += 1
        end
        for cstrRef in cstrGreaterThan
            print(f, " G  CON$cstr_index\n")
            push!(dictCstrIndex, cstrRef => cstr_index)
            cstr_index += 1
        end
        for cstrRef in cstrInterval
            print(f, " E  CON$cstr_index\n")
            push!(dictCstrIndex, cstrRef => cstr_index)
            cstr_index += 1
        end

        # Output each column
        inintegergroup = false
        print(f, "COLUMNS\n")
        for var in JuMP.all_variables(m)
            if JuMP.is_binary(var) || JuMP.is_integer(var) && !inintegergroup
                print(f, "    MARKER    'MARKER'                 'INTORG'\n")
                inintegergroup = true
            elseif !JuMP.is_binary(var) && !JuMP.is_integer(var) && inintegergroup
                print(f, "    MARKER    'MARKER'                 'INTEND'\n")
                inintegergroup = false
            end

            for set_type in (MOI.EqualTo{Float64}, MOI.GreaterThan{Float64}, MOI.LessThan{Float64}, MOI.Interval{Float64})
                for cstrRef in JuMP.all_constraints(m, JuMP.GenericAffExpr{Float64,JuMP.VariableRef}, set_type)
                    con = JuMP.constraint_object(cstrRef)
                    terms = JuMP.linear_terms(con.func)
                    for (coeff, term) in terms
                        if var == term
                            print(f, "    $(_varname(var))  CON$(dictCstrIndex[cstrRef])  ") ; print_short(coeff) ; println(f)
                        end
                    end
                end
            end

            for i = 1:length(md.objs)
                for (coeff, term) in JuMP.linear_terms(md.objs[i])
                    if var == term
                        print(f,"    $(_varname(var))  OBJ$i  ") ; print_short(flippedObj[i] ? -coeff : coeff) ; println(f)
                    end
                end
            end

        end
        if inintegergroup
            print(f, "    MARKER    'MARKER'                 'INTEND'\n")
        end

        # RHSs
        print(f, "RHS\n")

        # TODO : write objectives constant

        cstr_index = 1
        for cstrRef in cstrLessThan
            con = JuMP.constraint_object(cstrRef)
            rhs = con.set.upper
            print(f, "    RHS    CON$cstr_index    ") ; print_short(rhs) ; println(f)
            cstr_index += 1
        end
        for cstrRef in cstrEqualTo
            con = JuMP.constraint_object(cstrRef)
            rhs = con.set.value
            print(f, "    RHS    CON$cstr_index    ") ; print_short(rhs) ; println(f)
            cstr_index += 1
        end
        for cstrRef in cstrGreaterThan
            con = JuMP.constraint_object(cstrRef)
            rhs = con.set.lower
            print(f, "    RHS    CON$cstr_index    ") ; print_short(rhs) ; println(f)
            cstr_index += 1
        end
        for cstrRef in cstrInterval
            con = JuMP.constraint_object(cstrRef)
            rhs = con.set.lower
            print(f, "    RHS    CON$cstr_index    ") ; print_short(rhs) ; println(f)
            cstr_index += 1
        end

        # RANGES
        if length(cstrInterval) > 0
            print(f, "RANGES\n")
            cstr_index = numRows - length(cstrInterval)
            for cstrRef in cstrInterval
                con = JuMP.constraint_object(cstrRef)
                lb = con.set.lower
                ub = con.set.upper
                print(f, "    rhs    CON$cstr_index    ") ; print_short(ub - lb) ; println(f)
            end
        end

        # BOUNDS
        print(f, "BOUNDS\n")
        for var in JuMP.all_variables(m)
            if JuMP.is_binary(var)
                #Binary
                print(f, "  BV BOUND $(_varname(var))") ; println(f)
            elseif JuMP.is_fixed(var)
                # Fixed variable
                print(f, "  FX BOUND $(_varname(var)) ") ; print_short(JuMP.fix_value(var)) ; println(f)
            elseif JuMP.has_lower_bound(var) && JuMP.lower_bound(var) == 0 && JuMP.has_upper_bound(var) && JuMP.upper_bound(var) != Inf
                # Default lower 0, and an upper
                print(f, "  UP BOUND $(_varname(var))") ; print_short(JuMP.upper_bound(var)) ; println(f)
            elseif JuMP.has_lower_bound(var) && JuMP.lower_bound(var) == 0 && (!JuMP.has_upper_bound(var) || JuMP.upper_bound(var) == Inf)
                # Default bounds.
                print(f, "  PL BOUND $(_varname(var))")
                println(f)
            elseif (!JuMP.has_lower_bound(var) || JuMP.lower_bound(var) == -Inf) && (!JuMP.has_upper_bound(var) || JuMP.upper_bound(var) == Inf)
                # Free
                print(f, "  FR BOUND $(_varname(var))\n")
            elseif JuMP.has_lower_bound(var) && JuMP.lower_bound(var) != -Inf && (!JuMP.has_upper_bound(var) || JuMP.upper_bound(var) == +Inf)
                # No upper, but a lower
                print(f, "  PL BOUND $(_varname(var))\n")
                print(f, "  LO BOUND $(_varname(var))") ; print_short(JuMP.lower_bound(var)) ; println(f)
            elseif (!JuMP.has_lower_bound(var) || JuMP.lower_bound(var) == -Inf) && JuMP.has_upper_bound(var) && JuMP.upper_bound(var) != +Inf
                # No lower, but a upper
                print(f, "  MI BOUND $(_varname(var))\n")
                print(f, "  UP BOUND $(_varname(var)) ") ; print_short(JuMP.upper_bound(var)) ; println(f)
            else
                # Lower and upper
                print(f, "  LO BOUND $(_varname(var)) ") ; print_short(JuMP.lower_bound(var)) ; println(f)
                print(f, "  UP BOUND $(_varname(var)) ") ; print_short(JuMP.upper_bound(var)) ; println(f)
            end
        end

        print(f, "ENDATA\n")
    end
    nothing
end

function parseMOP(fname::AbstractString, optimizer_factory = nothing)

    m = vModel(optimizer_factory) ; JuMP.set_silent(m)
    nextline = (f) -> split(chomp(readline(f)), ' ', keepempty = false)

    open(fname) do f
        ln = nextline(f)
        while ln[1] != "NAME"
            ln = nextline(f)
        end

        objSense = MOI.MIN_SENSE
        ln = nextline(f)
        if ln[1] == "OBJSENSE"
            ln = nextline(f)
            if ln[1] == "MAXIMIZE" || ln[1] == "MAX"
                objSense = MOI.MAX_SENSE
            end
            ln = nextline(f)
        end

        if ln[1] == "ROWS"
            ln = nextline(f)
            dictExpr = Dict{String,Tuple{JuMP.GenericAffExpr,Symbol}}()
            objOrder = Vector{String}()
            while ln[1] != "COLUMNS"
                push!(dictExpr, ln[2] => (JuMP.AffExpr(), Symbol(ln[1])))
                ln[1] == "N" && push!(objOrder, ln[2])
                ln = nextline(f)
            end
        end

        if ln[1] == "COLUMNS"
            ln = nextline(f)
            dictVar = Dict{String,JuMP.VariableRef}()
            isInt = false
            while ln[1] != "RHS"
                if ln[3] == "'INTORG'"
                    isInt = true
                elseif ln[3] == "'INTEND'"
                    isInt = false
                else
                    if !(ln[1] in keys(dictVar))
                        v = JuMP.@variable(m, integer = isInt, base_name = String(ln[1]), lower_bound = 0.0)
                        push!(dictVar, ln[1] => v)
                    end
                    expr, expr_type = dictExpr[ln[2]]
                    var = dictVar[ln[1]]
                    coeff = parse(Float64, ln[3])

                    dictExpr[ln[2]] = (expr + coeff * var, expr_type)
                end
                ln = nextline(f)
            end
        end

        dictObj = Dict{String,JuMP.GenericAffExpr}()
        for (k, (expr, expr_type)) in dictExpr
            if expr_type == :N
                push!(dictObj, k => expr)
            end
        end
        filter!(p->p |> last |> last != :N, dictExpr)

        md = m.ext[:vOpt]
        for key in objOrder
            push!(md.objs, dictObj[key])
            push!(md.objSenses, objSense)
        end

        # TODO : read objectives constant
        dictRHS = Dict{String,Float64}()
        if ln[1] == "RHS"
            ln = nextline(f)
            while length(ln) > 1
                cstr_name = ln[2]
                rhs = parse(Float64, ln[3])
                # cstr_name == "nonS@800" && error()
                push!(dictRHS, cstr_name => rhs)
                ln = nextline(f)
            end
        end

        if ln[1] == "RANGES"
            ln = nextline(f)
            while length(ln) > 1
                cstr_name = ln[2]
                expr, constraint_type = dictExpr[cstr_name]
                rhs = dictRHS[cstr_name]
                r = parse(Float64, ln[3])
                if constraint_type == :G
                    JuMP.@constraint(m, rhs <= expr <= rhs + abs(r))
                elseif constraint_type == :L
                    JuMP.@constraint(m, rhs - abs(r) <= expr <= rhs)
                else
                    if r >= 0
                        JuMP.@constraint(m, rhs <= expr <= rhs + r)
                    else
                        JuMP.@constraint(m, rhs + r <= expr <= rhs)
                    end
                end
                delete!(dictExpr, cstr_name)
                delete!(dictRHS, cstr_name)
                ln = nextline(f)
            end
        end

        # add all constraints that aren't range constraints
        for (cstr_name, rhs) in dictRHS
            expr, constraint_type = dictExpr[cstr_name]
            if constraint_type == :E
                JuMP.@constraint(m, expr == rhs)
            elseif constraint_type == :G
                JuMP.@constraint(m, expr >= rhs)
            elseif constraint_type == :L
                JuMP.@constraint(m, expr <= rhs)
            end
            delete!(dictExpr, cstr_name)
        end

        undeclared_variables = String[]
        if ln[1] == "BOUNDS"
            ln = nextline(f)
            while length(ln) > 1
                boundType, varName = ln[1], ln[3]
                val = length(ln) > 3 ? parse(Float64, ln[4]) : 0.
                if haskey(dictVar, varName)
                    var = dictVar[varName]
                    if boundType == "LO"
                        JuMP.set_lower_bound(var, val)
                    elseif boundType == "UP"
                        JuMP.set_upper_bound(var, val)
                    elseif boundType == "FX"
                        JuMP.fix(var, val)
                    elseif boundType == "FR"
                        JuMP.set_upper_bound(var, Inf)
                        JuMP.set_lower_bound(var, -Inf)
                    elseif boundType == "MI"
                        JuMP.set_lower_bound(var, -Inf)
                    elseif boundType == "PL"
                        JuMP.set_upper_bound(var, Inf)
                    elseif boundType == "BV"
                        JuMP.is_integer(var) && JuMP.unset_integer(var)
                        JuMP.set_binary(var)
                    elseif boundType == "LI"
                        JuMP.set_lower_bound(var, val)
                    elseif boundType == "UI"
                        JuMP.set_upper_bound(var, val)
                    elseif boundType == "SC"
                        error("Semi-continuous variables are not supported by vOptGeneric")
                    else
                        error("Unrecognised bound type : $boundType")
                    end
                else
                    push!(undeclared_variables, varName)
                end
                ln = nextline(f)
            end
        end
        isempty(undeclared_variables) || @warn "Some variables were declared in BOUNDS but were never used, they were not added to the model" variables = undeclared_variables
        isempty(dictExpr) || @warn "Some constraints are missing a RHS and were not added to the model" constraints = keys(dictExpr) |> collect
    end

    return m
end

max_stars_repo_name: vOptSolver/vOptGeneric

max_issues_repo_name: vOptSolver/vOptGeneric

max_forks_repo_name: vOptSolver/vOptGeneric


text:
"""
    stopping_time(criterion, losses; verbosity=0)
    stopping_time(criterion, losses, is_training; verbosity=0)

Determine the stopping time for the iterator `losses`, given
`stopping::StoppingCriterion`. Include the `Bool` vector `is_training`
of matching length, when there is a distinction between
"out-of-sample" losses and "training" losses.

If losses completes before a stop, then `0` is returned.

```
julia> stopping_time(NotANumber(), [10.0, 3.0, NaN, 4.0])
3

julia> stopping_time(NotANumber(), [10.0, 3.0, 5.0, 4.0])
0
```
"""
function stopping_time(criterion::EarlyStopper, losses, training; verbosity=0)

    t = 0 # counts regular `update` calls but ignores `update_training` calls
    for (loss, training) in zip(losses, training)
        if !training
            t += 1  # Increment count of out-of-sample updates
        end

        # Update criterion state
        is_done = done!(criterion, loss; training = training)

        if verbosity > 0
            @info "loss updates: $t"
            @info "state: $(criterion.state)"
        end
        is_done && return t
    end

    # No stopping
    return 0
end

# If training is not provided -> Assume always out-of-sample
stopping_time(criterion, losses; kwargs...) =
    stopping_time(criterion, losses, Iterators.repeated(false); kwargs...)

stopping_time(c::StoppingCriterion, args...; kwargs...) =
    stopping_time(EarlyStopper(c), args...; kwargs...)


text:
export moddims, joinArrays

immutable Modify <: AFImpl
    moddims::Ptr{Void}
    join::Ptr{Void}
    join_many::Ptr{Void}

    function Modify(ptr)
        new(
            Libdl.dlsym(ptr, :af_moddims),
            Libdl.dlsym(ptr, :af_join),
            Libdl.dlsym(ptr, :af_join_many)
        )
    end
end

function moddims(arr::AFArray, dims::DimT...)
    verifyAccess(arr)
    af = arr.af
    ptr = af.results.ptr
    dims2 = collectDims(af.results.dims, dims)
    err = ccall(af.modify.moddims,
        Cint, (Ptr{Ptr{Void}}, Ptr{Void}, DimT, Ptr{DimT}),
        ptr, arr.ptr, length(dims2), pointer(dims2))
    assertErr(err)
    array(af, ptr[])
end

@generated function joinArrays{B}(dim::Int, arrays::AFArray{B}...)
    len = length(arrays)
    if len == 1
        :( arrays[1] )
    elseif len == 2
        quote
            arr1 = arrays[1]
            arr2 = arrays[2]
            verifyAccess(arr1)
            verifyAccess(arr2)
            af = arr1.af
            ptr = af.results.ptr
            err = ccall(af.modify.join,
                Cint, (Ptr{Ptr{Void}}, Int32, Ptr{Void}, Ptr{Void}),
                ptr, dim, arr1.ptr, arr2.ptr)
            assertErr(err)
            array(af, ptr[])
        end
    else
        quote
            af = arrays[1].af
			len, arrPtrs = collectArrayPointers(af.results.pointers, arrays)
            ptr = af.results.ptr
            err = ccall(af.modify.join_many,
                Cint, (Ptr{Ptr{Void}}, Int32, UInt32, Ptr{Ptr{Void}}),
                ptr, dim, len, pointer(arrPtrs))
            assertErr(err)
            array(af, ptr[])
        end
    end
end

max_stars_repo_name: unbornchikken/julia-ml-proto

max_issues_repo_name: unbornchikken/julia-ml-proto

max_forks_repo_name: unbornchikken/julia-ml-proto


text:
module ColorBlendModes

using FixedPointNumbers
using ColorTypes

import Base: parse

export blend, keyword

include("blendmodes.jl")
include("compositeoperations.jl")

using .BlendModes
using .CompositeOperations

# re-export
for name in names(ColorBlendModes.BlendModes)
    @eval export $name
end
for name in names(ColorBlendModes.CompositeOperations)
    @eval export $name
end

include("types.jl")
include("traits.jl")
include("parse.jl")
include("operations.jl")

end # module


text:
# MIT License
#
# Copyright (c) 2020 Joshua E Gentry

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# =========================================================================================
"""
    struct GitHubProject
        owner::String
        package::String
        branch::String
        basedir::String
    end

This structure holds details about a GitHub project we will be downloading information
from.

__Values:__

| Name    | Description
| :------ | :----------
| owner   | The owner of the project.
| package | The package to look in.
| branch  | The branch to use.
| basedir | The directory in the package to look for the files in.
"""
struct GitHubProject
    owner::String
    package::String
    branch::String
    basedir::String
end

# =========================================================================================
"""
    gh_url(
        gh::GitHubProject
    )::String

Build the URL to retrieve the contents of the project form GitHub.

__Arguments:__

| T | Name | Default | Description
|:--| :--- | :------ | :----------
| R | gh   |         | The project to get the URL for.
"""
function gh_url(
    gh::GitHubProject
        )::String
    local url = "$GITHUB_CONTENTS_BASE/$(gh.owner)/$(gh.package)/contents"

    if isempty(gh.basedir)
        url = string(url, "?ref=$(gh.branch)")
    else
        url = string(url , "/$(gh.basedir)?ref=$(gh.branch)")
    end

    return url
end

# =========================================================================================
"""
    gh_contents(
        gh::GitHubProject
    )::Union{AbstractDict, AbstractArray}

Get the contents of the directory on GitHub.

__Arguments:__

| T | Name | Default | Description
|:--| :--- | :------ | :----------
| R | gh   |         | The project to get the contents of.

__Exceptions:__

| Name         | Reason
| :----------- | :-----
| NetworkError | There was an issue downloading the JSON object.
"""
function gh_contents(
            gh::GitHubProject
        )::Union{AbstractDict, AbstractArray}
    local url = gh_url(gh)
    return download_json(url)
end


text:
function FieldStepNormalizer(arg0::jdouble, arg1::FieldODEFixedStepHandler)
    return FieldStepNormalizer((jdouble, FieldODEFixedStepHandler), arg0, arg1)
end

function FieldStepNormalizer(arg0::jdouble, arg1::FieldODEFixedStepHandler, arg2::StepNormalizerBounds)
    return FieldStepNormalizer((jdouble, FieldODEFixedStepHandler, StepNormalizerBounds), arg0, arg1, arg2)
end

function FieldStepNormalizer(arg0::jdouble, arg1::FieldODEFixedStepHandler, arg2::StepNormalizerMode)
    return FieldStepNormalizer((jdouble, FieldODEFixedStepHandler, StepNormalizerMode), arg0, arg1, arg2)
end

function FieldStepNormalizer(arg0::jdouble, arg1::FieldODEFixedStepHandler, arg2::StepNormalizerMode, arg3::StepNormalizerBounds)
    return FieldStepNormalizer((jdouble, FieldODEFixedStepHandler, StepNormalizerMode, StepNormalizerBounds), arg0, arg1, arg2, arg3)
end

function handle_step(obj::FieldStepNormalizer, arg0::FieldODEStateInterpolator, arg1::jboolean)
    return jcall(obj, "handleStep", void, (FieldODEStateInterpolator, jboolean), arg0, arg1)
end

function init(obj::FieldStepNormalizer, arg0::FieldODEStateAndDerivative, arg1::RealFieldElement)
    return jcall(obj, "init", void, (FieldODEStateAndDerivative, RealFieldElement), arg0, arg1)
end


text:
for (func, elty) in [(:CLBlastSgbmv, Float32), (:CLBlastDgbmv, Float64),
                     (:CLBlastCgbmv, ComplexF32), (:CLBlastZgbmv, ComplexF64)]
    #TODO: (:CLBlastHgbmv, Float16)

    @eval function $func(layout::CLBlastLayout, a_transpose::CLBlastTranspose,
                         m::Integer, n::Integer, kl::Integer, ku::Integer,
                         alpha::$elty,
                         a_buffer::cl.CL_mem, a_offset::Integer, a_ld::Integer,
                         x_buffer::cl.CL_mem, x_offset::Integer, x_inc::Integer,
                         beta::$elty,
                         y_buffer::cl.CL_mem, y_offset::Integer, y_inc::Integer,
                         queue::cl.CmdQueue, event::cl.Event)
        err = ccall(
            ($(string(func)), libCLBlast),
            cl.CL_int,
            (Cint, Cint, Csize_t, Csize_t, Csize_t, Csize_t, $elty, Ptr{Cvoid}, Csize_t, Csize_t,
              Ptr{Cvoid}, Csize_t, Csize_t, $elty, Ptr{Cvoid}, Csize_t, Csize_t, Ptr{Cvoid}, Ptr{Cvoid}),
            Cint(layout), Cint(a_transpose), m, n, kl, ku, alpha, a_buffer, a_offset, a_ld,
              x_buffer, x_offset, x_inc, beta, y_buffer, y_offset, y_inc, Ref(queue), Ref(event)
        )
        if err != cl.CL_SUCCESS
            println(stderr, "Calling function $(string($func)) failed!")
            throw(CLBlastError(err))
        end
        return err
    end

    @eval function gbmv!(tA::Char, m::Integer, kl::Integer, ku::Integer, α::Number,
                         A::cl.CLArray{$elty,2}, x::cl.CLArray{$elty},
                         β::Number, y::cl.CLArray{$elty};
                         queue::cl.CmdQueue=cl.queue(y))
        # check and convert arguments
        if tA == 'N'
            a_transpose = CLBlastTransposeNo
        elseif tA == 'T' || (tA == 'C' && $elty <: Real)
            a_transpose = CLBlastTransposeYes
        elseif tA == 'C' && $elty <: Complex
            a_transpose = CLBlastTransposeConjugate
        else
            throw(ArgumentError("Transpose marker `tA` is $(tA) but only 'N', 'T', and 'C' are allowed."))
        end
        alpha = convert($elty, α)
        beta  = convert($elty, β)
        layout = CLBlastLayoutColMajor

        # output event
        event::cl.Event = cl.Event(C_NULL)

        $func(layout, a_transpose,
              m, size(A,2), kl, ku,
              alpha,
              pointer(A), 0, size(A,1),
              pointer(x), 0, 1,
              beta,
              pointer(y), 0, 1,
              queue, event)

        # wait for kernel
        cl.wait(event)

        y
    end

end


text:
"""
    AbstractFitFunction{T, ND, NP}

Abstract type for an `ND`-dimensional fit of eltype `T` with `NP` parameters.
"""
abstract type AbstractFitFunction{T, ND, NP} end

"""
    mutable struct FitFunction{T, ND, NP} <: AbstractFitFunction{T, ND, NP}

T: Precision type

ND: Dimensionality

NP: NP parameters

Fields:
- `model::Function`: Function of the fit model.
- `fitranges::NTuple{N, Vector{T}}`: Range on which the fit is performed.
- `parameter_names::Vector{Symbol}`: Parameters names.
- `fitted_parameters::Vector{T}`: Fitted parameters.
- `initial_parameters::Vector{T}`: Initial parameters.

"""
mutable struct FitFunction{T, ND, NP} <: AbstractFitFunction{T, ND, NP}
    model::Function
    fitranges::NTuple{ND, AbstractVector{T}}
    parameter_names::AbstractVector{Symbol}
    fitted_parameters::AbstractVector{T}
    initial_parameters::AbstractVector{T}
    parameter_bounds::AbstractVector{<:Interval}
    bin_widths::Vector{T}
    bin_centers::Vector{T}
    residuals::Vector{T}
    Χ²::T
    backend_result::Any

    function FitFunction{T}(model::Function, ndims::Int, nparams::Int) where {T <: AbstractFloat}
        fitranges::NTuple{ndims, Vector{T}} = NTuple{ndims, Vector{T}}( [-Inf, Inf] for idim in 1:ndims)
        parameter_names::Vector{Symbol} = [Symbol("par$(ipar)") for ipar in 1:nparams]
        fitted_parameters::Vector{T} = [ T(NaN) for ipar in 1:nparams]
        initial_parameters::Vector{T} = [ T(NaN) for ipar in 1:nparams]
        parameter_bounds = [ T(nextfloat(typemin(T))/2)..T(prevfloat(typemax(T))/2) for ipar in 1:nparams]
        return new{T, ndims, nparams}(model, fitranges, parameter_names, fitted_parameters, initial_parameters, parameter_bounds, T[], T[], T[], T(NaN), missing)
    end
end

function Base.getproperty(f::FitFunction, s::Symbol)
    if s === :Chi2 || s === :chi2
        return f.Χ²
    else
        return getfield(f, s)
    end
end

get_ndims(ff::AbstractFitFunction{T, ND}) where {T <: AbstractFloat, ND} = ND
get_nparams(ff::AbstractFitFunction{T, ND, NP}) where {T <: AbstractFloat, ND, NP} = NP
get_pricision_type(ff::AbstractFitFunction{T}) where {T <: AbstractFloat} = T

function get_fit_backend_result(f::AbstractFitFunction)
    return get_fit_backend_result(f.backend_result)
end
function _set_fit_backend_result!(f::AbstractFitFunction, r)
    f.backend_result = r
    nothing
end

function set_parameter_bounds!(ff::FitFunction{T}, par_bounds::Vector{<:Interval})::Nothing where {T <: AbstractFloat}
    nparams::Int = get_nparams(ff)
    @assert length(par_bounds) == nparams "Wrong number of parameter bounds."
    for i in 1:nparams
        ff.parameter_bounds[i] = par_bounds[i]
    end
end
function set_parameter_bounds!(ff::FitFunction{T}, par_bounds::NamedTuple)::Nothing where {T <: AbstractFloat}
    nparams::Int = get_nparams(ff)
    @assert length(par_bounds) == nparams "Wrong number of parameter bounds."
    for i in 1:nparams
        ff.parameter_bounds[i] = par_bounds[i]
    end
end

function set_fitranges!(ff::AbstractFitFunction{T, N}, fitranges::NTuple{N, NTuple{2, <:Real}})::Nothing where {T <: AbstractFloat, N}
     for idim in 1:N
        ff.fitranges[idim][:] = T.([ fitranges[idim][1], fitranges[idim][2] ])
    end
    nothing
end
function set_fitranges!(ff::AbstractFitFunction{T, N}, fitranges::NTuple{N, AbstractVector{<:Real}})::Nothing where {T <: AbstractFloat, N}
    for idim in 1:N
        @assert length(fitranges[idim]) == 2 "All vectors in `fitranges` must have length 2. But in dimension $(idim) it is $(length(fitranges[idim])) ($(fitranges[idim]))."
        ff.fitranges[idim][:] = T.([ first(fitranges[idim]), last(fitranges[idim]) ])
    end
    nothing
end
function set_parameter_names!(ff::FitFunction{T}, parameter_names::Vector{String})::Nothing where {T <: AbstractFloat}
    ff.parameter_names[:] = [Symbol(name) for name in parameter_names]
    nothing
end
function set_initial_parameters!(ff::FitFunction{T}, initial_parameters::NamedTuple)::Nothing where {T <: AbstractFloat}
    ff.parameter_names[:] = collect(keys(initial_parameters))
    ff.initial_parameters[:] = collect(T, initial_parameters)
    nothing
end
function set_initial_parameters!(ff::FitFunction{T}, initial_parameters::AbstractVector{<:Real})::Nothing where {T <: AbstractFloat}
    ff.initial_parameters[:] = collect(T, initial_parameters)
    nothing
end
function _set_fitted_parameters!(ff::FitFunction{T}, fitted_parameters::AbstractVector{<:Real})::Nothing where {T <: AbstractFloat}
    ff.fitted_parameters[:] = T.(fitted_parameters)
    nothing
end
function _set_fitted_parameters!(ff::FitFunction{T}, fitted_parameters::NamedTuple)::Nothing where {T <: AbstractFloat}
    ff.fitted_parameters[:] = collect(T, fitted_parameters)
    nothing
end

function get_fitted_parameters(ff::FitFunction{T, ND, NP}) where {T <: AbstractFloat, ND, NP}
    return NamedTuple{Tuple(ff.parameter_names), NTuple{NP, T}}( ff.fitted_parameters )
end
function get_initial_parameters(ff::FitFunction{T, ND, NP}) where {T <: AbstractFloat, ND, NP}
    return NamedTuple{Tuple(ff.parameter_names), NTuple{NP, T}}( ff.initial_parameters )
end

function println(io::IO, f::FitFunction)
    println(io, "Model: ", f.model)
    println(io, "  fit ranges: ", f.fitranges)
    println(io, "  Parameters: value (initial value)")
    for i in eachindex(f.parameter_names)
        println("    ", f.parameter_names[i], ": ", f.fitted_parameters[i], " (", f.initial_parameters[i],")" )
    end
end
function print(io::IO, f::FitFunction)
    println(io, f)
end
function show(io::IO, f::FitFunction)
    println(io, f)
end
function show(io::IO, ::MIME"text/plain", f::FitFunction)
    println(io, f)
end
function show(io::IO, ::MIME"text/html", f::FitFunction)
    println(io, f)
end

function _set_bin_widths!(f::FitFunction, bin_widths::Vector{T})::Nothing where T <: Real
    f.bin_widths = bin_widths
    nothing
end

function _set_bin_centers!(f::FitFunction, bin_centers::Vector{T})::Nothing where T <: Real
    f.bin_centers = bin_centers
    nothing
end

function _get_Χ²(residuals::Array{T,1}, inv_σi²::Array{T,1}, dof::Int)::T where T <: Real
    x::T = 0.0
    residuals_sq = residuals .* residuals
    for i in 1:length(residuals_sq)
        val = residuals_sq[i] * inv_σi²[i]
        (!isnan(val) && !isinf(val)) ? x += val : x+= residuals_sq[i]
    end
    x / dof
end

function _set_Χ²!(f::FitFunction, weights::Vector{T}; idcs::Vector{Int}=collect(eachindex(weights)))::Nothing where T <: Real
    f.Χ² = _get_Χ²(f.residuals[idcs], weights[idcs], length(weights[idcs]) - length(f.fitted_parameters) ) # weights are 1/(σ_i)^2
    nothing
end

function _set_Χ²!(f::FitFunction; idcs::Vector{Int} = collect(eachindex(f.bin_centers)))::Nothing where T <: Real
    f.Χ² = _get_Χ²(f.residuals[idcs], inv.(f.model(f.bin_centers, f.fitted_parameters) .* (isempty(f.bin_widths) ? 1.0 : f.bin_widths)), length(f.bin_centers[idcs]) - length(f.fitted_parameters) ) # weights are 1/(σ_i)^2
    nothing
end

function _get_residuals(f::FitFunction, xdata::Vector{T}, ydata::Vector{T})::Vector{T} where T <: Real
    return  (f.model(xdata, f.fitted_parameters) .* (isempty(f.bin_widths) ? 1.0 : f.bin_widths) .- ydata)
end

function _set_residuals!(f::FitFunction, xdata::Vector{T}, ydata::Vector{T})::Nothing where T <: Real
    f.residuals = _get_residuals(f, xdata, ydata)
    nothing
end

get_standard_deviations(f::FitFunction) = _get_standard_deviations(f, f.backend_result)

_get_standard_deviations(f::FitFunction, fr::Missing) = error("No fit performed yet.")

@recipe function f(ff::FitFunction{T}, h::Union{Missing, Histogram} = missing; npoints = 501, use_initial_parameters = false) where {T}
    x = collect(range(ff.fitranges[1][1], stop=ff.fitranges[1][2], length=npoints))
    par = use_initial_parameters ? ff.initial_parameters : ff.fitted_parameters
    y = if ismissing(h) && isempty(ff.bin_widths)
        ff.model(x, collect(par))
    elseif ismissing(h)
        ff.model(x, collect(par)) .*  map(xe -> ff.bin_widths[findmin(abs.(ff.bin_centers .- xe))[2]], x)
    else
        bin_width_weights::Vector{T} = map(xe -> StatsBase.binvolume(h, StatsBase.binindex(h, xe)), x)
        ff.model(x, collect(par)) .* bin_width_weights
    end
    linecolor --> (use_initial_parameters ? :green : :red)
    label --> (use_initial_parameters ? "Fit model with initial parameters" : "Fit model with fitted parameters")
    x,y
end


text:
import Random

struct VariableIndex
    value::Int64
end

struct ConstraintIndex
    value::Int64
end

const CI = ConstraintIndex
const VI = VariableIndex

function chooseNbVar(L::Vector{Float64})
    x::Float64 = rand()

    if x < L[1]
        return 2
    elseif x+L[1] < L[2]
        return 3
    else
        return 4
    end
end

# Idée comme structure de donnée : comme données en entrée !

function generate(nbrVar::Int64, nbrConst::Int64)
    c::Dict{VI, Int64} = Dict( VI(ind) => Random.rand(1:28) for ind in 1:nbrVar)
    # Mbis::Array{Int64, 2} = zeros(Int, nbrConst, nbrVar)
    # Mtris::Dict{VI, Dict{VI, Int64}} = Dict(VI(var) => Dict(VI(varBis) => 0 for varBis = 1:nbrVar) for var = 1:nbrVar)

    M::Dict{CI, Vector{VI}} = Dict()

    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # La complexité de ca !
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    # listOccur::Dict{VI, Dict{VI, Int64}} = Dict(VI(var) => Dict(VI(varBis) => 0 for varBis = 1:nbrVar) for var = 1:nbrVar)

    listOccur::Dict{VI, Dict{VI, Int64}} = Dict()
    listLiaison::Dict{VI, Vector{VI}} = Dict()

    occurVar::Dict{VI, Int64} = Dict(VI(var) => 0 for var = 1:nbrVar)

    listProba::Vector{Float64} = [0.75, 0.20, 0.05]

    for ind in 1:nbrConst
        varConst::Int64 = chooseNbVar(listProba)
        ListTirage = []
        for _ in 1:varConst
            var = rand(1:nbrVar)
            while var in ListTirage
                var = rand(1:nbrVar)
            end
            push!(ListTirage, var)
            # Mbis[ind, var] = 1
        end
        # println(ListTirage)
        for var1 in VI.(ListTirage)
            occurVar[var1] += 1
            for var2 in VI.(ListTirage)
                if var1 != var2
                    if !haskey(listOccur, var1)
                        push!(listOccur, var1 => Dict())
                        push!(listLiaison, var1 => [var1])
                    end
                    if !haskey(listOccur[var1], var2)
                        push!(listOccur[var1], var2 => 0)
                        push!(listLiaison[var1], var2)
                    end
                    listOccur[var1][var2] += 1

                end
            end
        end

        push!(M, CI(ind) => VI.(ListTirage))
    end
    return c, M, listOccur, listLiaison, occurVar
    # for indVar = 1:nbrVar
    #     for indConst = 1:nbrConst
    #         if Mbis[indConst, indVar] == 1
    #             for indVarBis = 1:nbrVar
    #                 if Mbis[indConst, indVarBis] == 1 && indVar != indVarBis
    #                     Mtris[VI(indVar)][VI(indVarBis)]+=1
    #                 end
    #             end
    #         end
    #     end
    # end
    # return c, M, Mbis
end

function loadSPP(fname)
    f= open(fname)
    nbConst, nbVar = parse.(Int, split(readline(f)))
    c = parse.(Int, split(readline(f)))
    c = Dict(VI(ind) => c[ind] for ind=1:nbVar)

    # listOccur::Dict{VI, Dict{VI, Int64}} = Dict(var1 => Dict(var1 => 0 for var2 in VI.(1:nbVar)) for var1 in VI.(1:nbVar))
    listOccur::Dict{VI, Dict{VI, Int64}} = Dict()
    listLiaison::Dict{VI, Vector{VI}} = Dict()

    occurVar::Dict{VI, Int64} = Dict(VI(var) => 0 for var = 1:nbVar)
    M::Dict{CI, Vector{VI}} = Dict()

    for ind = 1:nbConst
        readline(f)

        ListTirage = parse.(Int, split(readline(f)))

        # println(ListTirage)
        for var1 in VI.(ListTirage)
            occurVar[var1] += 1
            for var2 in VI.(ListTirage)
                if var1 != var2
                    if !haskey(listOccur, var1)
                        push!(listOccur, var1 => Dict())
                        push!(listLiaison, var1 => [var1])
                    end
                    if !haskey(listOccur[var1], var2)
                        push!(listOccur[var1], var2 => 0)
                        push!(listLiaison[var1], var2)
                    end
                    listOccur[var1][var2] += 1

                end
            end
        end

        push!(M, CI(ind) => VI.(ListTirage))
    end
    return c, M, listOccur, listLiaison, occurVar
end


text:
using JuliaWebAPI

const apiclnt = APIInvoker("tcp://127.0.0.1:9999")
run_rest(apiclnt, 12000)


text:
using Documenter, SchwarzChristoffel

makedocs(
    format =:html,
    sitename = "SchwarzChristoffel.jl",
    pages = [
        "Home" => "index.md",
        "Basic Usage" => "usage.md",
        "Reference" => [
                   "polygons.md",
                   "exterior.md"
                   ]
    ],
    assets = ["assets/custom.css"],
    strict = true,
    doctest = true
)

deploydocs(
    deps = nothing,
    repo = "github.com/jdeldre/SchwarzChristoffel.jl.git",
    target = "build",
    make = nothing,
    julia = "0.6"
)


text:
struct LinearPartitioner <: AbstractPartitioner
    width::Int
    n::Int

    function LinearPartitioner(width::Int, n::Int)
        width < 0 && throw(DomainError(width, "Width must be non-negative"))
        n < 1 && throw(DomainError(n, "Partition may not be less then one"))

        new(width, n)
    end
end

function Base.iterate(itr::PartitionerIterator{LinearPartitioner,<:AbstractVector}, state=1)
    l = length(itr)
    start = (state - 1) * itr.partitioner.n + 1

    if state > l
        return nothing
    elseif state == l
        return itr.X[start:end], state + 1
    else
        return itr.X[start:start + itr.partitioner.n - 1], state + 1
    end
end

function Base.iterate(itr::PartitionerIterator{LinearPartitioner,<:AbstractMatrix}, state=1)
    l = length(itr)
    start = (state - 1) * itr.partitioner.n + 1

    if state > l
        return nothing
    elseif state == l
        return itr.X[:, start:end], state + 1
    else
        return itr.X[:, start:start + itr.partitioner.n - 1], state + 1
    end
end

max_stars_repo_name: RafaelFK/ramnet

max_issues_repo_name: RafaelFK/ramnet

max_forks_repo_name: RafaelFK/ramnet


text:
@cache struct MagnusMidpointCache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusMidpoint,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusMidpointCache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusMidpointConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusMidpoint,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusMidpointConstantCache()
end

@cache struct RKMK2Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::RKMK2,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  RKMK2Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct RKMK2ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::RKMK2,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  RKMK2ConstantCache()
end

@cache struct LieRK4Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::LieRK4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  LieRK4Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct LieRK4ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::LieRK4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  LieRK4ConstantCache()
end

@cache struct CG3Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::CG3,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  CG3Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct CG3ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::CG3,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  CG3ConstantCache()
end

@cache struct CG2Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::CG2,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  CG2Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct CG2ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::CG2,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  CG2ConstantCache()
end

@cache struct RKMK4Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::RKMK4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  RKMK4Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct RKMK4ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::RKMK4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  RKMK4ConstantCache()
end

@cache struct MagnusAdapt4Cache{uType,rateType,WType,uNoUnitsType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
  utilde::uType
  atmp::uNoUnitsType
end

function alg_cache(alg::MagnusAdapt4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  utilde = zero(u)
  atmp = similar(u,uEltypeNoUnits)
  tmp = zero(u)
  MagnusAdapt4Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k,utilde,atmp)
end

struct MagnusAdapt4ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusAdapt4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusAdapt4ConstantCache()
end

@cache struct MagnusNC8Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusNC8,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusNC8Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusNC8ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusNC8,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusNC8ConstantCache()
end

@cache struct MagnusGL4Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusGL4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusGL4Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusGL4ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusGL4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusGL4ConstantCache()
end

@cache struct MagnusGL8Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusGL8,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusGL8Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusGL8ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusGL8,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusGL8ConstantCache()
end

@cache struct MagnusNC6Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusNC6,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusNC6Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusNC6ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusNC6,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusNC6ConstantCache()
end

@cache struct MagnusGL6Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusGL6,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusGL6Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusGL6ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusGL6,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusGL6ConstantCache()
end
@cache struct MagnusGauss4Cache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusGauss4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusGauss4Cache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusGauss4ConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusGauss4,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusGauss4ConstantCache()
end

@cache struct LieEulerCache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::LieEuler,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  LieEulerCache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct LieEulerConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::LieEuler,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  LieEulerConstantCache()
end

@cache struct CayleyEulerCache{uType,rateType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  tmp::uType
  V::uType
  fsalfirst::rateType
  k::rateType
end

function alg_cache(alg::CayleyEuler,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  CayleyEulerCache(u,uprev,zero(u),zero(u),fsalfirst,k)
end

struct CayleyEulerConstantCache <: OrdinaryDiffEqConstantCache
end

alg_cache(alg::CayleyEuler,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
  ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits} = CayleyEulerConstantCache()

@cache struct MagnusLeapfrogCache{uType,rateType,WType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  uprev2::uType
  tmp::uType
  fsalfirst::rateType
  W::WType
  k::rateType
end

function alg_cache(alg::MagnusLeapfrog,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  W = false .* _vec(rate_prototype) .* _vec(rate_prototype)' # uEltype?
  k = zero(rate_prototype); fsalfirst = zero(rate_prototype)
  MagnusLeapfrogCache(u,uprev,uprev2,zero(u),fsalfirst,W,k)
end

struct MagnusLeapfrogConstantCache <: OrdinaryDiffEqConstantCache
end

function alg_cache(alg::MagnusLeapfrog,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
                   ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  MagnusLeapfrogConstantCache()
end

struct LinearExponentialConstantCache <: OrdinaryDiffEqConstantCache end

alg_cache(alg::LinearExponential,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
  ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits} = LinearExponentialConstantCache()

@cache struct LinearExponentialCache{uType,rateType,KsType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  tmp::uType
  rtmp::rateType
  KsCache::KsType # different depending on alg.krylov
end

function alg_cache(alg::LinearExponential,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},
  ::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tmp = zero(u)
  rtmp = zero(rate_prototype)
  n = length(u)
  T = eltype(u)
  m = min(alg.m, n)

  if alg.krylov == :off
    KsCache = nothing
  elseif alg.krylov == :simple
    Ks = KrylovSubspace{T}(n, m)
    expv_cache = ExpvCache{T}(m)
    KsCache = (Ks, expv_cache)
  elseif alg.krylov == :adaptive
    KsCache = _phiv_timestep_caches(u, m, 0)
  else
    throw(ArgumentError("Unknown krylov setting $(alg.krylov). Can be :off, :simple or :adaptive."))
  end
  LinearExponentialCache(u,uprev,tmp,rtmp,KsCache)
end


text:
using Test
using nctools
using Ipaper

# println(dirname(@__FILE__))
# println(pwd())

# cd(dirname(@__FILE__)) do
include("test-nc_write.jl")
include("test-nc_dims.jl")
# include("test-Ipaper.jl")

    # include("test-smooth_whit.jl")
    # include("test-smooth_SG.jl")
    # include("test_wTSM.jl")
    # include("test_whittaker.jl")
    # include("test-lambda_init.jl")
# end


text:
using ForwardDiff
import Rotations: ∇rotate, ∇composition1, ∇composition2, skew, params

@testset "$R basic tests" for R in (RodriguesParam, MRP)

    @testset "Constructors" begin
        @test R(1.0, 0.0, 0.0) isa R{Float64}
        @test R(1.0, 0, 0) isa R{Float64}
        @test R(1.0f0, 0f0, 0f0) isa R{Float32}
        @test R(1.0f0, 0, 0) isa R{Float32}
        @test R(1.0, 0f0, 0) isa R{Float64}
        @test R(1, 0, 0) isa R{Int}
        @test R{Float64}(1, 0, 0) isa R{Float64}
        @test R{Float64}(1f0, 0f0, 0f0) isa R{Float64}
        @test R{Float32}(1.0, 0, 0) isa R{Float32}
    end

    @testset "Copy constructors" begin
        g = rand(R)
        @test R{Float32}(g) isa R{Float32}
        @test R{Float64}(rand(R{Float32})) isa R{Float64}
    end

    @testset "Initializers" begin
        @test rand(R) isa R{Float64}
        @test rand(R{Float32}) isa R{Float32}
        @test one(R) isa R{Float64}
        @test one(R{Float32}) isa R{Float32}
        @test params(one(R)) === @SVector [0,0,0.]
    end

    @testset "Math operations" begin
        g = rand(R)
        @test norm(g) == norm(Matrix(g))
    end

    @testset "Jacobians" begin
        R = RodriguesParam
        g1 = rand(R)
        g2 = rand(R)
        r = @SVector rand(3)
        @test ForwardDiff.jacobian(g->R(g)*r, params(g1)) ≈ ∇rotate(g1, r)

        function compose(g2,g1)
            params(R(g2)*R(g1))
        end
        @test ForwardDiff.jacobian(g->compose(params(g2),g), params(g1)) ≈ ∇composition1(g2,g1)
        @test ForwardDiff.jacobian(g->compose(g,params(g1)), params(g2)) ≈ ∇composition2(g2,g1)

        g0 = R{Float64}(0,0,0)
        @test ∇composition1(g2, g0) ≈ Rotations.∇differential(g2)

        gval = params(g1)
        b = @SVector rand(3)
        @test ForwardDiff.jacobian(g->∇composition1(g2,R(g))'b, gval) ≈
            Rotations.∇²composition1(g2,g1,b)
        @test Rotations.∇²differential(g2, b) ≈
            Rotations.∇²composition1(g2, g0, b)
    end

end

@testset "kinematics" begin
    repeats = 100

    @testset "QuatRotation" begin
        for _ in 1:repeats
            q = rand(QuatRotation)
            ω = @SVector rand(3)
            q_ = Rotations.params(q)
            qdot = Rotations.kinematics(q,ω)
            @test qdot ≈ 0.5*lmult(q)*hmat()*ω
            @test qdot ≈ 0.5*lmult(q)*hmat(ω)
            @test ω ≈ 2*vmat()*lmult(q)'qdot
            @test ω ≈ 2*vmat()*lmult(inv(q))*qdot
            q2 = Quaternion(q)*pure_quaternion(ω)
            @test qdot ≈ SVector(real(q2), imag_part(q2)...)/2
        end
    end

    @testset "MRP" begin
        for _ in 1:repeats
            ω = @SVector rand(3)
            g = rand(MRP)
            p = Rotations.params(g)
            A = Diagonal(I,3) + 2*(skew(p)^2 + skew(p))/(1+p'p)
            @test Rotations.kinematics(g, ω) ≈ 0.25*(1 + p'p) * A*ω
            @test ω ≈ 4/(1+p'p) * A'Rotations.kinematics(g,ω)
        end
    end

    @testset "RodriguesParam" begin
        for _ in 1:repeats
            ω = @SVector rand(3)
            g = rand(RodriguesParam)
            p = Rotations.params(g)
            gdot = Rotations.kinematics(g, ω)
            @test gdot ≈ 0.5*(Diagonal(I,3) + skew(p) + p*p')*ω
            @test ω ≈ 2/(1+p'p)*(gdot - p × gdot)
        end
    end

end


text:
export is_discrete_space, discrete2standard_discrete

is_discrete_space(x) = is_discrete_space(typeof(x))

is_discrete_space(::Type{<:AbstractVector}) = true
is_discrete_space(::Type{<:Tuple}) = true
is_discrete_space(::Type{<:NamedTuple}) = true

is_discrete_space(::Type{<:Space}) = false

"""
    discrete2standard_discrete(env)

Convert an `env` with a discrete action space to a standard form:

- The action space is of type `Base.OneTo`
- If the `env` is of `FULL_ACTION_SET`, then each action in the
  `legal_action_space(env)` is also an `Int` in the action space.

The standard form is useful for some algorithms (like Q-learning).
"""
function discrete2standard_discrete(env::AbstractEnv)
    A = action_space(env)
    if is_discrete_space(A)
        AS = ActionStyle(env)
        if AS === FULL_ACTION_SET
            mapping = Dict(x => i for (i, x) in enumerate(A))
            ActionTransformedEnv(
                env;
                action_space_mapping = a -> map(x -> mapping[x], a),
                action_mapping = i -> A[i],
            )
        elseif AS === MINIMAL_ACTION_SET
            ActionTransformedEnv(
                env;
                action_space_mapping = x -> Base.OneTo(length(A)),
                action_mapping = i -> A[i],
            )
        else
            @error "unknown ActionStyle $AS"
        end
    else
        throw(ArgumentError("unrecognized action space: $A"))
    end
end


text:
abstract ShannonEntropy
abstract GroupedShannonEntropy <: ShannonEntropy
abstract Hist

type Hist1d <: Hist
    wordcnt::Array{Float64,1}
    bins::Array{Float64,1}
end

type Hist2d <: Hist
    wordcnt::Array{Float64,2}
    binsx::Array{Float64,1}
    binsy::Array{Float64,1}
end

type BinnedEntropy <: ShannonEntropy
    counts::Hist
    E::Float64
end

type BinnedInformation <: ShannonEntropy
    counts::Hist
    I::Float64
    function BinnedInformation(NN::Hist2d)
        Nc = NN.wordcnt
        N = sum(Nc[:])
        H1 = log2(Nc + (Nc.==0))
        H2 = log2(sum(Nc,1))
        H3 = log2(sum(Nc,2))
        H4 = log2(N)
        H = Nc.*(broadcast(-,broadcast(-, H1, H2),H3) + H4)
        H[isnan(H)] = 0
        H = 1/N*sum(sum(H))
        new(A,H)
    end
end

type TemporalEntropy <: ShannonEntropy
	H::Array{Float64,1}
	bins::Array{Float64,1}
	word_size::Integer
end

type GroupedTemporalEntropy <: GroupedShannonEntropy
	Hc::Array{Float64,2}
	dHc::Array{Float64,2}
	H::Array{Float64,1}
	dH::Array{Float64,1}
	I::Array{Float64,1}
	dI::Array{Float64,1}
	bins::Array{Float64,1}
	word_size::Integer
	group_labels::Array{Int64,1}
	trials_per_group::Array{Int64,1}
end
type GroupedCountEntropy <: GroupedShannonEntropy
	Hc::Array{Float64,2}
	dHc::Array{Float64,2}
	H::Array{Float64,1}
	dH::Array{Float64,1}
	I::Array{Float64,1}
	dI::Array{Float64,1}
	bins::Array{Float64,1}
	word_size::Integer
	group_labels::Array{Int64,1}
	trials_per_group::Array{Int64,1}
end

type GroupedPopulationEntropy <: GroupedShannonEntropy
	Hc::Array{Float64,2}
	dHc::Array{Float64,2}
	H::Array{Float64,1}
	dH::Array{Float64,1}
	I::Array{Float64,1}
	dI::Array{Float64,1}
	bins::Array{Float64,1}
	ncells::Integer
	group_labels::Array{Int64,1}
	trials_per_group::Array{Int64,1}
end

varname(::Type{GroupedTemporalEntropy})  = "GTE"
varname(::Type{GroupedCountEntropy})  = "GCE"
varname(::Type{GroupedPopulationEntropy})  = "GPE"

filename(::Type{GroupedTemporalEntropy})  = "temporalEntropy.jd"
filename(::Type{GroupedCountEntropy})  = "countEntropy.jd"
filename(::Type{GroupedPopulationEntropy})  = "populationEntropy.jl"

function GroupedTemporalEntropy(Hc::Array{Float64,2}, dHc::Array{Float64,2},H::Array{Float64,1},dH::Array{Float64,1}, bins::Array{Float64,1}, word_size::Integer, group_labels::Array{Int64,1},trials_per_group::Array{Int64,1})
	ps = trials_per_group/sum(trials_per_group)
	_hc = zeros(size(Hc,1))
	_dhc = zeros(size(Hc,1))
	for i=1:size(Hc,2)
		for j=1:size(Hc,1)
			_hc[j] += ps[i]*Hc[j,i]
			_dhc[j] += ps[i]*ps[i]*dHc[j,i]*dHc[j,i] #variance
		end
	end
	I = H - _hc
	dI = sqrt(dH.*dH + _dhc)
	return GroupedTemporalEntropy(Hc,dHc,H,dH,I,dI,bins,word_size,group_labels,trials_per_group)
end

function GroupedTemporalEntropy(fname::String;redo::Bool=false)
	GTE = JLD.load(fname,"GTE")
	if redo
		GTE = GroupedTemporalEntropy(GTE.Hc, GTE.dHc, GTE.H, GTE.dH, GTE.bins, GTE.word_size, GTE.group_labels,GTE.trials_per_group)
	end
	return GTE
end

function GroupedCountEntropy(fname::String)
	GCE = JLD.load(fname,"GCE")
	return GCE
end

function GroupedCountEntropy(Hc::Array{Float64,2}, dHc::Array{Float64,2},H::Array{Float64,1},dH::Array{Float64,1}, bins::Array{Float64,1}, word_size::Integer, group_labels::Array{Int64,1},trials_per_group::Array{Int64,1})
	ps = trials_per_group/sum(trials_per_group)
	_hc = zeros(size(Hc,1))
	_dhc = zeros(size(Hc,1))
	for i=1:size(Hc,2)
		for j=1:size(Hc,1)
			_hc[j] += ps[i]*Hc[j,i]
			_dhc[j] += ps[i]*ps[i]*dHc[j,i]*dHc[j,i] #variance
		end
	end
	I = H - _hc
	dI = sqrt(dH.*dH + _dhc)
	return GroupedCountEntropy(Hc,dHc,H,dH,I,dI,bins,word_size,group_labels,trials_per_group)
end

function save(GTE::GroupedTemporalEntropy, fname::String)
	JLD.save(fname, {"GTE" => GTE})
end