text:
module JuliaExcel
export srv_xl, setxlpid, killflagfile, getcommsfolder

using Dates, DataFrames
import StringEncodings
global const xlpid = Ref(0)
global const commsfolder = Ref("")

"""
    setxlpid(pid::Int64)
Set the process id of the instance of Excel that the current Julia process is serving.
"""
function setxlpid(pid::Int64)
  xlpid[] = pid
  settitle()
  println("xlpid set to $pid")
  nothing
end

"""
    getxlpid()
Returns the process id of the instance of Excel that the current Julia process is serving.
"""
function getxlpid()
    xlpid[]
end

"""
    getcommsfolder()
Returns the name of the folder to which request files are written by VBA code in
JuliaExcel.xlam and to which `srv_xl` writes results. See also `setcommsfolder`.
"""
function getcommsfolder()
    if commsfolder[] == ""
        throw("commsfolder has not been set")
    else
        commsfolder[]
    end
end

#JuliaExcel.setcommsfolder("C:/Users/PhilipSwannell/AppData/Local/Temp/@JuliaExcel")
"""
    setcommsfolder()
Sets the name of the folder to which request files are written by VBA code in
JuliaExcel.xlam and to which `srv_xl` writes results. See also `getcommsfolder`.
"""
function setcommsfolder(folder::String)
    commsfolder[] = folder
end

function installme()
    Sys.iswindows() || throw("JuliaExcel can only be installed on Windows")
    installscript = normpath(joinpath(@__DIR__,"..","installer","install.vbs"))
    exefile = "C:/Windows/System32/wscript.exe"
    isfile(exefile) || throw("Cannot find Windows Script Host at '$exefile'")
    isfile(installscript) || throw("Cannot find install script at '$installscript'")
    run(`$exefile $installscript`,wait = false)
    println("Installer script has been launched, please respond to the dialogs there.")
    nothing
end

flagfile() = joinpath(getcommsfolder(), "Flag_$(getxlpid()).txt")
resultfile() = joinpath(getcommsfolder(), "Result_$(getxlpid()).txt")
expressionfile() = joinpath(getcommsfolder(), "Expression_$(getxlpid()).txt")

"""
    killflagfile()
Deletes the "flag file" whose existence indicates to VBA code in JuliaExcel.xlam that
`srv_xl()` has not yet completed its evaluation of the contents of the expression to be
evaluated. `killflagfile` can thus be used manually from the REPL if (for example) the
expression to be evaluated includes an infinite loop.
"""
function killflagfile()
    if isfile(flagfile())
        rm(flagfile())
        "File $(flagfile()) deleted"
    else
        "File $(flagfile()) not found"
    end
end
"""
    read_utf16(filename::String)
Returns the contents of a UTF-16 encoded text file that has a byte option mark.
See https://discourse.julialang.org/t/reading-a-utf-16-le-file/11687
"""
read_utf16(filename::String) = transcode(String, reinterpret(UInt16, read(filename)))[4:end]

"""
    srv_xl()
Read the expression file created by JuliaExcel.xlam, evaluate it and write the result to
file, to be unserialised by JuliaExcel.xlam. Files are read from and written to the folder
given by `getcommsfolder`.
"""
function srv_xl()

    expression = read_utf16(expressionfile())

    global result = try
        Main.eval(Meta.parse(expression))
    catch e
        "#($e)!"
    end

    canencode = true
    encodedresult = try
        encode_for_xl(result)
    catch e
        canencode = false
        encode_for_xl("#Expression evaluated to a variable of type $(typeof(result))," *
                      " which cannot be returned to Excel because: $(e)!")
    end

    io = open(resultfile(), "w")
    write(io, StringEncodings.encode(encodedresult, "UTF-16"))
    close(io)

    killflagfile()
    println(truncate(expression))
    display(result)
    canencode || (println("");@error "Result of type $(typeof(result)) could not be " *
                                     "encoded for return to Excel.")

    nothing
end

"""
    setvar(name::String, arg)
Set a variable in global scope. Called by VBA function JuliaSetVar.
"""
function setvar(name::String, arg)

    if Base.isidentifier(name)
        Main.eval(Main.eval(Meta.parse(":(global $name = $arg)")))

        thesize = ()
        thetype = Nothing
        try
            tmp = Main.eval(Meta.parse(name))
            thesize = size(tmp)
            thetype = typeof(tmp)
        catch
        end

        numdims = length(thesize)
        if numdims == 0
             sizedesc = ""
        elseif numdims == 1
            sizedesc =  "$(thesize[1])-element "
        elseif numdims > 1
            sizedesc = join(thesize,"x") * " "
        end
        "Set global variable `$name` to $sizedesc$thetype"

    else
        "#`$name` is not an allowed variable name in Julia!"
    end
end

#= Overriding base include method to avoid serializing issue
Issue is `include` returns the last thing that it encounters in the file. Which may be
something that is not serializable. To avoid the error, we add a `nothing` at the end. =#
function include(x::String)
    if isfile(x)
        Base.MainInclude.include(x)
        "File `$(normpath(abspath(x)))` was included"
    else
        "#Cannot find file `$(normpath(abspath(x)))`!"
    end
end

# https://docs.microsoft.com/en-us/windows/terminal/tutorials/tab-title
function settitle()
    if Sys.islinux()
        os = "Linux"
    elseif Sys.iswindows()
        os = "Windows"
    end

    print("\033]0;Julia $VERSION on $os serving Excel PID $(getxlpid())\a")
end

"""
    truncate(x::String)
Abbreviate a string to show only 120 characters, the usual width of the REPL.
"""
function truncate(x::String)
    if (length(x)) > 120
        first(x,58) * " … " * last(x,58)
    else
        x
    end
end

#=
encode_for_xl implements a data serialisation format that's easier and faster to
unserialise than csv.
- Singleton types are prefixed with a type indicator character.
- Dates are converted to their Excel representation - faster to unserialise in VBA.
- Arrays are written with type indicator *, then three sections separated by semi-colons:
  First section gives the number of dimensions and the dimensions themselves, comma
  delimited e.g. a 3 x 4 array would have a dimensions section "2,3,4".
  Second section gives the lengths of the encodings of each element, comma delimited with a
  terminating comma.
  Third section gives the encodings, concatenated with no delimiter.
  - Note that arrays are written in column-major order.

When decoded (by VBA function modDecode.Decode), the type indicator characters are
interpreted as follows:
 #   vbDouble
 £   String
 T   Boolean True
 F   Boolean False
 D   Date (D should be followed by the number that represents the date, Excel-style
           i.e. Dates.value(x) - 693594)
 E   Empty
 N   Null
 %   Integer
 &   Long
 S   Single
 C   Currency
 !   Error (! should be followed by an Excel error number, e.g.
              2042 for the Excel error value #N/A )
 @   Decimal
 *   Array
 ^   Dictionary

  Examples:
  julia> JuliaExcel.encode_for_xl(1.0)
"#1.0"

julia> JuliaExcel.encode_for_xl(1)
"&1"

julia> JuliaExcel.encode_for_xl("Hello")
"£Hello"

julia> JuliaExcel.encode_for_xl(true)
"T"

julia> JuliaExcel.encode_for_xl(false)
"F"

julia> JuliaExcel.encode_for_xl(Date(2021,3,11))
"D44266"

julia> JuliaExcel.encode_for_xl([1 2;true π;"Hello" "World"])
"*2,3,2;2,1,6,2,18,6,;&1T£Hello&2#3.141592653589793£World" =#

# See also VBA method Decode which unserialises i.e. inverts this function
encode_for_xl(x::AbstractString) = "£" * x         # String in VBA/Excel
encode_for_xl(x::AbstractChar) = "£" * x           # String in VBA/Excel
encode_for_xl(x::Int8) = string("S", x)   # Integer in VBA
encode_for_xl(x::Int16) = string("S", x)   # Integer in VBA
encode_for_xl(x::Int32) = string("&", x)   # Long in VBA 64-bit, no native 32-bit integer
                                           # type exists on 64 bit Excel
encode_for_xl(x::Int64) = string("&", x)   # Long in VBA 64-bit
encode_for_xl(x::Int128) = string("#", Float64(x))   # Double in VBA
encode_for_xl(x::Irrational) = string("#", Float64(x)) #Double in VBA
encode_for_xl(x::Missing) = "E"            # Empty in VBA
encode_for_xl(x::Nothing) = "E"            # Empty in VBA
encode_for_xl(x::Bool) = x ? "T" : "F"     # Boolean in VBA/Excel
encode_for_xl(x::Date) = string("D", Dates.value(x) - 693594) # Date in VBA/Excel
encode_for_xl(x::DateTime) = string("D", Dates.value(x)/86_400_000 - 693594)  # VBA has no separate DateTime type
encode_for_xl(x::DataType) = wrapshow(x)
encode_for_xl(x::VersionNumber) = encode_for_xl("$x")
encode_for_xl(x::Tuple) = encode_for_xl([x[i] for i in eachindex(x)])
encode_for_xl(x::T) where T <: Function = wrapshow(x)
encode_for_xl(x::Symbol) = wrapshow(x)
encode_for_xl(x::Any) = throw("Cannot encode variable of type $(typeof(x))")

function wrapshow(x)
    io = IOBuffer()
    show(io, "text/plain", x)
    encode_for_xl(String(take!(io)))
end

function encode_for_xl(x::Float64)
    if isinf(x)
        "!2036" # #NUM! in Excel
    elseif isnan(x)
        "!2042" # #N/A in Excel
    else
        string("#", x)# Double in VBA/Excel
    end
end

function encode_for_xl(x::Union{Float16,Float32})
    if isinf(x)
        "!2036" # #NUM! in Excel
    elseif isnan(x)

        "!2042" # #N/A in Excel
    else
        string("S", x)# Single in VBA
    end
end

#=PGS 8 Dec 2021 Seeing problem:
The applicable method may be too new: running in world age 31344, while current world is 31485.
Closest candidates are:
  size(::SentinelArrays.MissingVector) at ~/.julia/packages/SentinelArrays/iHRpO/src/missingvector.jl:6 (method too new to be called from this world context.)

  Solutions tried
1)
Used Base.invokelatest(size,x). Bit surprised this did not work...
2) write method of encode_for_xl(x::SentinelArrays.MissingVector), which
    a) requires SentinelArrays be a dependency of JuliaExcel :(
    b) solves the problem for SentinelArrays.MissingVector, but the same problem pops up
    but for NamedArrays.NamedArray
=#

#function encode_for_xl(x::SentinelArrays.MissingVector)
#    l = x.len
#    "*1,$l;$("1,"^l);$("E"^l)"
#end

function encode_for_xl(x::T) where T <: AbstractArray

    sx = size(x)
    dimssection = string(length(sx)) * "," * join(sx, ",")
    lengths_buf = IOBuffer()
    contents_buf = IOBuffer()

    for i in eachindex(x)
        this = encode_for_xl(x[i])
        write(contents_buf, this)
        write(lengths_buf, string(length(this)), ",")
    end

    "*" * dimssection * ";" * String(take!(lengths_buf)) * ";" * String(take!(contents_buf))
end

function encode_for_xl(x::DataFrame)
    nc = size(x)[2]
    data = Matrix{Any}(x)
    headers = Matrix{Any}(undef, 1, nc)
    for i in 1:nc
        headers[1,i] = names(x)[i]
    end
    encode_for_xl(vcat(headers, data))
end

function encode_for_xl(x::T) where T <: AbstractDict

    dimssection = string(length(x))
    lengths_buf = IOBuffer()
    contents_buf = IOBuffer()

    for (k,v) in x
        thiskey = encode_for_xl(k)
        thisvalue = encode_for_xl(v)
        write(contents_buf, thiskey)
        write(contents_buf,thisvalue)
        write(lengths_buf, string(length(thiskey)), ",")
        write(lengths_buf, string(length(thisvalue)), ",")
    end

    "^" * dimssection * ";" * String(take!(lengths_buf)) * ";" * String(take!(contents_buf))
end

end # module


text:
# ---
# title: 1436. Destination City
# id: problem1436
# author: Tian Jun
# date: 2020-10-31
# difficulty: Easy
# categories: String
# link: <https://leetcode.com/problems/destination-city/description/>
# hidden: true
# ---
#
# You are given the array `paths`, where `paths[i] = [cityAi, cityBi]` means
# there exists a direct path going from `cityAi` to `cityBi`. _Return the
# destination city, that is, the city without any path outgoing to another
# city._
#
# It is guaranteed that the graph of paths forms a line without any loop,
# therefore, there will be exactly one destination city.
#
#
#
# **Example 1:**
#
#
#
#     Input: paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]
#     Output: "Sao Paulo"
#     Explanation: Starting at "London" city you will reach "Sao Paulo" city which is the destination city. Your trip consist of: "London" -> "New York" -> "Lima" -> "Sao Paulo".
#
#
# **Example 2:**
#
#
#
#     Input: paths = [["B","C"],["D","B"],["C","A"]]
#     Output: "A"
#     Explanation: All possible trips are:
#     "D" -> "B" -> "C" -> "A".
#     "B" -> "C" -> "A".
#     "C" -> "A".
#     "A".
#     Clearly the destination city is "A".
#
#
# **Example 3:**
#
#
#
#     Input: paths = [["A","Z"]]
#     Output: "Z"
#
#
#
#
# **Constraints:**
#
#   * `1 <= paths.length <= 100`
#   * `paths[i].length == 2`
#   * `1 <= cityAi.length, cityBi.length <= 10`
#   * `cityAi != cityBi`
#   * All strings consist of lowercase and uppercase English letters and the space character.
#
#
## @lc code=start
using LeetCode

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

ext: jl


text:
using Documenter, ParallelKMeans

makedocs(;
    modules=[ParallelKMeans],
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/PyDataBlog/ParallelKMeans.jl/blob/{commit}{path}#L{line}",
    sitename="ParallelKMeans.jl",
    authors="Bernard Brenyah & Andrey Oskin",
    assets=String[],
)

deploydocs(;
    repo="github.com/PyDataBlog/ParallelKMeans.jl",
)


text:
################################################################################
### Updates
################################################################################
import .MPI

abstract type AbstractMPIUpdate <: AbstractGlobalUpdate end
function init!(mc, ::AbstractMPIUpdate)
    MPI.Initialized() || MPI.Init()
end

"""
    MPIReplicaExchange([mc, model], target)

Represents a replica exchange update with a given `target` MPI rank.

Note that this update is blocking, i.e. a simulation will wait on its partner to
perform the update.
"""
struct MPIReplicaExchange <: AbstractMPIUpdate
    target::Int
end
MPIReplicaExchange(target) = MPIReplicaExchange(target)
MPIReplicaExchange(mc, model, target) = MPIReplicaExchange(target)
name(::MPIReplicaExchange) = "MPIReplicaExchange"

@bm function update(u::MPIReplicaExchange, mc, model)
    # swap conf
    MPI.Isend(conf(mc), u.target, 0, MPI.COMM_WORLD)
    MPI.Recv!(mc.temp_conf, u.target, 0, MPI.COMM_WORLD)

    # compute weight
    detratio, ΔE_boson, passthrough = propose_global_from_conf(mc, model, mc.temp_conf)
    local_weight = exp(- ΔE_boson) * detratio
    local_prob = rand()

    # swap weight, probability
    req = MPI.Isend((local_weight, local_prob), u.target, 1, MPI.COMM_WORLD)
    data, _ = MPI.Recv(Tuple{Float64, Float64}, u.target, 1, MPI.COMM_WORLD)
    remote_weight, remote_prob = data

    # accept/deny
    # We need to pick one of the random values and do so consistently across
    # processes.
    w = local_weight * remote_weight
    if ifelse(myid() < u.target, local_prob, remote_prob) < w
        accept_global!(mc, model, mc.temp_conf, passthrough)
        MPI.Wait!(req)
        return 1
    else
        MPI.Wait!(req)
        return 0
    end
end

# """
#     MPIReplicaPull([mc, model])

# This update will pull a configuration from a connected worker and attempt a
# global update with it. The target worker will be cycled as the simulation
# progresses.

# To connect workers for this update, the remote worker has to call
# `connect(this_worker)`.

# This update only blocks locally.
# """
# mutable struct MPIReplicaPull <: AbstractMPIUpdate
#     cycle_idx::Int
#     window::MPI.Win

#     MPIReplicaPull(idx) = new(idx)
# end
# MPIReplicaPull() = MPIReplicaPull(1)
# MPIReplicaPull(mc::MonteCarloFlavor, model::Model) = MPIReplicaPull(1)
# name(::MPIReplicaPull) = "MPIReplicaPull"
# Base.:(==)(a::MPIReplicaPull, b::MPIReplicaPull) = a.cycle_idx == b.cycle_idx
# function init!(mc, update::MPIReplicaPull)
#     MPI.Initialized() || MPI.Init()
#     update.window = MPI.Win_create(mc.conf, MPI.COMM_WORLD)
#     nothing
# end

# @bm function update(u::MPIReplicaPull, mc, model)
#     # TODO
#     # - this needs to call
#     #   MPI.Win_create(mc.conf, MPI.COMM_WORLD)
#     #   and make the result available here?
#     # - needs testing
#     # - needs its own connected_ids management

#     # cycle first to make sure the idx is in bounds
#     @sync if !isempty(connected_ids)
#         idx = mod1(u.cycle_idx, length(connected_ids))
#         MPI.Get(mc.temp_conf, connected_ids[idx], u.window)
#         return global_update(mc, model, mc.temp_conf)
#     end
#     return 0
# end


text:
function differentiate(obj::UnivariateVectorFunctionDifferentiator, arg0::UnivariateVectorFunction)
    return jcall(obj, "differentiate", UnivariateDifferentiableVectorFunction, (UnivariateVectorFunction,), arg0)
end


text:
using CuArrays
using CUDAnative
using CUDAdrv
using MPI

function pin!(a)
  ad = Mem.register(Mem.Host, pointer(a), sizeof(a))
  finalizer(_ -> Mem.unregister(ad), a)
end

function kernel!(c, a, b)
  i = (blockIdx().x-1) * blockDim().x + threadIdx().x
  @inbounds a_val = a[i]
  @inbounds b_val = b[i]
  @inbounds c_val = c[i]

  for j in 1:99
    a_val = CUDAnative.fma(a_val, b_val, c_val)
    b_val = CUDAnative.fma(a_val, b_val, c_val)
    c_val = CUDAnative.fma(a_val, b_val, c_val)
  end

  @inbounds c[i] = CUDAnative.fma(a_val, b_val, c_val)

  return
end

function main()
  if !MPI.Initialized()
    MPI.Init()
  end
  comm = MPI.COMM_WORLD
  local_comm = MPI.Comm_split_type(comm, MPI.MPI_COMM_TYPE_SHARED,
                                   MPI.Comm_rank(comm))
  device!(MPI.Comm_rank(local_comm) % length(devices()))
  copystream = CuStream(CUDAdrv.STREAM_NON_BLOCKING)
  compstream = CuStream(CUDAdrv.STREAM_NON_BLOCKING)
  CuArrays.allowscalar(false)

  synchronize(copystream)
  synchronize(compstream)
  MPI.Barrier(comm)

  dst_rank = mod(MPI.Comm_rank(comm)+1, MPI.Comm_size(comm))
  src_rank = mod(MPI.Comm_rank(comm)-1, MPI.Comm_size(comm))

  T = Float32
  M = 1024
  N = M*100

  A = CuArray(rand(T, M, N))
  B = CuArray(rand(T, M, N))
  C = CuArray(rand(T, M, N))
  d = CuArray(rand(T, M))

  b = Array{T}(undef, M)
  c = Array{T}(undef, M)
  pin!(b)
  pin!(c)

  len = length(A)
  threads = min(len, 1024)
  blocks = len ÷ threads

  for j = 1:100
    unsafe_copyto!(pointer(b), pointer(B), M, async=true, stream=copystream)
    @cuda threads=threads blocks=blocks stream=compstream kernel!(C, A, B)

    synchronize(copystream)

    rreq = MPI.Irecv!(c, src_rank, 222, comm)
    sreq = MPI.Isend(b, dst_rank, 222, comm)
    stats = MPI.Waitall!([sreq, rreq])

    unsafe_copyto!(pointer(d), pointer(c), M, async=true, stream=copystream)

    synchronize(copystream)
    synchronize(compstream)

    unsafe_copyto!(pointer(C), pointer(d), M, async=true, stream=copystream)
    @cuda threads=threads blocks=blocks stream=copystream kernel!(C, A, B)

    synchronize(copystream)
  end
end
main()


text:
@testset "c2i00a" begin
    rc2i = c2i00a(2400000.5, 53736.0)
    @test rc2i[1,1] ≈ 0.9999998323037165557 atol=1e-12
    @test rc2i[1,2] ≈ 0.5581526348992140183e-9 atol=1e-12
    @test rc2i[1,3] ≈ -0.5791308477073443415e-3 atol=1e-12
    @test rc2i[2,1] ≈ -0.2384266227870752452e-7 atol=1e-12
    @test rc2i[2,2] ≈ 0.9999999991917405258 atol=1e-12
    @test rc2i[2,3] ≈ -0.4020594955028209745e-4 atol=1e-12
    @test rc2i[3,1] ≈ 0.5791308472168152904e-3 atol=1e-12
    @test rc2i[3,2] ≈ 0.4020595661591500259e-4 atol=1e-12
    @test rc2i[3,3] ≈ 0.9999998314954572304 atol=1e-12
end

@testset "c2i00b" begin
    rc2i = c2i00b(2400000.5, 53736.0)
    @test rc2i[1,1] ≈ 0.9999998323040954356 atol=1e-12
    @test rc2i[1,2] ≈ 0.5581526349131823372e-9 atol=1e-12
    @test rc2i[1,3] ≈ -0.5791301934855394005e-3 atol=1e-12
    @test rc2i[2,1] ≈ -0.2384239285499175543e-7 atol=1e-12
    @test rc2i[2,2] ≈ 0.9999999991917574043 atol=1e-12
    @test rc2i[2,3] ≈ -0.4020552974819030066e-4 atol=1e-12
    @test rc2i[3,1] ≈ 0.5791301929950208873e-3 atol=1e-12
    @test rc2i[3,2] ≈ 0.4020553681373720832e-4 atol=1e-12
    @test rc2i[3,3] ≈ 0.9999998314958529887 atol=1e-12
end

@testset "c2i06a" begin
    rc2i = c2i06a(2400000.5, 53736.0)
    @test rc2i[1,1] ≈ 0.9999998323037159379 atol=1e-12
    @test rc2i[1,2] ≈ 0.5581121329587613787e-9 atol=1e-12
    @test rc2i[1,3] ≈ -0.5791308487740529749e-3 atol=1e-12
    @test rc2i[2,1] ≈ -0.2384253169452306581e-7 atol=1e-12
    @test rc2i[2,2] ≈ 0.9999999991917467827 atol=1e-12
    @test rc2i[2,3] ≈ -0.4020579392895682558e-4 atol=1e-12
    @test rc2i[3,1] ≈ 0.5791308482835292617e-3 atol=1e-12
    @test rc2i[3,2] ≈ 0.4020580099454020310e-4 atol=1e-12
    @test rc2i[3,3] ≈ 0.9999998314954628695 atol=1e-12
end

@testset "c2ibpn" begin
    rbpn = [9.999962358680738e-1 -2.516417057665452e-3 -1.093569785342370e-3;
            2.516462370370876e-3 9.999968329010883e-1 4.006159587358310e-5;
            1.093465510215479e-3 -4.281337229063151e-5 9.999994012499173e-1]
    rc2i = c2ibpn(2400000.5, 50123.9999, rbpn)
    @test rc2i[1,1] ≈ 0.9999994021664089977 atol=1e-12
    @test rc2i[1,2] ≈ -0.3869195948017503664e-8 atol=1e-12
    @test rc2i[1,3] ≈ -0.1093465511383285076e-2 atol=1e-12
    @test rc2i[2,1] ≈ 0.5068413965715446111e-7 atol=1e-12
    @test rc2i[2,2] ≈ 0.9999999990835075686 atol=1e-12
    @test rc2i[2,3] ≈ 0.4281334246452708915e-4 atol=1e-12
    @test rc2i[3,1] ≈ 0.1093465510215479000e-2 atol=1e-12
    @test rc2i[3,2] ≈ -0.4281337229063151000e-4 atol=1e-12
    @test rc2i[3,3] ≈ 0.9999994012499173103 atol=1e-12
    @test_throws ArgumentError c2ibpn(2400000.5, 50123.9999, rbpn[1:2,:])
end

@testset "c2s" begin
    t, p = c2s([100.,-50.,25.])
    @test t ≈ -0.4636476090008061162 atol=1e-15
    @test p ≈ 0.2199879773954594463 atol=1e-15
    @test_throws ArgumentError c2s([100.,-50.])
end

@testset "c2ixy" begin
    x = 0.5791308486706011000e-3
    y = 0.4020579816732961219e-4
    rc2i = c2ixy(2400000.5, 53736., x, y)
    @test rc2i[1,1] ≈ 0.9999998323037157138 atol=1e-12
    @test rc2i[1,2] ≈ 0.5581526349032241205e-9 atol=1e-12
    @test rc2i[1,3] ≈ -0.5791308491611263745e-3 atol=1e-12
    @test rc2i[2,1] ≈ -0.2384257057469842953e-7 atol=1e-12
    @test rc2i[2,2] ≈ 0.9999999991917468964 atol=1e-12
    @test rc2i[2,3] ≈ -0.4020579110172324363e-4 atol=1e-12
    @test rc2i[3,1] ≈ 0.5791308486706011000e-3 atol=1e-12
    @test rc2i[3,2] ≈ 0.4020579816732961219e-4 atol=1e-12
    @test rc2i[3,3] ≈ 0.9999998314954627590 atol=1e-12
end

@testset "c2ixys" begin
    x =  0.5791308486706011000e-3
    y =  0.4020579816732961219e-4
    s = -0.1220040848472271978e-7
    rc2i = c2ixys(x, y, s)
    @test rc2i[1,1] ≈ 0.9999998323037157138 atol=1e-12
    @test rc2i[1,2] ≈ 0.5581984869168499149e-9 atol=1e-12
    @test rc2i[1,3] ≈ -0.5791308491611282180e-3 atol=1e-12
    @test rc2i[2,1] ≈ -0.2384261642670440317e-7 atol=1e-12
    @test rc2i[2,2] ≈ 0.9999999991917468964 atol=1e-12
    @test rc2i[2,3] ≈ -0.4020579110169668931e-4 atol=1e-12
    @test rc2i[3,1] ≈ 0.5791308486706011000e-3 atol=1e-12
    @test rc2i[3,2] ≈ 0.4020579816732961219e-4 atol=1e-12
    @test rc2i[3,3] ≈ 0.9999998314954627590 atol=1e-12
end

@testset "c2t00a" begin
    tta = 2400000.5
    uta = 2400000.5
    ttb = 53736.0
    utb = 53736.0
    xp = 2.55060238e-7
    yp = 1.860359247e-6
    rc2t = c2t00a(tta, ttb, uta, utb, xp, yp)
    @test rc2t[1,1] ≈ -0.1810332128307182668 atol=1e-12
    @test rc2t[1,2] ≈ 0.9834769806938457836 atol=1e-12
    @test rc2t[1,3] ≈ 0.6555535638688341725e-4 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834768134135984552 atol=1e-12
    @test rc2t[2,2] ≈ -0.1810332203649520727 atol=1e-12
    @test rc2t[2,3] ≈ 0.5749801116141056317e-3 atol=1e-12
    @test rc2t[3,1] ≈ 0.5773474014081406921e-3 atol=1e-12
    @test rc2t[3,2] ≈ 0.3961832391770163647e-4 atol=1e-12
    @test rc2t[3,3] ≈ 0.9999998325501692289 atol=1e-12
end

@testset "c2t00b" begin
    tta = 2400000.5
    uta = 2400000.5
    ttb = 53736.0
    utb = 53736.0
    xp = 2.55060238e-7
    yp = 1.860359247e-6
    rc2t = c2t00b(tta, ttb, uta, utb, xp, yp)
    @test rc2t[1,1] ≈ -0.1810332128439678965 atol=1e-12
    @test rc2t[1,2] ≈ 0.9834769806913872359 atol=1e-12
    @test rc2t[1,3] ≈ 0.6555565082458415611e-4 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834768134115435923 atol=1e-12
    @test rc2t[2,2] ≈ -0.1810332203784001946 atol=1e-12
    @test rc2t[2,3] ≈ 0.5749793922030017230e-3 atol=1e-12
    @test rc2t[3,1] ≈ 0.5773467471863534901e-3 atol=1e-12
    @test rc2t[3,2] ≈ 0.3961790411549945020e-4 atol=1e-12
    @test rc2t[3,3] ≈ 0.9999998325505635738 atol=1e-12
end

@testset "c2t06a" begin
    tta = 2400000.5
    uta = 2400000.5
    ttb = 53736.0
    utb = 53736.0
    xp = 2.55060238e-7
    yp = 1.860359247e-6
    rc2t = c2t06a(tta, ttb, uta, utb, xp, yp)
    @test rc2t[1,1] ≈ -0.1810332128305897282 atol=1e-12
    @test rc2t[1,2] ≈ 0.9834769806938592296 atol=1e-12
    @test rc2t[1,3] ≈ 0.6555550962998436505e-4 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834768134136214897 atol=1e-12
    @test rc2t[2,2] ≈ -0.1810332203649130832 atol=1e-12
    @test rc2t[2,3] ≈ 0.5749800844905594110e-3 atol=1e-12
    @test rc2t[3,1] ≈ 0.5773474024748545878e-3 atol=1e-12
    @test rc2t[3,2] ≈ 0.3961816829632690581e-4 atol=1e-12
    @test rc2t[3,3] ≈ 0.9999998325501747785 atol=1e-12
end

@testset "c2tcio" begin
    c = [0.9999998323037164738 0.5581526271714303683e-9 -0.5791308477073443903e-3;
         -0.2384266227524722273e-7 0.9999999991917404296 -0.4020594955030704125e-4;
         0.5791308472168153320e-3 .4020595661593994396e-4 0.9999998314954572365]
    era = 1.75283325530307
    p = [0.9999999999999674705 -0.1367174580728847031e-10 0.2550602379999972723e-6;
         0.1414624947957029721e-10 0.9999999999982694954 -0.1860359246998866338e-5;
         -0.2550602379741215275e-6 0.1860359247002413923e-5 0.9999999999982369658]
    rc2t = c2tcio(c, era, p)
    @test rc2t[1,1] ≈ -0.1810332128307110439 atol=1e-12
    @test rc2t[1,2] ≈ 0.9834769806938470149 atol=1e-12
    @test rc2t[1,3] ≈ 0.6555535638685466874e-4 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834768134135996657 atol=1e-12
    @test rc2t[2,2] ≈ -0.1810332203649448367 atol=1e-12
    @test rc2t[2,3] ≈ 0.5749801116141106528e-3 atol=1e-12
    @test rc2t[3,1] ≈ 0.5773474014081407076e-3 atol=1e-12
    @test rc2t[3,2] ≈ 0.3961832391772658944e-4 atol=1e-12
    @test rc2t[3,3] ≈ 0.9999998325501691969 atol=1e-12
    @test_throws ArgumentError c2tcio(c[1:2,:], era, p)
    @test_throws ArgumentError c2tcio(c, era, p[1:2,:])
end

@testset "c2teqx" begin
    c = [0.9999989440476103608 -0.1332881761240011518e-2 -0.5790767434730085097e-3;
         0.1332858254308954453e-2 0.9999991109044505944 -0.4097782710401555759e-4;
         0.5791308472168153320e-3 0.4020595661593994396e-4 0.9999998314954572365]
    gst = 1.754166138040730516
    p = [0.9999999999999674705 -0.1367174580728847031e-10 0.2550602379999972723e-6;
         0.1414624947957029721e-10 0.9999999999982694954 -0.1860359246998866338e-5;
         -0.2550602379741215275e-6 0.1860359247002413923e-5 0.9999999999982369658]
    rc2t = c2teqx(c, gst, p)
    @test rc2t[1,1] ≈ -0.1810332128528685730 atol=1e-12
    @test rc2t[1,2] ≈ 0.9834769806897685071 atol=1e-12
    @test rc2t[1,3] ≈ 0.6555535639982634449e-4 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834768134095211257 atol=1e-12
    @test rc2t[2,2] ≈ -0.1810332203871023800 atol=1e-12
    @test rc2t[2,3] ≈ 0.5749801116126438962e-3 atol=1e-12
    @test rc2t[3,1] ≈ 0.5773474014081539467e-3 atol=1e-12
    @test rc2t[3,2] ≈ 0.3961832391768640871e-4 atol=1e-12
    @test rc2t[3,3] ≈ 0.9999998325501691969 atol=1e-12
    @test_throws ArgumentError c2teqx(c[1:2,:], gst, p)
    @test_throws ArgumentError c2teqx(c, gst, p[1:2,:])
end

@testset "c2tpe" begin
    tta = 2400000.5
    uta = 2400000.5
    ttb = 53736.0
    utb = 53736.0
    deps =  0.4090789763356509900
    dpsi = -0.9630909107115582393e-5
    xp = 2.55060238e-7
    yp = 1.860359247e-6
    rc2t = c2tpe(tta, ttb, uta, utb, dpsi, deps, xp, yp)
    @test rc2t[1,1] ≈ -0.1813677995763029394 atol=1e-12
    @test rc2t[1,2] ≈ 0.9023482206891683275 atol=1e-12
    @test rc2t[1,3] ≈ -0.3909902938641085751 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834147641476804807 atol=1e-12
    @test rc2t[2,2] ≈ -0.1659883635434995121 atol=1e-12
    @test rc2t[2,3] ≈ 0.7309763898042819705e-1 atol=1e-12
    @test rc2t[3,1] ≈ 0.1059685430673215247e-2 atol=1e-12
    @test rc2t[3,2] ≈ 0.3977631855605078674 atol=1e-12
    @test rc2t[3,3] ≈ 0.9174875068792735362 atol=1e-12
end

@testset "c2txy" begin
    tta = 2400000.5
    uta = 2400000.5
    ttb = 53736.0
    utb = 53736.0
    x = 0.5791308486706011000e-3
    y = 0.4020579816732961219e-4
    xp = 2.55060238e-7
    yp = 1.860359247e-6
    rc2t = c2txy(tta, ttb, uta, utb, x, y, xp, yp)
    @test rc2t[1,1] ≈ -0.1810332128306279253 atol=1e-12
    @test rc2t[1,2] ≈ 0.9834769806938520084 atol=1e-12
    @test rc2t[1,3] ≈ 0.6555551248057665829e-4 atol=1e-12
    @test rc2t[2,1] ≈ -0.9834768134136142314 atol=1e-12
    @test rc2t[2,2] ≈ -0.1810332203649529312 atol=1e-12
    @test rc2t[2,3] ≈ 0.5749800843594139912e-3 atol=1e-12
    @test rc2t[3,1] ≈ 0.5773474028619264494e-3 atol=1e-12
    @test rc2t[3,2] ≈ 0.3961816546911624260e-4 atol=1e-12
    @test rc2t[3,3] ≈ 0.9999998325501746670 atol=1e-12
end

@testset "cal2jd" begin
    dmj0, dmj = cal2jd(2003, 6, 1)
    @test dmj0 ≈ 2400000.5 atol=1e-9
    @test dmj ≈ 52791.0 atol=1e-9
    @test_throws ERFAException cal2jd(-1e9, 6, 1)
    @test_throws ERFAException cal2jd(2021, 13, 1)
    @test_throws ERFAException cal2jd(2021, 6, 32)
end

@testset "cp" begin
    a = randn(3)
    b1 = ERFA._cp(a)
    b2 = copy(a)
    b1[1] = 1.0
    b2[1] = 1.0
    @test a != b1
    @test a != b2
    @test b1 == b2
end

@testset "cpv" begin
    a = [randn(3), randn(3)]
    b1 = ERFA._cpv(a)
    b2 = deepcopy(a)
    b1[1][1] = 1.0
    b2[1][1] = 1.0
    @test a != b1
    @test a != b2
    @test b1 == b2
end

@testset "cr" begin
    a = randn(3, 3)
    b1 = ERFA._cr(a)
    b2 = copy(a)
    b1[1,1] = 1.0
    b2[1,1] = 1.0
    @test a != b1
    @test a != b2
    @test b1 == b2
end


text:
using Fastnet

const S=1                   # Node state 1: Susceptible node
const I=2                   # Node state 2: Infected node
const R=3
const SI=1                  # Link state 1: Susceptible-Infected link

p=0.05                      # Infection rate (per SI-link)
r=0.1                       # Recovery rate (per I-node)
l=0.02                      # Loss of immunity rate (per R-node)

SI_link=LinkType(S,I)     # This describes what we mean by SI-link

# Lets make a network of 100k nodes and 400k links, 2 node states, that keeps track of SI links
net=FastNet(100000,400000,3,[SI_link]; nodealias=["S","I","R"], linkalias=["SI"])

randomgraph!(net)           # Initialize as ER-random graph (all nodes will be in state 1: S)

for i=1:20                  # Infect 20 nodes at random
    node=randomnode(net,S)
    nodestate!(net,node,I)
end

function rates!(rates,t)    # This functins computes the rates of processes
    infected=countnodes_f(net,I)        # count the infected nodes
    recovered=countnodes_f(net,R)        # count the infected nodes
    activelinks=countlinks_f(net,SI)    # count the SI links
    infrate=p*activelinks               # compute total infection rate
    recrate=r*infected                  # compute total recovery rate
    lossrate=l*recovered
    rates[1]=infrate                    # Return the values by filling the rates array
    rates[2]=recrate
    rates[3]=lossrate
    nothing
end

function recovery!()        # This is what we do when the recovery process is triggered
    inode=randomnode_f(net,I)                   # Find a random infected node
    nodestate_f!(net,inode,R)                   # Set the state of the node to recovered
end

function lossofi!()        # This is what we do when a node loses immunity
    rnode=randomnode_f(net,R)                   # Find a node in the recovered state
    nodestate_f!(net,rnode,S)                   # Set the state of the node to susceptible
end

function infection!()       # This is what we do when the infection process is triggered
    alink=randomlink_f(net,SI)                   # Find a random SI link
    nodestate_f!(net,linksrc_f(net,alink),I)     # Set both endpoints of the link to infected
    nodestate_f!(net,linkdst_f(net,alink),I)
end

sim=FastSim(net,rates!,[infection!,recovery!,lossofi!])   # initialize the simulation

@time runsim!(sim,100,10)                      # Run for 100 timeunits (reporting every 10)


text:
# # Indexing
containers = Dict("<:AbstractRange" => 1:1000,
                  "StaticRange" => srange(1,1000,step=1),
                  "Type{StaticRange}" => OneToSRange{1000},
                  "SVector" => SVector(1:1000...),
                  "Vector" => [1:1000...],
                  "Matrix" => rand(Int, 20, 50),
                  "SMatrix" => SMatrix{20,50}(1:1000...));

by_r(x) = x[range(1, 500, step=1)];
by_sr(x) = x[srange(1, 500, step=1)];
# TODO: should this be a thing?
#by_srtype(x) = x[OneToSRange{500}];

by_step_r(x) = x[range(1, 500, step=2)];
by_step_sr(x) = x[srange(1, 500, step=2)];

fxns = Dict("range" => by_r,
            "srange" => by_sr,
            "step_range" => by_step_r,
            "step_srange" => by_step_sr)
by_nd_r(x::AbstractMatrix) = x[range(1, 20, step=1), range(1, 20, step=1)];
by_nd_sr(x::AbstractMatrix) = x[srange(1, 20, step=1), srange(1, 20, step=1)];

SRBench["indexing"] = BenchmarkGroup();
for  (ck,cv) in containers
    for (fk, fv) in fxns
        if !haskey(SRBench["indexing"], ck)
            SRBench["indexing"][ck] = BenchmarkGroup([ck])
        end
        SRBench["indexing"][ck][fk] = @benchmarkable $(fv)($cv)
    end
end

SRBench["indexing"]["Matrix"]["by_nd_r"] = @benchmarkable by_nd_r($(containers["Matrix"]))
SRBench["indexing"]["Matrix"]["by_nd_sr"] = @benchmarkable by_nd_sr($(containers["Matrix"]))
SRBench["indexing"]["SMatrix"]["by_nd_r"] = @benchmarkable by_nd_r($(containers["SMatrix"]))
SRBench["indexing"]["SMatrix"]["by_nd_sr"] = @benchmarkable by_nd_sr($(containers["SMatrix"]))


text:
type VenaCava
    R::Float64
    L::Float64
    C::Float64
    V0::Float64
    P::Vector{Float64}
    V::Vector{Float64}
    Q::Vector{Float64}

    function VenaCava()
        this = new()
        this.P = Vector{Float64}[];
        this.V = Vector{Float64}[];
        this.Q = Vector{Float64}[];
        return this
    end
end

max_stars_repo_name: dcanuto/CardioModeling

max_issues_repo_name: dcanuto/CardioModeling

max_forks_repo_name: dcanuto/CardioModeling


text:
#  github: part of RxNav.jl

"""
    findDrugInteractions

/interaction	Interactions of an RxNorm drug
returns a Vector of NamedTuples
"""
function findDrugInteractions(rxcui::String, extras = [])
    argstring = "interaction/interaction?rxcui=$rxcui" * isempty(extras) ? "" : morearg(extras)
    interactions = NamedTuple[]
    try
        doc = getdoc("baseurl", argstring)
        rxn = findall("//interactionTypeGroup/fullInteractionType/interactionPair")
        for x in rxn
            sev = nodecontent(findfirst("severity", p))
            desc = nodecontent(findfirst("description", p))
            namepair = findall("interactionConcept/minConceptItem/name", p)
            if !isempty(namepair)
                enames = nodecontent.(namepair)
                push!(interactions, (drug1 = enames[1], drug2 = enames[2], severity = sev, description = desc))
            end
        end
    catch y
        @warn y
    end
    return interactions
end

"""
    findInteractionsFromList

/list	Interactions between a list of drugs
returns a Vector of NamedTuples
"""
function findInteractionsFromList(rxcuis::Vector{String}, extras = [])
    argstring = "interaction/list?rxcuis=" * join(rxcuis, "+") *
        isempty(extras) ? "" : morearg(extras)
    interactions = NamedTuple[]
    try
        doc = getdoc("baseurl", argstring)
        rxn = findall("//interactionTypeGroup/fullInteractionType/interactionPair")
        for x in rxn
            sev = nodecontent(findfirst("severity", p))
            desc = nodecontent(findfirst("description", p))
            namepair = findall("interactionConcept/minConceptItem/name", p)
            if !isempty(namepair)
                enames = nodecontent.(namepair)
                push!(interactions, (drug1 = enames[1], drug2 = enames[2], severity = sev, description = desc))
            end
        end
    catch y
        @warn y
    end
    return interactions
end

"""
    getInteractionSources

/sources	Sources of the interactions
"""
function getInteractionSources()
    sources = String[]
    try
        doc = getdoc("baseurl", "interaction/sources")
        rxn = findall("//sourceList/source")
        for x in rxn
            push!(sources, nodecontent(x))
        end
    catch y
        @warn y
    end
    return sources
end

"""
    getVersion

/version	Version of the data set(s)
"""
function getVersion()
    versions = String[]
    try
        doc = getdoc("baseurl", "version")
        rxn = findall("//sourceVersionList/sourceVersion")
        for x in rxn
            push!(versions, nodecontent(x))
        end
    catch y
        @warn y
    end
    return versions
end


text:
using Dates

"""
    {{blogposts}}

Plug in the list of blog posts contained in the `/blog/` folder.
"""
@delay function hfun_blogposts()
    today = Dates.today()
    curyear = year(today)
    curmonth = month(today)
    curday = day(today)

    list = readdir("blog")
    filter!(f -> endswith(f, ".md"), list)
    sorter(p) = begin
        ps  = splitext(p)[1]
        url = "/blog/$ps/"
        surl = strip(url, '/')
        pubdate = pagevar(surl, :published)
        if isnothing(pubdate)
            return Date(Dates.unix2datetime(stat(surl * ".md").ctime))
        end
        return Date(pubdate, dateformat"d U Y")
    end
    sort!(list, by=sorter, rev=true)

    io = IOBuffer()
    write(io, """
""")
    for (i, post) in enumerate(list)
        if post == "index.md"
            continue
        end
        ps  = splitext(post)[1]
        write(io, "
")
        url = "/blog/$ps/"
        surl = strip(url, '/')
        title = pagevar(surl, :title)
        pubdate = pagevar(surl, :published)
        if isnothing(pubdate)
            date    = "$curyear-$curmonth-$curday"
        else
            date    = Date(pubdate, dateformat"d U Y")
        end
        write(io, """$date$title""")
    end
    write(io, "
")
    return String(take!(io))
end

"""
    {{custom_taglist}}

Plug in the list of blog posts with the given tag
"""
function hfun_custom_taglist()::String
    tag = locvar(:fd_tag)
    rpaths = globvar("fd_tag_pages")[tag]
    sorter(p) = begin
        pubdate = pagevar(p, :published)
        if isnothing(pubdate)
            return Date(Dates.unix2datetime(stat(p * ".md").ctime))
        end
        return Date(pubdate, dateformat"d U Y")
    end
    sort!(rpaths, by=sorter, rev=true)

    io = IOBuffer()
    write(io, """
""")
    # go over all paths
    for rpath in rpaths
        write(io, "
")
        url = get_url(rpath)
        title = pagevar(rpath, :title)
        pubdate = pagevar(rpath, :published)
        if isnothing(pubdate)
            date    = "$curyear-$curmonth-$curday"
        else
            date    = Date(pubdate, dateformat"d U Y")
        end
        # write some appropriate HTML
        write(io, """$date$title""")
    end
    write(io, "
")
    return String(take!(io))
end


text:
struct UniformScalingMap{T} <: LinearMap{T}
    λ::T
    M::Int
    function UniformScalingMap(λ::Number, M::Int)
        M < 0 && throw(ArgumentError("size of UniformScalingMap must be non-negative, got $M"))
        return new{typeof(λ)}(λ, M)
    end
end
UniformScalingMap(λ::Number, M::Int, N::Int) =
    (M == N ?
        UniformScalingMap(λ, M) : error("UniformScalingMap needs to be square"))
UniformScalingMap(λ::T, sz::Dims{2}) where {T} =
    (sz[1] == sz[2] ?
        UniformScalingMap(λ, sz[1]) : error("UniformScalingMap needs to be square"))

MulStyle(::UniformScalingMap) = FiveArg()

# properties
Base.size(A::UniformScalingMap) = (A.M, A.M)
Base.isreal(A::UniformScalingMap) = isreal(A.λ)
LinearAlgebra.issymmetric(::UniformScalingMap) = true
LinearAlgebra.ishermitian(A::UniformScalingMap) = isreal(A)
LinearAlgebra.isposdef(A::UniformScalingMap) = isposdef(A.λ)

# comparison of UniformScalingMap objects
Base.:(==)(A::UniformScalingMap, B::UniformScalingMap) = (A.λ == B.λ && A.M == B.M)

# special transposition behavior
LinearAlgebra.transpose(A::UniformScalingMap) = A
LinearAlgebra.adjoint(A::UniformScalingMap)   = UniformScalingMap(conj(A.λ), size(A))

# multiplication with scalar
Base.:(*)(A::UniformScaling, B::LinearMap) = A.λ * B
Base.:(*)(A::LinearMap, B::UniformScaling) = A * B.λ
Base.:(*)(α::Number, J::UniformScalingMap) = UniformScalingMap(α * J.λ, size(J))
Base.:(*)(J::UniformScalingMap, α::Number) = UniformScalingMap(J.λ * α, size(J))
# needed for disambiguation
Base.:(*)(α::RealOrComplex, J::UniformScalingMap) = UniformScalingMap(α * J.λ, size(J))
Base.:(*)(J::UniformScalingMap, α::RealOrComplex) = UniformScalingMap(J.λ * α, size(J))

# multiplication with vector
Base.:(*)(J::UniformScalingMap, x::AbstractVector) =
    length(x) == J.M ? J.λ * x : throw(DimensionMismatch("*"))
# multiplication with matrix
Base.:(*)(J::UniformScalingMap, B::AbstractMatrix) =
    size(B, 1) == J.M ? J.λ * LinearMap(B) : throw(DimensionMismatch("*"))
Base.:(*)(A::AbstractMatrix, J::UniformScalingMap) =
    size(A, 2) == J.M ? LinearMap(A) * J.λ : throw(DimensionMismatch("*"))
# disambiguation
Base.:(*)(xc::LinearAlgebra.AdjointAbsVec, J::UniformScalingMap) = xc * J.λ
Base.:(*)(xt::LinearAlgebra.TransposeAbsVec, J::UniformScalingMap) = xt * J.λ

# multiplication with vector/matrix
for (In, Out) in ((AbstractVector, AbstractVecOrMat), (AbstractMatrix, AbstractMatrix))
    @eval begin
        function _unsafe_mul!(y::$Out, J::UniformScalingMap, x::$In)
            _scaling!(y, J.λ, x, true, false)
            return y
        end
        function _unsafe_mul!(y::$Out, J::UniformScalingMap{<:RealOrComplex}, x::$In{<:RealOrComplex},
                    α::RealOrComplex, β::Number)
            _scaling!(y, J.λ * α, x, true, β)
            return y
        end
        function _unsafe_mul!(y::$Out, J::UniformScalingMap, x::$In,
                    α::Number, β::Number)
            _scaling!(y, J.λ, x, α, β)
            return y
        end
    end
end

function _scaling!(y, λ, x, α, β)
    if (iszero(α) || iszero(λ))
        iszero(β) && return fill!(y, zero(eltype(y)))
        isone(β) && return y
        return rmul!(y, β)
    elseif isone(α) && isone(λ)
        iszero(β) && return copyto!(y, x)
        isone(β) && return y .+= x
        return y .= y .* β .+ x
    elseif isone(α)
        iszero(β) && return y .= λ .* x
        isone(β) && return y .+= λ .* x
        return y .= y .* β .+ λ .* x
    elseif isone(λ)
        iszero(β) && return y .= x .* α
        isone(β) && return y .+= x .* α
        return y .= y .* β .+ x .* α
    else
        iszero(β) && return y .= λ .* x .* α
        isone(β) && return y .+= λ .* x .* α
        return y .= y .* β .+ λ .* x .* α
    end
end

# combine LinearMap and UniformScaling objects in linear combinations
Base.:(+)(A₁::LinearMap, A₂::UniformScaling) = A₁ + UniformScalingMap(A₂.λ, size(A₁, 1))
Base.:(+)(A₁::UniformScaling, A₂::LinearMap) = UniformScalingMap(A₁.λ, size(A₂, 1)) + A₂
Base.:(-)(A₁::LinearMap, A₂::UniformScaling) = A₁ - UniformScalingMap(A₂.λ, size(A₁, 1))
Base.:(-)(A₁::UniformScaling, A₂::LinearMap) = UniformScalingMap(A₁.λ, size(A₂, 1)) - A₂


text:
# This file was generated, do not modify it.

using Pkg  # hideall
Pkg.activate("_literate/D0-loading/Project.toml")
Pkg.update()

using RDatasets
import DataFrames

boston = dataset("MASS", "Boston");

typeof(boston)

c = """
col1,col2,col3,col4,col5,col6,col7,col8
,1,1.0,1,one,2019-01-01,2019-01-01T00:00:00,true
,2,2.0,2,two,2019-01-02,2019-01-02T00:00:00,false
,3,3.0,3.14,three,2019-01-03,2019-01-03T00:00:00,true
"""
fpath, = mktemp()
write(fpath, c);

using CSV
data = CSV.read(fpath, DataFrames.DataFrame)

typeof(data)

c = """
3.26;0.829;1.676;0;1;1.453;3.770
2.189;0.58;0.863;0;0;1.348;3.115
2.125;0.638;0.831;0;0;1.348;3.531
3.027;0.331;1.472;1;0;1.807;3.510
2.094;0.827;0.86;0;0;1.886;5.390
3.222;0.331;2.177;0;0;0.706;1.819
3.179;0;1.063;0;0;2.942;3.947
3;0;0.938;1;0;2.851;3.513
2.62;0.499;0.99;0;0;2.942;4.402
2.834;0.134;0.95;0;0;1.591;3.021
2.405;0.134;0.843;0;0;1.769;3.210
2.728;0.223;0.953;0;0;1.591;2.371
2.512;0.223;0.929;1;0;1.769;3.919
2.834;0.134;1.237;0;0;1.859;3.030
2.819;0.331;1.271;0;1;0.981;2.736
2.126;0.251;1.114;0;0;0.143;2.157
2.834;0.134;1.322;0;0;1.199;2.413
3.014;0.56;1.781;0;0;-0.115;0.898
3.024;0.452;2.698;0;0;1.107;0.450
3.036;0.405;1.205;1;0;1.807;3.733
2.707;0.972;1.889;0;3;-1.169;2.976
2.978;1.246;1.103;0;1;3.988;6.535
3.111;0.732;0.923;0;0;4.068;5.643
"""
fpath, = mktemp()
write(fpath, c);

header = ["CIC0", "SM1_Dz", "GATS1i",
          "NdsCH", "NdssC", "MLOGP", "LC50"]
data = CSV.read(fpath, DataFrames.DataFrame, header=header)
first(data, 3)

c = """
1,0,1,0,0,0,0,1,0,1,1,?,1,0,0,0,0,1,0,0,0,0,1,67,137,15,0,1,1,1.53,95,13.7,106.6,4.9,99,3.4,2.1,34,41,183,150,7.1,0.7,1,3.5,0.5,?,?,?,1
0,?,0,0,0,0,1,1,?,?,1,0,0,1,0,0,0,1,0,0,0,0,1,62,0,?,0,1,1,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,1.8,?,?,?,?,1
1,0,1,1,0,1,0,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,1,78,50,50,2,1,2,0.96,5.8,8.9,79.8,8.4,472,3.3,0.4,58,68,202,109,7,2.1,5,13,0.1,28,6,16,1
1,1,1,0,0,0,0,1,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,77,40,30,0,1,1,0.95,2440,13.4,97.1,9,279,3.7,0.4,16,64,94,174,8.1,1.11,2,15.7,0.2,?,?,?,0
1,1,1,1,0,1,0,1,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,76,100,30,0,1,1,0.94,49,14.3,95.1,6.4,199,4.1,0.7,147,306,173,109,6.9,1.8,1,9,?,59,15,22,1
1,0,1,0,?,0,0,1,0,?,0,1,0,0,0,0,0,1,1,1,0,0,1,75,?,?,1,1,2,1.58,110,13.4,91.5,5.4,85,3.4,3.5,91,122,242,396,5.6,0.9,1,10,1.4,53,22,111,0
1,0,0,0,?,1,1,1,0,0,1,0,?,0,0,0,0,0,0,0,0,0,1,49,0,0,0,1,1,1.4,138.9,10.4,102,3.2,42000,2.35,2.72,119,183,143,211,7.3,0.8,5,2.6,2.19,171,126,1452,0
1,1,1,0,?,0,0,1,0,1,1,?,0,0,0,0,0,0,1,1,1,0,1,61,?,20,3,1,1,1.46,9860,10.8,92,3,58,3.1,3.2,79,108,184,300,7.1,0.52,2,9,1.3,42,25,706,0
1,1,1,0,0,0,0,1,0,1,1,0,0,1,0,0,0,?,1,1,0,0,1,50,100,32,1,1,2,3.14,8.8,11.9,107.5,4.9,70,1.9,3.3,26,59,115,63,6.1,0.59,1,6.4,1.2,85,73,982,1
1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,43,100,0,0,1,1,1.12,1.8,11.8,87.8,5100,193000,4.2,0.5,71,45,256,303,7.1,0.59,1,9.3,0.7,?,?,?,1
1,0,1,0,0,0,1,1,?,?,0,0,0,0,0,0,0,?,1,1,0,0,1,41,?,?,0,1,2,1.05,100809,13,94.2,5.7,196,4.4,3,90,334,494,236,7.6,0.8,5,?,1.1,?,?,?,0
1,0,1,0,0,0,1,1,1,0,0,0,0,1,0,0,0,?,0,1,0,0,1,74,?,0,0,1,1,1.33,86,15.7,96.7,4,61,3.7,1.3,132,168,113,154,?,7.6,5,1.9,0.3,144,41,277,1
1,0,1,0,0,0,0,1,0,1,1,0,0,1,0,0,?,?,1,1,1,0,0,66,?,30,0,1,1,1.53,60,13.3,90.1,5.5,207000,4.4,8.5,25,36,35,74,8.5,0.73,1,5,0.8,?,?,?,1
1,?,0,0,0,0,1,1,?,?,0,0,0,0,0,0,0,0,0,0,0,0,1,56,0,?,0,1,1,1.2,6.6,13.7,93.8,4.1,91000,4.5,1,103,96,205,70,8.8,0.88,1,22,?,82,24,?,1
1,0,1,0,0,0,0,1,0,?,1,0,0,1,0,0,?,1,1,1,0,0,1,63,?,?,2,2,2,1.25,29,13.5,93,6,128,3.15,10.5,76,116,165,163,7.3,1.07,4,4.5,4.5,197,84,302,1
0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,41,100,0,1,1,2,1.61,4.6,10.2,89.6,5.5,161,3.1,3.1,24,57,163,176,5,0.8,2,2.6,1.3,25,13,60,1
1,0,1,0,0,0,0,1,?,1,1,?,1,0,0,0,?,?,1,1,1,0,1,72,?,?,3,2,1,2.14,60,12.1,99.2,5,58,2.4,9.8,69,63,201,235,6.2,0.96,2,2,2.9,136,95,767,0
1,1,1,0,0,0,0,1,0,1,0,0,?,0,0,0,?,1,1,1,1,1,1,60,100,60,2,1,1,1.05,9.2,10.3,103.7,5.4,159,3.8,0.5,56,91,459,146,5.4,1.23,5,13.5,3.8,187,58,443,1
1,?,1,0,0,0,0,1,?,1,0,?,0,1,1,0,0,1,0,0,0,0,1,64,200,78,1,1,1,1.13,8.8,14.9,94.8,6.3,137,4.3,0.9,16,23,82,180,6.5,4.95,1,5.4,0.9,144,49,295,1
1,1,1,0,0,0,0,1,?,?,0,0,0,1,0,0,0,1,1,1,1,0,1,75,500,?,0,1,3,1.44,34,15.9,103.4,9600,101000,3.4,3.4,27,87,260,147,6.3,0.9,5,2.3,1.6,67,34,774,0
"""
fpath, = mktemp()
write(fpath, c);

data = CSV.read(fpath, DataFrames.DataFrame, header=false, missingstring="?")
first(data[:, 1:5], 3)

max_issues_repo_name: alan-turing-institute/MLJTutorials

max_forks_repo_name: alan-turing-institute/MLJTutorials


text:
######################################################################
# Example for various input methods
# -----
# Licensed under MIT License
using Pkg
Pkg.activate(".")

using GLFWAbstraction
using GLFW

buffer = ""
function GLFWAbstraction.on_receive_char(::Window{:mywnd}, char::Char)
    global buffer
    buffer *= char
end
function GLFWAbstraction.on_key_press(::Window{:mywnd}, key::Key, scancode::Integer, modifiers::ModifierKey)
    global buffer
    if key === Key(:backspace) && !isempty(buffer)
        buffer = buffer[1:length(buffer)-1]
    elseif key === Key(:enter)
        println(buffer)
        buffer = ""
    end
end
function GLFWAbstraction.on_key_repeat(::Window{:mywnd}, key::Key, scancode::Integer, modifiers::ModifierKey)
    global buffer
    if key === Key(:backspace) && !isempty(buffer)
        buffer = buffer[1:length(buffer)-1]
    end
end
function GLFWAbstraction.on_mouse_press(::Window{:mywnd}, button::MouseButton, modifiers::ModifierKey)
    println(button)
end
function GLFWAbstraction.on_mouse_move(::Window{:mywnd}, xpos::AbstractFloat, ypos::AbstractFloat)
    println("mouse moved to $xpos, $ypos")
end
GLFWAbstraction.on_mouse_enter(::Window{:mywnd}) = println("hi mouse :)")
GLFWAbstraction.on_mouse_leave(::Window{:mywnd}) = println("bye mouse :(")

let wnd = window(:mywnd, "Input Example", 960, 480)
    while !wnd.shouldclose
        sleep(0.1)
        swapbuffers(wnd)
        pollevents()
    end
end


text:
function MCARP_solve(data, graph)
    """Given data, solve a MCARP problem with integer programming."""

    ### Constants linked to the problem ###

    Er = graph["req_edges"]
    Enr = graph["noreq_edges"]
    Ar = graph["req_arcs"]
    Anr = graph["noreq_arcs"]

    # Return acs for edges
    Er_swap = copy(Er)
    Er_swap[:start_node], Er_swap[:end_node] = Er_swap[:end_node], Er_swap[:start_node]
    Enr_swap = copy(Enr)
    Enr_swap[:start_node], Enr_swap[:end_node] = Enr_swap[:end_node], Enr_swap[:start_node]

    # All arcs
    A = vcat(Er, Enr, Er_swap, Enr_swap, Ar, Anr)
    # Required arcs
    R = vcat(Er, Er_swap, Ar)
    # Non-required arcs
    NR = vcat(Enr, Enr_swap, Anr)

    # Number of nodes
    nb_nodes = data[1, :nodes]
    # Depot node
    depot = data[1, :depots][1]
    # Vehicle capacity
    W = data[1, :capa]
    # Traversing cost on arcs
    trav_cost = A[:, :trav_cost]
    # Service cost on required arcs
    serv_cost = R[:, :serv_cost]
    # Demand on required arcs
    demand = R[:, :demand]

    # Number of vehicle
    P = data[1, :nb_vehicles]

    ### Model definition ###

    model = Model(with_optimizer(CPLEX.Optimizer, CPX_PARAM_SCRIND=0))

    ### Variables ###

    # Service variables
    @variable(model, X_R[1:P, 1:nrow(R)], Bin)
    X_Er = X_R[:, 1:nrow(Er)]
    X_Er_swap = X_R[:, (nrow(Er)+1):(nrow(Er)+nrow(Er_swap))]
    X_Ar = X_R[:, (nrow(Er)+nrow(Er_swap)+1):nrow(R)]
    X_tot = hcat(X_Er, [0 for p in 1:P, arc in 1:nrow(Enr)],
        X_Er_swap, [0 for p in 1:P, arc in 1:nrow(Enr_swap)],
        X_Ar, [0 for p in 1:P, arc in 1:nrow(Anr)])

    # Passage without service variables
    @variable(model, Y_Er[1:P, 1:nrow(Er)], Int)
    @constraint(model, Y_Er .>= 0)
    @variable(model, Y_Enr[1:P, 1:nrow(Enr)], Int)
    @constraint(model, Y_Enr .>= 0)
    @variable(model, Y_Er_swap[1:P, 1:nrow(Er_swap)], Int)
    @constraint(model, Y_Er_swap .>= 0)
    @variable(model, Y_Enr_swap[1:P, 1:nrow(Enr_swap)], Int)
    @constraint(model, Y_Enr_swap .>= 0)
    @variable(model, Y_Ar[1:P, 1:nrow(Ar)], Int)
    @constraint(model, Y_Ar .>= 0)
    @variable(model, Y_Anr[1:P, 1:nrow(Anr)], Int)
    @constraint(model, Y_Anr .>= 0)
    Y_tot = hcat(Y_Er, Y_Enr, Y_Er_swap, Y_Enr_swap, Y_Ar, Y_Anr)
    Y_NR = hcat(Y_Enr, Y_Enr_swap, Y_Anr)

    # Flow variables
    @variable(model, F_Er[1:P, 1:nrow(Er)] >= 0)
    @variable(model, F_Enr[1:P, 1:nrow(Enr)] >= 0)
    @variable(model, F_Er_swap[1:P, 1:nrow(Er_swap)] >= 0)
    @variable(model, F_Enr_swap[1:P, 1:nrow(Enr_swap)] >= 0)
    @variable(model, F_Ar[1:P, 1:nrow(Ar)] >= 0)
    @variable(model, F_Anr[1:P, 1:nrow(Anr)] >= 0)
    F = hcat(F_Er, F_Enr, F_Er_swap, F_Enr_swap, F_Ar, F_Anr)
    F_R = hcat(F_Er, F_Er_swap, F_Ar)
    F_NR = hcat(F_Enr, F_Enr_swap, F_Anr)

    ### Objective ###

    @objective(model, Min, sum(X_R*serv_cost + Y_tot*trav_cost))

    ### Constraint ###

    # Continuity constrain
    @constraint(model, continuity[p=1:P, i=1:nb_nodes],
        sum(map(arc->starts_in(arc,i,A) ? Y_tot[p,arc] : 0, 1:nrow(A)))
        + sum(map(arc->starts_in(arc,i,R) ? X_R[p,arc] : 0, 1:nrow(R)))
        == sum(map(arc->ends_in(arc,i,A) ? Y_tot[p,arc] : 0, 1:nrow(A)))
        + sum(map(arc->ends_in(arc,i,R) ? X_R[p,arc] : 0, 1:nrow(R)))
        )

    # Service constraint on arcs
    @constraint(model, service_Ar[arc=1:nrow(Ar)], sum(X_Ar[:,arc]) == 1)

    # Service constraint on edges
    @constraint(model, service_Er[arc=1:nrow(Er)], sum(X_Er[:,arc] + X_Er_swap[:,arc]) == 1)

    # Dumping constraint
    @constraint(model, dumping[p=1:P],
        sum(map(arc->starts_in(arc,depot,A) ? Y_tot[p,arc] : 0, 1:nrow(A)))
        +  sum(map(arc->starts_in(arc,depot,R) ? X_R[p,arc] : 0, 1:nrow(R)))
        <= 1
        )

    # Flow constraint 1
    @constraint(model, flow_1[p=1:P, i=[node for node in 1:nb_nodes if node!=depot]],
        sum(map(arc->ends_in(arc,i,A) ? F[p,arc] : 0, 1:nrow(A)))
        - sum(map(arc->starts_in(arc,i,A) ? F[p,arc] : 0, 1:nrow(A)))
        == sum(map(arc->ends_in(arc,i,R) ? X_R[p,arc]*demand[arc] : 0, 1:nrow(R)))
        )

    # Flow constraint 2
    @constraint(model, flow_2[p=1:P],
        sum(map(arc->starts_in(arc,depot,A) ? F[p,arc] : 0, 1:nrow(A)))
        == sum(X_R[p,:].*demand)
        )

    # Flow constraint 3
    @constraint(model, flow_3[p=1:P],
        sum(map(arc->ends_in(arc,depot,A) ? F[p,arc] : 0, 1:nrow(A)))
        == sum(map(arc->ends_in(arc,depot,R) ? X_R[p,arc]*demand[arc] : 0, 1:nrow(R)))
        )

    # Capacity constraint
    @constraint(model, capacity[p=1:P, arc=1:nrow(A)],
        F[p,arc] <= W*(Y_tot[p,arc]+X_tot[p,arc])
        )

    # Minimum vehicle constrain
    @constraint(model, min_vehicle,
        sum(map(arc->starts_in(arc,depot,A) ? sum(Y_tot[:,arc]) : 0, 1:nrow(A)))
        + sum(map(arc->starts_in(arc,depot,R) ? sum(X_R[:,arc]) : 0, 1:nrow(R)))
        >= ceil((sum(Er[:,:demand])+sum(Ar[:,:demand]))/W)
        )

    # Flow lower bound 1
    @constraint(model, flow_bound_1[p=1:P,arc=1:nrow(R)],
        F_R[p,arc] >= X_R[p,arc]*demand[arc]
        )

    # Flow lower bound 2
    @constraint(model, flow_bound_2[p=1:P,arc=1:nrow(NR)],
        F_NR[p,arc] >= Y_NR[p,arc]-1
        )

    # Symmetries breaking
    @constraint(model, symmetries[p=1:(P-1)],
        sum(map(arc->starts_in(arc,depot,A) ? Y_tot[p,arc] : 0, 1:nrow(A)))
        + sum(map(arc->starts_in(arc,depot,R) ? X_R[p,arc] : 0, 1:nrow(R)))
        >= sum(map(arc->starts_in(arc,depot,A) ? Y_tot[p+1,arc] : 0, 1:nrow(A)))
        + sum(map(arc->starts_in(arc,depot,R) ? X_R[p+1,arc] : 0, 1:nrow(R)))
        )

    ### Solve problem ###

    start = now()
    optimize!(model)
    stop = now()

    solving_time = stop-start

    ### Format output ###

    tours = []

    for p in 1:P

        cost = (value.(X_R)*serv_cost + value.(Y_tot)*trav_cost)[p]

        X = Dict(
            "req_arcs" => [value.(X_Ar[p, arc]) for arc in 1:nrow(Ar)],
            "req_edges" => [value.(X_Er[p, arc]) for arc in 1:nrow(Er)],
            "req_edges_swap" => [value.(X_Er_swap[p, arc]) for arc in 1:nrow(Er_swap)]
            )

        Y = Dict(
            "req_arcs" => [value.(Y_Ar[p, arc]) for arc in 1:nrow(Ar)],
            "noreq_arcs" => [value.(Y_Anr[p, arc]) for arc in 1:nrow(Anr)],
            "req_edges" => [value.(Y_Er[p, arc]) for arc in 1:nrow(Er)],
            "noreq_edges" => [value.(Y_Enr[p, arc]) for arc in 1:nrow(Enr)],
            "req_edges_swap" => [value.(Y_Er_swap[p, arc]) for arc in 1:nrow(Er)],
            "noreq_edges_swap" => [value.(Y_Enr_swap[p, arc]) for arc in 1:nrow(Enr)]
            )

        tour = Dict(
            "depot" => depot,
            "cost" => cost,
            "capacity" => sum(value.(X_R[p,:]).*demand),
            "X" => X,
            "Y" => Y
            )

        push!(tours, tour)
    end
    return(tours, solving_time)

end

max_stars_repo_name: TheoGuyard/Groomer-Optimization-Problem

max_issues_repo_name: TheoGuyard/Groomer-Optimization-Problem

max_forks_repo_name: TheoGuyard/Groomer-Optimization-Problem


text:
function readGraph(file::String)
    file = "C://Users//Antoine//Documents//MPRO//MLA//MLA//seance_3//instances//" * file
    if (!isfile(file))
        println("Je ne trouve pas le fichier")
        return
    end
    myFile=open(file)
    data=readlines(myFile)
    global n=parse(Int,data[1])
    global m=parse(Int,data[2])
    global adj=[]       #matrice d'adjacence
    global demande=zeros(n)     #demande
    for i in 3:3+m-1
        line=split(data[i]," ")
        u=parse(Int,line[1])
        #println("u : ",u+1)
        v=parse(Int,line[2])
        #println("v : ", v+1)
        push!(adj,v+1)
        push!(adj,u+1)
    end
    for i in 3+m:3+m+n-1
        line=split(data[i]," ")
        u=parse(Int,line[1])
        #println("u : ",u+1)
        d=parse(Int,line[2])
        #println("d: ",d)
        demande[u+1]=d
    end
    return n, m, adj, demande
end

max_stars_repo_name: boumpteryx/MLA

max_issues_repo_name: boumpteryx/MLA

max_forks_repo_name: boumpteryx/MLA


text:
@testset "prioritized_sweeping_sample_model" begin
    m = PrioritizedSweepingSampleModel(0.5)

    update!(m, (1, 1, 1.0, true, 2), 0.0)
    @test sample(m) === nothing

    update!(m, (1, 1, 1.0, true, 2), 1.0)
    @test sample(m) == (1, 1, 1.0, true, 2)

    update!(m, (1, 1, 1.0, true, 2), 1.0)
    update!(m, (2, 2, 2.0, true, 3), 1.1)
    @test sample(m) == (2, 2, 2.0, true, 3)
    @test sample(m) == (1, 1, 1.0, true, 2)
end


text:
function SeisFXDecon(d,param=Dict())
	#FX_DECON: SNR enhancement using fx-deconvolution.

	#  [DATA_f] = fx_decon(D1,D2,dt,lf,mu,flow,fhigh);
	# param should be defined, for example
	# param = Dict("dt"=>dt,"filter_length"=>lf,"mu"=>mu,"fmax"=>fhigh)

	#  OUT  de:     filtered data
	#
	#  Reference: Canales, 1984, Random noise reduction, 54.th. Ann. Internat.
	#             Mtg., Soc. Expl. Geophys., Expanded Abstracts, pp. 525-527
	#
	#  Note: Canales' method is modified to use non Toeplitz system of equations
	#        with backward and forward prediction filters
	#

	dt = get(param,"dt",0.002)
	filter_length = get(param,"filter_length",10)
	mu = get(param,"mu",0.01)
	nt = size(d,1)
	nx = size(d,2)
	nf = nt
	dw = 2. *pi/nf/dt
	nw = convert(Int,floor(nf/2)) + 1
	fmax = get(param,"fmax",convert(Int,floor(0.5/dt)))
	if(fmax*dt*nf < nw)
		iw_max = convert(Int,floor(fmax*dt*nf))
	else
		iw_max = convert(Int,floor(0.5/dt))
	end
	D = fft(d,1)
	Df = zeros(ComplexF64,size(D))
	Db = zeros(ComplexF64,size(D))
	for iw=1:iw_max
		y = vec(D[iw,:])
		yf = fxdecon(y,"f",filter_length,mu);
		yb = fxdecon(y,"b",filter_length,mu);
		Df[iw,:] = yf
		Db[iw,:] = yb
	end
	# symmetries
	for iw=nw+1:nf
		Df[iw,:] = conj(Df[nf-iw+2,:])
		Db[iw,:] = conj(Db[nf-iw+2,:])
	end
	dout = ( ifft(Df,1) .+ ifft(Db,1) )/ 2
	out = real(dout[1:nt,:])

	return out
end

function fxdecon(d,direction,filter_length,mu)
	nx = length(d);
	if (direction=="b")
		y  = d[1:nx-filter_length];
		C  = d[2:nx-filter_length+1];
		R  = d[nx-filter_length+1:nx];
		M = hankel(C,R);
	else
		y  = d[filter_length+1:nx,1];
		C  = d[filter_length:nx-1];
		R = reverse(d[1:filter_length]);
		M = toeplitz(C,R);
	end
	B = M'*M;
	beta = B[1,1]*mu/100
	ab = (B + beta*Matrix(I,filter_length,filter_length))\M'*y
	temp = M*ab
	if (direction=="b")
		d = [temp ; zeros(filter_length)]
	else
		d = [zeros(filter_length) ; temp]
	end

	return d
end

function hankel(c, r)

	nc = length(r)
	nr = length(c)
	if (nc > 1)
		c = [ c ; r[2:nc] ]
	end
	m = c[ones(Int,nr) * collect(Int,1:nc)' + collect(Int,0:nr-1)*ones(Int,nc)']
	m = reshape(m,nr,nc)

	return m
end

function toeplitz(c, r)

	nc = length(r)
	nr = length(c)
	m = zeros(ComplexF64,nr, nc);
	for i = 1:min(nc, nr)
		m[i:nr,i] .= c[1:nr-i+1]
	end
	for i = 1:min(nr, nc-1)
		m[i,i+1:nc] .= r[2:nc-i+1];
	end

	return m
end


text:
######################################################################
# greedy.jl
#
# Defines a greedy, info-theoretic policy
# Currently only considers a small set of the possible actions
######################################################################
struct GreedyPolicy <: Policy
    actions::Vector{Action}

    GreedyPolicy() = new()

    function GreedyPolicy(max_step::Real, n::Int, headings=0; stay=true)
        return new( make_action_list(max_step, n, headings, stay=stay) )
    end
    function GreedyPolicy(x::Vehicle, n::Int, headings=0; stay=true)
        return new( make_action_list(x.max_step, n, headings, stay=stay) )
    end
end

# loop over all actions.
# The one with smallest expected entropy is best
# We know this depends on sensor
function action(m::SearchDomain, x::Vehicle, o, f::AbstractFilter, p::GreedyPolicy)
    best_mi = -Inf
    best_a = (0.0, 0.0, 0.0)
    for a in p.actions
        # find out where a will take you
        xp = new_pose(m, x, a)
        # compute best mutual information
        mi = mutual_information(f, xp)
        #println("a = ", a)
        #println("\tmi = ", mi)
        if mi > best_mi
            best_mi = mi
            best_a = a
        end
    end
    return best_a
end


text:
module IBKR

using CxxWrap
using CxxWrap.CxxWrapCore: CxxInt
using Base.Threads: Event

using Unitful
using UnitfulAssets
using Dates
using MacroTools: @forward

using ..Emporos: PACKAGE_ROOT

export IB

const IB_DEFAULT_PORT = 7497
const IB_DEFAULT_HOST = "127.0.0.1"
const IB_DEFAULT_CLIENT_ID = 0

include("IBKRCore/IBKRCore.jl")
using .IBKRCore

include("types.jl")

end


text:
#=
Copyright (c) 2015, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
=#

module DebugMsg

export init

"""
When this module is first loaded, we check if PROSPECT_DEV_MODE is set in environment.
If it is not, then all debug messages will be surpressed.
"""
const PROSPECT_DEV_MODE=haskey(ENV, "PROSPECT_DEV_MODE")

"""
A module using DebugMsg must call DebugMsg.init(), which expands to several local definitions
that provide three functions: set_debug_level, dprint, dprintln.
"""
function init()
  m = current_module()
  Base.eval(m, :(DEBUG_LVL = 0))
  if PROSPECT_DEV_MODE
    Base.eval(m, :(function set_debug_level(l) global DEBUG_LVL = l end))
    Base.eval(m, :(function dprint(l, msg...) if l <= DEBUG_LVL print(msg...) end end))
    Base.eval(m, :(function dprintln(l, msg...) if l <= DEBUG_LVL println(msg...) end end))
    Base.eval(m, :(macro dprint(l, msg...) esc(Expr(:call, :dprint, l, msg...)) end))
    Base.eval(m, :(macro dprintln(l, msg...) esc(Expr(:call, :dprintln, l, msg...)) end))
  else
    Base.eval(m, :(function set_debug_level(l) end))
    Base.eval(m, :(function dprint(l, msg...) end))
    Base.eval(m, :(function dprintln(l, msg...) end))
    Base.eval(m, :(macro dprint(l, msg...) end))
    Base.eval(m, :(macro dprintln(l, msg...) end))
end
end

end


text:
using Base.Cartesian

"""
    Sequence{N,T}(::AbstractArray)

A `Sequence` is a thin wrapper around a multi-dimensional array that
allows you to index it like a vector. For example, the following
code shows a 10-dimensional time series, sampled at 100 time points:

```
data = randn(10,100)
seq = Sequence(data)
seq[1] == data[:,1] # true
```

This generalizes to higher-order arrays. Consider a time series
where a 10x10 matrix of data is collected at 100 time points:

```
data = randn(10,10,100)
seq = Sequence(data)
seq[1] == data[:,:,1] # true
```
"""
struct Sequence{N,T} <: AbstractArray{T,1}
    val::AbstractArray{T,N}
end

Base.size(x::Sequence{N}) where N = (size(x.val,N),)
Base.eltype(x::Sequence{N,T}) where {N, T} = T

@generated function Base.getindex(x::Sequence{N}, i) where N
    :( x.val[@ntuple($N, (n-> n==$N ? i : Colon()))...] )
end

@generated function Base.setindex!(x::Sequence{N}, val, i) where N
    :( x.val[@ntuple($N, (n-> n==$N ? i : Colon()))...] = val )
end

function seq_to_array(seq::Sequence{N}) where N
    return cat(seq..., dims=N)
end


text:
function LimitAngle(arg0::S1Point, arg1::jboolean, arg2::jdouble)
    return LimitAngle((S1Point, jboolean, jdouble), arg0, arg1, arg2)
end

function copy_self(obj::LimitAngle)
    return jcall(obj, "copySelf", LimitAngle, ())
end

function empty_hyperplane(obj::LimitAngle)
    return jcall(obj, "emptyHyperplane", SubLimitAngle, ())
end

function get_location(obj::LimitAngle)
    return jcall(obj, "getLocation", S1Point, ())
end

function get_offset(obj::LimitAngle, arg0::Point)
    return jcall(obj, "getOffset", jdouble, (Point,), arg0)
end

function get_reverse(obj::LimitAngle)
    return jcall(obj, "getReverse", LimitAngle, ())
end

function get_tolerance(obj::LimitAngle)
    return jcall(obj, "getTolerance", jdouble, ())
end

function is_direct(obj::LimitAngle)
    return jcall(obj, "isDirect", jboolean, ())
end

function project(obj::LimitAngle, arg0::Point)
    return jcall(obj, "project", Point, (Point,), arg0)
end

function same_orientation_as(obj::LimitAngle, arg0::Hyperplane)
    return jcall(obj, "sameOrientationAs", jboolean, (Hyperplane,), arg0)
end

function whole_hyperplane(obj::LimitAngle)
    return jcall(obj, "wholeHyperplane", SubLimitAngle, ())
end

function whole_space(obj::LimitAngle)
    return jcall(obj, "wholeSpace", ArcsSet, ())
end


text:
using StatsBase
using DSP

"""
    surroplot(x, s; W = 100, gfs = 8, lfs = 6,
        cx = :black, cs = :red, size = (400, 600); kwargs...)

Plot a time series along with its surrogate realization `s`, and compare the
periodogram and histogram of the two time series.

## Arguments

- **`x`**: the time series for which to generate a surrogate.

- **`s`** is the surrogate realization of the time series.

## Keyword arguments

- **`W`**: Sets the number of windows for binning the periodogram.

- **`gfs`** and **`lfs`**: Fontsizes of the guides and legends, respectively.

- **`cx`** and **`cs`**: Colors of the original and the surrogate time series, respectively.

- **`size`**: A tuple giving the size of the assembled plot.

- **`nbins`**: The number of bins for the histograms.

- **`kwargs`**: Plots.jl keyword arguments that are supplied to the final `plot` call that assembles the subplots.
"""
function surroplot(x, s; W = 100, gfs = 8, lfs = 6,
        cx = :black, cs = :red, size = (500, 600),
        nbins = 50, kwargs...)

    # Time series
    p1 = Plots.plot()
    Plots.plot!(x, label = "", c = cx);
    Plots.plot!(s, label = "", c = cs)

    # Autocorrelation
    p2 = Plots.plot()
    Plots.plot!(autocor(x), label = "", c = cx)
    Plots.plot!(autocor(s), label = "", c = cs)

    # Binned multitaper periodograms
    p, psurr = DSP.mt_pgram(x), DSP.mt_pgram(s)
    p3 = Plots.plot()
    Plots.plot!(interp([x for x in p.freq], p.power, W), label = "", c = cx, yaxis = :log10)
    Plots.plot!(interp([x for x in psurr.freq], psurr.power, W), label = "", c = cs, yaxis = :log10)

    # Histograms
    p4 = Plots.plot()
    Plots.histogram!(x, label = "Original", alpha = 0.5, nbins = nbins, c = cx)
    Plots.histogram!(s, label = "Surrogate", alpha = 0.5, nbins = nbins, c = cs)

    Plots.xlabel!(p1, "Time step")
    Plots.ylabel!(p1, "Value")

    Plots.xlabel!(p2, "Lag")
    Plots.ylabel!(p2, "Autocorrelation")

    Plots.xlabel!(p3, "Binned frequency")
    Plots.ylabel!(p3, "Power")

    Plots.xlabel!(p4, "Binned value")
    Plots.ylabel!(p4, "Frequency")

    l = Plots.@layout [a{0.3h}; b{0.25h}; c{0.25h}; d{0.2h}]
    Plots.plot(p1, p2, p3, p4;
                layout = l,
                guidefont = (gfs, gfs, gfs, gfs),
                legendfont = (lfs, lfs, lfs, lfs),
                size = size,
                kwargs...
                )
end

export surroplot


text:
using CompileBot, Test
import CompileBot.goodjoinpath
stripall(x::String) = replace(x, r"\s|\n"=>"")

snoopcompiledir = pwd()
bottestdir = GoodPath(@__DIR__)

@testset "bot" begin

    @testset "add_includer" begin
        package_name = "TestPackage0"
        package_path = goodjoinpath(bottestdir,"$package_name.jl","src","$package_name.jl")
        includer_path = goodjoinpath(dirname(package_path), "precompile_includer.jl")

        CompileBot.add_includer(package_name, package_path)

        @test occursin("include(\"precompile_includer.jl\")", stripall(Base.read(package_path, String)))
    end

    @testset "precompile de/activation" begin
        package_name = "TestPackage0"
        package_path = goodjoinpath(bottestdir,"$package_name.jl","src","$package_name.jl")
        precompiles_rootpath = goodjoinpath(bottestdir,"$package_name.jl","deps/SnoopCompile/precompile")
        includer_path = goodjoinpath(dirname(package_path), "precompile_includer.jl")

        CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, nothing, nothing, nothing, nothing)

        CompileBot.precompile_deactivator(package_path)
        @test occursin("should_precompile=false", stripall(Base.read(includer_path, String)))

        CompileBot.precompile_activator(package_path)
        includer_text = stripall(Base.read(includer_path, String))
        @test occursin("should_precompile=true", includer_text)

        rm(includer_path)
    end

    @testset "precompile new_includer_file" begin
        package_name = "TestPackage0"
        package_path = goodjoinpath(bottestdir,"$package_name.jl","src","$package_name.jl")
        precompiles_rootpath = "$(dirname(dirname(package_path)))/deps/SnoopCompile/precompile"
        precompiles_rootpath_rel = GoodPath(relpath( precompiles_rootpath , dirname(package_path)))
        includer_path = goodjoinpath(dirname(package_path), "precompile_includer.jl")

        @testset "no os, no else_os, no version, no else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, nothing, nothing, nothing, nothing)
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=false", includer_text)
            @test occursin("ismultiversion=false", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else

            end # precompile_enclosure
            """), includer_text)
        end

        @testset "yes os, no else_os, no version, no else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, ["linux", "windows"], nothing, nothing, nothing)
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=true", includer_text)
            @test occursin("ismultiversion=false", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if Sys.islinux()
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel/linux/precompile_$package_name.jl")
                        _precompile_()
                    end
                elseif Sys.iswindows()
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel/windows/precompile_$package_name.jl")
                        _precompile_()
                    end
                else
                end

            end
            """), includer_text)
        end

        @testset "yes os, yes else_os, no version, no else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, ["linux", "windows"], "linux", nothing, nothing)
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=true", includer_text)
            @test occursin("ismultiversion=false", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if Sys.islinux()
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel/linux/precompile_$package_name.jl")
                        _precompile_()
                    end
                elseif Sys.iswindows()
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel/windows/precompile_$package_name.jl")
                        _precompile_()
                    end
                else
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel/linux/precompile_$package_name.jl")
                        _precompile_()
                    end
                end

            end # precompile_enclosure
            """), includer_text)
        end

        @testset "no os, no else_os, yes version, no else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, nothing, nothing, [v"1.2",v"1.5.0"], nothing)
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=false", includer_text)
            @test occursin("ismultiversion=true", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel//1.2/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel//1.2/precompile_$package_name.jl")
                        _precompile_()
                    end
                elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel//1.5/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel//1.5/precompile_$package_name.jl")
                        _precompile_()
                    end
                else
                end

            end # precompile_enclosure
            """), includer_text)
        end

        @testset "no os, no else_os, yes version, yes else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, nothing, nothing, [v"1.2",v"1.5.0"],v"1.5.0")
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=false", includer_text)
            @test occursin("ismultiversion=true", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel//1.2/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel//1.2/precompile_$package_name.jl")
                        _precompile_()
                    end
                elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel//1.5/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel//1.5/precompile_$package_name.jl")
                        _precompile_()
                    end
                else
                    @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel//1.5/precompile_$package_name.jl"))
                        include("$precompiles_rootpath_rel//1.5/precompile_$package_name.jl")
                        _precompile_()
                    end
                end

            end # precompile_enclosure
            """), includer_text)
        end

        @testset "yes os, yes else_os, yes version, no else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, ["linux", "windows"], "linux", [v"1.2",v"1.5.0"], nothing)
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=true", includer_text)
            @test occursin("ismultiversion=true", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if Sys.islinux()
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                    end

                elseif Sys.iswindows()
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                    end

                else
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                    end

                end

            end # precompile_enclosure
            """), includer_text)
        end

        @testset "yes os, yes else_os, yes version, yes else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, ["linux", "windows"], "linux", [v"1.2",v"1.5.0"],v"1.5.0")
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=true", includer_text)
            @test occursin("ismultiversion=true", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if Sys.islinux()
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    end

                elseif Sys.iswindows()
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    end

                else
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    end

                end

            end # precompile_enclosure
            """), includer_text)
        end

        @testset "yes os, no else_os, yes version, no else_version" begin
            CompileBot.new_includer_file(package_name, package_path, precompiles_rootpath, ["linux", "windows"], nothing, [v"1.2",v"1.5.0"], nothing)
            includer_text = stripall(Base.read(includer_path, String))
            @test occursin("ismultios=true", includer_text)
            @test occursin("ismultiversion=true", includer_text)

            @test occursin(stripall("""
            @static if !should_precompile
                # nothing
            elseif !ismultios && !ismultiversion
                @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/precompile_$package_name.jl"))
                    include("$precompiles_rootpath_rel/precompile_$package_name.jl")
                    _precompile_()
                end
            else
                @static if Sys.islinux()
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/linux/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                    end

                elseif Sys.iswindows()
                    @static if v"1.2.0-DEV" <= VERSION <= v"1.2.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.2/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.2/precompile_$package_name.jl")
                            _precompile_()
                        end
                    elseif v"1.5.0-DEV" <= VERSION <= v"1.5.999"
                        @static if isfile(joinpath(@__DIR__, "$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl"))
                            include("$precompiles_rootpath_rel/windows/1.5/precompile_$package_name.jl")
                            _precompile_()
                        end
                    else
                    end

                else
                end

            end # precompile_enclosure
            """), includer_text)
        end
        rm(includer_path)
    end

    using Pkg
    package_rootpath = String[]
    for (i, package_name) in enumerate(["TestPackage1", "TestPackage2", "TestPackage3", "TestPackage0", "TestPackage5"])
        Pkg.develop(PackageSpec(path=joinpath(bottestdir,"$package_name.jl")))
        push!(package_rootpath, goodjoinpath(bottestdir,"$package_name.jl"))
    end
    @show package_rootpath

    @testset "snoop_bot" begin

        include("$(package_rootpath[1])/deps/SnoopCompile/snoop_bot.jl")

        @test isfile("$(package_rootpath[1])/deps/SnoopCompile/precompile/precompile_TestPackage1.jl")

        @test isfile("$(package_rootpath[1])/.gitattributes")
        rm("$(package_rootpath[1])/.gitattributes", force=true)

        precompile_text = Base.read("$(package_rootpath[1])/deps/SnoopCompile/precompile/precompile_TestPackage1.jl", String)

        @test occursin("hello", precompile_text)
        @test occursin("domath", precompile_text)
    end

    @testset "snoop_bench" begin
        include("$(package_rootpath[1])/deps/SnoopCompile/snoop_bench.jl")
    end

    @testset "snoop_bot_multios" begin
        os, osfun = CompileBot.detectOS()

        include("$(package_rootpath[2])/deps/SnoopCompile/snoop_bot.jl")

        @test isfile("$(package_rootpath[2])/.gitattributes")
        rm("$(package_rootpath[2])/.gitattributes", force=true)

        @test isfile("$(package_rootpath[2])/deps/SnoopCompile/precompile/$os/precompile_TestPackage2.jl")

        precompile_text = Base.read("$(package_rootpath[2])/deps/SnoopCompile/precompile/$os/precompile_TestPackage2.jl", String)

        if os == "windows"
            @test occursin("hello2", precompile_text)
            @test !occursin("domath2", precompile_text)
        else
            @test !occursin("hello2", precompile_text)
            @test occursin("domath2", precompile_text)
        end
    end

    @testset "snoop_bench-multios" begin
        include("$(package_rootpath[2])/deps/SnoopCompile/snoop_bench.jl")
    end

    @testset "snoop_bot_multiversion" begin
        os, osfun = CompileBot.detectOS()

        include("$(package_rootpath[3])/deps/SnoopCompile/snoop_bot.jl")

        @test isfile("$(package_rootpath[3])/.gitattributes")
        rm("$(package_rootpath[3])/.gitattributes", force=true)

        @test isfile("$(package_rootpath[3])/deps/SnoopCompile/precompile/$(CompileBot.VersionFloat(VERSION))/precompile_TestPackage3.jl")

        precompile_text = Base.read("$(package_rootpath[3])/deps/SnoopCompile/precompile/$(CompileBot.VersionFloat(VERSION))/precompile_TestPackage3.jl", String)

        if VERSION > v"1.3"
            @test occursin("hello3", precompile_text)
            @test !occursin("domath3", precompile_text)
            @test !occursin("multiply3", precompile_text)
        elseif VERSION > v"1.2"
            @test !occursin("hello3", precompile_text)
            @test occursin("domath3", precompile_text)
            @test !occursin("multiply3", precompile_text)
        else
            @test !occursin("hello3", precompile_text)
            @test !occursin("domath3", precompile_text)
            @test occursin("multiply3", precompile_text)
        end
    end

    if VERSION <= v"1.5.0"
        @testset "snoop_bench-multiversion" begin
            include("$(package_rootpath[3])/deps/SnoopCompile/snoop_bench.jl")
        end
    else
        @warn "else version is set to 1.2, so we should not run the benchmark test on nightly, when we have not generated such files yet (unlike in the realworld tests)."
    end

    @testset "Nothing is generated" begin

        include("$(package_rootpath[4])/deps/SnoopCompile/snoop_bot.jl")

        @test isfile("$(package_rootpath[4])/deps/SnoopCompile/precompile/precompile_TestPackage0.jl")

        precompile_text = Base.read("$(package_rootpath[4])/deps/SnoopCompile/precompile/precompile_TestPackage0.jl", String)

        @test occursin(stripall("""
        function _precompile_()
            # nothing
        end
        """), stripall(precompile_text))
    end

    @testset "Nothing is generated" begin
        include("$(package_rootpath[4])/deps/SnoopCompile/snoop_bench.jl")
    end

    @testset "yaml os and version parse" begin
        include("$(package_rootpath[5])/deps/SnoopCompile/snoop_bot.jl")
        for bc in bcs
            @test [v"1.5.0", v"1.3.1"] == bc.version
            @test ["ubuntu-latest", "windows-latest", "macos-latest"] == bc.os
        end
    end

    # Clean Test remainder
    for (i, package_name) in enumerate(["TestPackage1", "TestPackage2", "TestPackage3", "TestPackage0", "TestPackage5"])
        Pkg.rm(package_name)
        main_file= goodjoinpath(package_rootpath[i], "src/$package_name.jl")
        run(`git checkout -- $main_file`)
    end
    Pkg.resolve()
    project_toml_path = "$(dirname(bottestdir))/Project.toml"
    run(`git checkout -- $project_toml_path`)

    # just in case
    cd(snoopcompiledir)

    include("botutils.jl")
end