text:
#general function to validate dates in a time series
#dates should already be unique and sorted
function validatedates(dates::Vector{Date};
    frequency::NSymbol=throw("frequency is required"), validateexactfrequency::Bool=false)
  @assert allunique(dates)
  @assert issorted(dates)

  (frequency === nothing) && return true

  #not much to do with daily data, we already checked the data was unique
  if Symbol(lowercase(string(frequency))) == :day
    (!validateexactfrequency) || throw("Exact validation of daily frequency not supported")
    return true

  #weekly data should have a minimum frequency of 7 days
  elseif Symbol(lowercase(string(frequency))) == :week
    dateseow = (lastdayofweek).(dates)
    #=datesyw = broadcast(dates) do d
      wd = week(d)
      if (wd==1) && (year(d) ≠ year(lastdayofweek(d)))
        return year(lastdayofweek(d)) .+ wd ./ 100
      elseif (wd ≥ 52) && (year(d) ≠ year(firstdayofweek(d)))
        return year(firstdayofweek(d)) .+ wd ./ 100
      end
      return year(d) .+ wd ./ 100
    end=#
    if !allunique(dateseow)
      nonuniquedateindices = nonunique(DataFrame(datesyw=dateseow))
      nonuniquedates = dates[nonuniquedateindices]
      throw("weeks and years of weekly data are not unique. Nonunique dates:
        $(collect(zip(dates, dateseow))[(d->d∈nonuniquedates).(dates)])")
    end
    if validateexactfrequency #make sure there are no missing or misaligned weeks
      validdates= firstdayofweek(minimum(dates)):Week(1):lastdayofweek(maximum(dates))
      validdateseow = lastdayofweek.(validdates)
      mismatches = dateseow .≠ validdateseow
      sum(mismatches)==0 || throw(
        "Failed to validate weekly dates with $(sum(mismatches)) mismatches.
        List of mismatches (given, minimum(dates):Week(1):maximum(dates)):
          $(collect(zip(dateseow, validdateseow))[mismatches])")
    end
  elseif Symbol(lowercase(string(frequency))) == :month
    datesym = (d->year(d) .+ month(d) ./ 100).(dates)
    allunique(datesym) || throw("months and years of monthly data are not unique")
    if validateexactfrequency #we don't insist on equality of dates, just year-month
      validdates= firstdayofmonth(minimum(dates)):Month(1):lastdayofmonth(maximum(dates))
      validdatesym = (d->year(d) .+ month(d) ./ 100).(validdates)
      try
        mismatches = datesym .≠ validdatesym
        sum(mismatches)==0 || throw(error("
          Failed to validate monthly dates with $(sum(mismatches)) mismatches.
          List of mismatches (given, minimum(dates):Month(1):maximum(dates)):
            $(collect(zip(datesym, validdatesym))[mismatches])"))
      catch err
        debugdf = vcat(DataFrame(dates=dates, datesym=datesym),
          DataFrame(validdates=validdates, validdatesym=validdatesym), cols=:union)
        debugdf |> CSV.write("$(PARAM[:testpath])\\validdatesym_dump.csv")
        throw(err)
      end
    end
  else
    throw("unrecognized date frequency $frequency")
  end
  return nothing
end

#used to clean up names in a dataframe
function cleanname(dirty::T)::T where T
  local str::String
  local clean::T #holds the resulting answer

  str = string(dirty)

  str = replace(str, "-"=>"")
  str = replace(str, " "=>"")
  str = replace(str, "_"=>"")
  str = lowercase(str)

  T==String && return str
  return T(clean)
end

#same as above but always returns a symbol
cleanpropertyname(dirty) = Symbol(cleanname(dirty))

parseormissing(::Missing, s::String) = missing

#parses strings to a type or makes missing
function parseormissing(::Type{T}, s::String) where T<:Any
  val::Union{T,Nothing} = tryparse(T, s)

  isnothing(val) && (return missing)
  return val
end

#candidate for Finometrics
function winsorizewithin!(df::DataFrame;
    Fsource::Symbol=error("Fsource is required"),
    prop::Float64=error("prop is required"),
    Fgroup::Symbol=error("Fgroup is required"),
    twosided=true,
    Fnew::Symbol = Symbol("WX$Ftarget"))

  df[!, Fnew] = similar(df[!, Fsource])
  sdfs = groupby(df, Fgroup)
  Threads.@threads for k ∈ keys(sdfs)
    sdf = sdfs[k]
    (sum((!ismissing).(sdf[!,Fsource])) == 0) && continue
    #we can check the winsorization was performed as expected by recording the percentiles
    oldptile = (quantile(skipmissing(sdf[!, Fsource]),prop),
      quantile(skipmissing(sdf[!, Fsource]), 1-prop))

    sdf[:, Fnew] .= winsorizequantile(sdf[!, Fsource], prop; twosided)

    #perform the check
    newminmax = (minimum(skipmissing(sdf[!, Fnew])), maximum(skipmissing(sdf[!, Fnew])))
    @assert all(oldptile .≈ newminmax) || all(oldptile .≈ reverse(newminmax))
  end
  return nothing
end

#cleans up the names after a call to aggregate
@inline nofunction(s::Symbol, todelete::String) = Symbol(replace(string(s), todelete=>""))
@inline nofunction(s::String, todelete::String) = replace(s, todelete=>"")

finiteormissing(::Missing) = missing
function finiteormissing(f::Real)
  (isfinite(f)) && return f
  return missing
end

#converts gzip to lz4
function gz2zstd(file::String; filetype::String = "csv", location::Union{String,Nothing} = nothing,
  gzextension::String = "gz", zstdextension::String = "zstd",
  deleteold::Bool = false, level=1)

  local prefix::String

  prefix = isnothing(location) ?  "" : "$location\\"
  infile::String = "$prefix$file.$filetype.$gzextension"
  outfile::String = "$prefix$file.$filetype.$zstdextension"

  isfile(infile) || error("file not found. Full path: $prefix$file.$filetype.$gzextension")

  #Below doesnt work
  indata = open(infile)
  outdata = open(outfile, "w")
  s = GzipDecompressorStream(ZstdCompressorStream(outdata, level=level))

  try
    write(s, indata)
  finally
    close(s)
  end
end

#use this to clear a dictionary
function clearcollection(c::AbstractDict)
  for i ∈ 1:length(c)
    pop!(c)
  end
end

#check if all columns in a df or subdf are equal
#extra logic is to handle missing values
@inline function eachrowequal(df::AbstractDataFrame;
  cols::Vector{Symbol}=propertynames(df))::Bool
  for c ∈ eachcol(view(df, :, cols))
    completec = collect(skipmissing(c))
    (length(completec) == 0) && continue #all missing case

    #check for equality
    if  (length(completec) == length(c)) && (all(c[1] .== c))
     continue
    end

    return false
  end
  return true
end

@inline cleandate(d::Date) = replace("$d", "-"=>"")

#a vectorized exponential function
#handy for cuda work
vecexp(v::CuVector) = (CUDA.exp).(v)
vecexp(v::AbstractVector) = (exp).(v)

function pressakey()
  print("press any key to continue")
  read(stdin,1)
  return nothing
end

#this may allow for gpu toggling
maybegpu(obj::AbstractVector, ::Type{T}, ::Val{true}) where T = CuVector{T}(obj)
maybegpu(obj::AbstractMatrix, ::Type{T},  ::Val{true}) where T = CuMatrix{T}(obj)
maybegpu(obj, ::Type{T}, ::Val{false}) where T = obj
fluxgpu(obj, ::Type{T}=PARAM[:fluxtype]) where T<:Real = maybegpu(obj, T, Val(PARAM[:fluxgpu]))

#compute the jacobian from the pullback
function jacobian(f, x, Π)
  _, back = Zygote.pullback(()->f(x),Π)

  return back(ones(length(x))) #a vector of 1s evaluates df/dx|x
end

#maps the indices of a shape to its corresponding linear indices in Π
function map2linear(start::Int, dims::Tuple)
  N::Int = prod(dims)
  lins::Vector{Int} = collect(1:N) .+ (start-1)
  linmap = reshape(lins, dims)

  #this should be true, as vec should make this an identity
  @assert vec(linmap) == lins
  return start+N, linmap
end

#this utility re-interprets the object(!)
#the object MUST remain referenced, or bad things will happen
#tries to do some basic safety checks, but its still possible to screw things up
function less_unsafe_wrap(::Type{Tdest};
  source::Vector = error("src vector is required"),
  start::Int = error("start is required"),
  dims::Tuple)::Tdest where Tdest<:AbstractArray

  Ndat = prod(dims)

  T = eltype(Tdest)
  (eltype(source) == T) || error("eltype of src must be of same type as T")

  #this has the effect of making sure we are getting space from somewhere that exists
  protowrap::SubArray = view(source, start:(start + Ndat -1))
  @assert length(protowrap) == Ndat

  p = pointer(source, start)
  wrap::Tdest = unsafe_wrap(Tdest, p, dims)

  #final checks
  @assert sum(vec(protowrap) .== vec(wrap)) == Ndat

  linmap = map2linear(start, dims)
  #return the object
  return wrap
end

#CUDA version of the above
#WARNING- I think something is wrong- consider not using this
function less_unsafe_wrap(::Type{Tdest};

  source::AbstractVector = error("src vector is required"),
  start::Int = error("start is required"),
  dims::Tuple)::Tdest where Tdest<:CuArray
  @warn("Possible race error in less_unsafe_wrap- function is potentially broken.
    Consider not using.")

  Ndat = prod(dims)

  T = eltype(Tdest)
  (eltype(source) == T) || error("eltype of src must be of same type as T")

  #this has the effect of making sure we are getting space from somewhere that exists
  protowrap = view(source, start:(start + Ndat -1))
  @assert length(protowrap) == Ndat

  #a final check
  p = CUDA.pointer(source, start)
  #@info typeof(p)
  wrap::Tdest = CUDA.unsafe_wrap(CuArray, p, dims)
  @assert sum(vec(protowrap|>Array) .== vec(wrap|>Array)) == Ndat

  return wrap
end

#nice printing of matrices
printm(m) = show(IOContext(stdout, :limit=>false), MIME"text/plain"(), m)
function printmln(m)
  show(IOContext(stdout, :limit=>false), MIME"text/plain"(), m)
  println()
end

#if createa a labelling string if the dates are constricted
function boundrangestr(;
    lowerdatebound::NDate=PARAM[:lowerdatebound],
    upperdatebound::NDate=PARAM[:upperdatebound])
  lowerdatestr = lowerdatebound === nothing ?  "" : "_$(Dates.format(lowerdatebound,"yymd"))"
  upperdatestr = upperdatebound === nothing ?  "" : "_$(Dates.format(upperdatebound,"yymd"))"
  return "$lowerdatestr$upperdatestr"
end

#adds zeros at the end of a matrix
#used in hyperreg
function pad0(M::TM, trows::Int, ::Type{T} = eltype(TM)) where {TM<:AbstractMatrix, T}
  Mrows = size(M,1)
  (Mrows == trows) && return (view(M,:,:), deepcopy(M))

  padded = vcat(M, TM(zeros(T, trows-size(M,1), size(M,2))))
  sM = view(padded, 1:size(M,1), 1:size(M,2))
  return (sM, padded)
end
function pad0(V::TV, trows::Int, ::Type{T} = eltype(TV)) where {TV<:AbstractVector, T}
  NV::Int = length(V)
  (NV == trows) && return (view(V,:), deepcopy(V))

  padded = vcat(V, TV(zeros(T, trows-NV)))
  sV = view(padded, 1:NV)
  return (sV, padded)
end

Base.ones(::Type{T}, n::Int, ::Type{<:AbstractVector}) where {T} = ones(T,n)
Base.ones(::Type{T}, n::Int, m::Int, ::Type{<:AbstractMatrix}) where {T} = ones(T,n,m)
Base.ones(::Type{T}, dims::Tuple, ::Type{<:AbstractArray}) where {T} = ones(T,dims)
Base.ones(::Type{T}, n::Int, ::Type{<:CuVector}) where {T} = CUDA.ones(T,n)
Base.ones(::Type{T}, n::Int, m::Int, ::Type{<:CuMatrix}) where {T} = CUDA.ones(T,n,m)
Base.ones(::Type{T}, dims::Tuple, ::Type{<:CuMatrix}) where {T} = CUDA.ones(T,dims)

Base.show(io, M::CUDA.CUSPARSE.CuSparseMatrixCSR{Float32}) = Base.show(io,Matrix(M))
Base.show(io, V::CUDA.CUSPARSE.CuSparseVector{Float32}) = Base.show(io,Matrix(V))

#these are basicalyl convert methods that only create a copy if necessary
Matrix!(m::Matrix) = m
Matrix!(m::TM, ::Type{T}=eltype(TM)) where {TM<:AbstractMatrix, T} = m |> Matrix{T}

Vector!(v::Vector) = v
Vector!(v::TV, ::Type{T}=eltype(TV)) where {TV<:AbstractVector, T} = v |> Vector{T}
T!(obj::T,::Type{T}) where T = obj
T!(obj::U, ::Type{T}) where {U,T} = obj |> T

#expensive versions of cumprod(_,dims=2) to work around Zygote's bugs and quirks
#these is terrible and should go away once cumprod starts working with Zygote
function _cumprodbyrow(M::CuMatrix)
  cols = (i->CUDA.prod(M[:,1:i], dims=2)).(1:size(M,2))
  #CUDA.reduce(hcat, cols)
  CUDA.hcat(cols...)
end

_cumprodbyrow(M::Matrix) = hcat((i->prod(M[:,1:i], dims=2)).(1:size(M,2))...)

function cumprodbyrow(M::TM, ::Type{T}=eltype(M);
  limitA::Bool = PARAM[:iterlimitA],
  growthtype::Symbol = PARAM[:itergrowthtype],
  largelimit = T <: Float64 ? LARGE_VAL : LARGE_VAL32,
  smalllimit = T <: Float64 ? SMALL_VAL : SMALL_VAL32
  ) where {TM, T}

  if limitA
    if growthtype === :log
      return limitcumprodbyrow(M, largelimit, smalllimit)
    else
      return limitcumprodbyrow(M, largelimit)
    end
  end

  return _cumprodbyrow(M)
end

#bounds cumprod
function limitcumprodbyrow(M::TM, limit::T, ::Type{T}=eltype(TM);
   init=ones(T,size(M,1))) where {TM<:Matrix,T}

  function checklimit(x, y)
    xy = x * y
    ifelse(abs(xy) < limit, xy, limit*sign(xy))
  end

  cumprodcol(c1,c2) = map(checklimit, c1, c2)

  cols = eachcol(M) |> collect
  return reduce(hcat, Iterators.accumulate(cumprodcol,cols, init=init))
end

#bounds cumprod if we are working on a log scale
function limitcumprodbyrow(M::TM, largelimit::T, smalllimit::T, ::Type{T}=eltype(TM);
   init=ones(T,size(M,1))) where {TM<:Matrix,T}

  checklimit(x, y)= max(min(x * y, largelimit), smalllimit)
  cumprodcol(c1,c2) = map(checklimit, c1, c2)

  cols = eachcol(M) |> collect
  return reduce(hcat, Iterators.accumulate(cumprodcol,cols, init=init))
end

limitcumprodbyrow(M::TM, limit::T, ::Type{T}=eltype(TM)
  ) where {TM<:CuMatrix,TV, T} = (
    limitcumprodbyrow(M |> Matrix{T}, limit) |> TM)
limitcumprodbyrow(M::TM, largelimit::T, smalllimit::T, ::Type{T}=eltype(TM)
  ) where {TM<:CuMatrix,TV, T} = (
    limitcumprodbyrow(M |> Matrix{T}, largelimit, smalllimit) |> TM)
#testing for cumprodbyrow
function testcumprodbyrow()
  M = rand(10,100)
  Mcu = M |> CuMatrix{Float64}

  print("Testing cumprod....")
  @assert cumprodbyrow(M, limitA=false) ≈ cumprod(M, dims=2)
  @assert cumprodbyrow(Mcu, limitA=false) ≈ cumprod(Mcu, dims=2)

  M = [1.0 10.0 -10.0 10.0; 1.0 10.0 -0.01 10.0]

  largelimit = 1.0
  growthtype=:identity
  Mver = hcat(Iterators.accumulate((x,y)->
    ((xᵢ,yᵢ)-> abs(xᵢ * yᵢ) < largelimit ? xᵢ * yᵢ : largelimit * sign(xᵢ * yᵢ)).(x,y),
    eachcol(M), init=[1.0,1.0])...)
  (cumprodbyrow(M, limitA=true; largelimit, growthtype) ≈ Mver) || error("cumprodbyrow ≈/ Mver
    cumprodbyrow = $(cumprodbyrow(M, limitA=true; largelimit, growthtype))\nM=$M\nMver=$Mver")

  smalllimit = -1.0
  growthtype=:log
  Mver = hcat(Iterators.accumulate((x,y)->
    ((xᵢ,yᵢ)-> max(min(xᵢ*yᵢ,largelimit), smalllimit)).(x,y),
    eachcol(M), init=[1.0,1.0])...)
  (cumprodbyrow(M, limitA=true; largelimit, smalllimit, growthtype) ≈ Mver) || error("cumprodbyrow ≈/ Mver
    cumprodbyrow = $(cumprodbyrow(M, limitA=true; largelimit, smalllimit, growthtype))\nM=$M\nMver=$Mver")

  @info "Passed tests in testcumprodbyrow"
end

#this is the sign command without a 0
signsans0(x::T) where T = (x≥zero(T))*T(2.0)-T(1.0)

#this is a function for converting a CuArray to an Array in a Zygote-safe manner
zygotedevice2host(M::TM, ::Type{T}=eltype(TM)
  ) where {TM, T<:Real} = copyto!(Zygote.Buffer(Array{T}(undef, size(M))), M) |> copy

zygotecuones(::Type{T}, N) where T<:Real = ones(N) |> CuVector{T}

#a recursive parsing routine for converting Named Tuples to dicts
function Base.Dict(nt::NamedTuple)
  parsevalue(x::Any) = x
  parsevalue(x::Union{NamedTuple,Dict}) = Dict(x)
  return Dict(k=>parsevalue(v) for (k,v) ∈ zip(keys(nt), values(nt)))
end

#a simple function to get the lead of a field within a group
function simpleleadwithin!(df::DataFrame,
  target::Symbol=error("target is required"),
  group::Symbol=error("group is required");
  Ntarget::Symbol = Symbol(:N, target),
  Ngroup::Symbol = Symbol(:N, group))

  issorted(df, group) || error("df must be sorted by $group, date")
  #shift up target and group
  df[!, Ntarget] = [df[!, target][2:end]; missing]
  df[!, Ngroup] = [df[!, group][2:end]; missing]

  df[df[!, Ngroup] .!== df[!, group] , Ntarget] .= missing
  select!(df, Not([Ngroup]))

  #check type stability
  @assert eltype(df[!, Ntarget]) <: Union{eltype(df[!, target]), Missing}

  #NOTE: can delete the below at some point
  #only for testing purposes
  lagwithin2!(df, [Ntarget], group)
  LNtarget = Symbol(:L, Ntarget)
  @assert all((df[!, target] .=== df[!, LNtarget]) .| (df[!, LNtarget] .=== missing))
  select!(df, Not([LNtarget]))

  return nothing
end

#simple function to add dates and date periods with missing values
incrementdt(d1,d2) = d1 + d2
incrementdt(::Missing, ::Any) = missing
incrementdt(::Any, ::Missing) = missing

#formats a dict for logging purposes
formatdict(d;
  title="",
  header="\nkeys\tvalues\n",
  ) = title * header * join(string.(keys(d)) .* ":\t" .* string.(values(d)) .* "\n")

function StatsBase.partialcor(X::AbstractArray{T,2}, Z::AbstractArray{T,2};
    zincludesintercept = false) where T
  N,K = size(X)
  @assert size(X,1) == size(Z,1)

  local Xe::Matrix
  if zincludesintercept
    Xₑ = X - Z * (cholesky!(Symmetric(Z'*Z))\(Z'*X))
  else
    Z1 = hcat(ones(T,N), Z)
    Xₑ = X - Z1 * (cholesky!(Symmetric(Z1'*Z1))\(Z1'*X))
  end
  return cor(Xₑ)
end

function testpartialcor(;N=252, K=500, R = 4)
  X = rand(N, K)
  Z = rand(N, R)
  #slow, manual version
  function partialcorver(X::AbstractArray{T,2}, Z::AbstractArray{T,2}) where T
    N,K = size(X)
    @assert size(X,1) == size(Z,1)

    ρ = ones(T, K,K)
    for c ∈ 1:K
      for r ∈ 1:(c-1)
        ρ[r,c] = partialcor(X[:,c], X[:,r],Z)
      end
    end

    ρ .= Symmetric(ρ)
    return ρ
  end

  #create an orthogonalized version for testing purposes
  Z1 = hcat(ones(N), Z)
  Xr = X .- Z1*(cholesky!(Z1'*Z1)\(Z1'*X))

  @info "testing partial correlations"
  @assert (partialcor(Xr, Z) .≈ cor(Xr)) |> all
  @assert (partialcor(X,Z) .≈ partialcor(X,Z1,zincludesintercept=true)) |> all
  #@btime partialcor($X, $Z1,zincludesintercept=true)
  @btime partialcor($X, $Z)

  if K ≤ 1000
    @assert (partialcorver(X,Z) .≈ cor(Xr)) |> all
    @assert (partialcor(X,Z) .≈ partialcorver(X,Z)) |> all
  end

end

max_stars_repo_name: clintonTE/CCA

max_issues_repo_name: clintonTE/CCA

max_forks_repo_name: clintonTE/CCA


text:
using ModelingToolkit
using Test

using ModelingToolkit: value, Flow
using SymbolicUtils: FnType

@parameters t
@variables x(t) y(t) # test multi-arg
@variables z(t) # test single-arg

x1 = Num(Sym{FnType{Tuple{Any}, Real}}(:x)(value(t)))
y1 = Num(Sym{FnType{Tuple{Any}, Real}}(:y)(value(t)))
z1 = Num(Sym{FnType{Tuple{Any}, Real}}(:z)(value(t)))

@test isequal(x1, x)
@test isequal(y1, y)
@test isequal(z1, z)

@parameters begin
    t
    s
end
@parameters σ(..)

t1 = Num(Sym{Real}(:t))
s1 = Num(Sym{Real}(:s))
σ1 = Num(Sym{FnType{Tuple, Real}}(:σ))
@test isequal(t1, t)
@test isequal(s1, s)
@test isequal(σ1(t), σ(t))

@test ModelingToolkit.isparameter(t)
@test ModelingToolkit.isparameter(s)
@test ModelingToolkit.isparameter(σ)

@derivatives D'~t
D1 = Differential(t)
@test D1 == D

@test @macroexpand(@parameters x, y, z(t)) == @macroexpand(@parameters x y z(t))
@test @macroexpand(@variables x, y, z(t)) == @macroexpand(@variables x y z(t))

# Test array expressions
@parameters begin
    t[1:2]
    s[1:4,1:2]
end
@parameters σ[1:2](..)

@test all(ModelingToolkit.isparameter, collect(t))
@test all(ModelingToolkit.isparameter, collect(s))
@test all(ModelingToolkit.isparameter, Any[σ[1], σ[2]])

# fntype(n, T) = FnType{NTuple{n, Any}, T}
# t1 = Num[Variable{Real}(:t, 1), Variable{Real}(:t, 2)]
# s1 = Num[Variable{Real}(:s, 1, 1) Variable{Real}(:s, 1, 2);
#         Variable{Real}(:s, 3, 1) Variable{Real}(:s, 3, 2)]
# σ1 = [Num(Variable{fntype(1, Real)}(:σ, 1)), Num(Variable{fntype(1, Real)}(:σ, 2))]
# @test isequal(t1, collect(t))
# @test isequal(s1, collect(s))
# @test isequal(σ1, σ)

#@parameters t
#@variables x[1:2](t)
#x1 = Num[Variable{FnType{Tuple{Any}, Real}}(:x, 1)(t.val),
#      Variable{FnType{Tuple{Any}, Real}}(:x, 2)(t.val)]
#
#@test isequal(x1, x)

@variables a[1:11,1:2]
@variables a()

using Symbolics: value, VariableDefaultValue
using ModelingToolkit: VariableConnectType, VariableUnit, rename
using Unitful

vals = [1,2,3,4]
@variables x=1 xs[1:4]=vals ys[1:5]=1

@test getmetadata(x, VariableDefaultValue) === 1
@test getmetadata.(collect(xs), (VariableDefaultValue,)) == vals
@test getmetadata.(collect(ys), (VariableDefaultValue,)) == ones(Int, 5)

u = u"m^3/s"
@variables begin
    x = [1, 2], [connect=Flow,unit=u]
    y = 2
end

@test getmetadata(x, VariableDefaultValue) == [1, 2]
@test getmetadata(x, VariableConnectType) == Flow
@test getmetadata(x, VariableUnit) == u
@test getmetadata(y, VariableDefaultValue) === 2

@variables begin
    x, [connect=Flow,unit=u]
    y = 2, [connect=Flow]
end

@test !hasmetadata(x, VariableDefaultValue)
@test getmetadata(x, VariableConnectType) == Flow
@test getmetadata(x, VariableUnit) == u
@test getmetadata(y, VariableDefaultValue) === 2
@test getmetadata(y, VariableConnectType) == Flow

a = rename(value(x), :a)
@test !hasmetadata(x, VariableDefaultValue)
@test getmetadata(x, VariableConnectType) == Flow
@test getmetadata(x, VariableUnit) == u

@variables t x(t)=1 [connect=Flow,unit=u]

@test getmetadata(x, VariableDefaultValue) == 1
@test getmetadata(x, VariableConnectType) == Flow
@test getmetadata(x, VariableUnit) == u

a = rename(value(x), :a)
@test getmetadata(a, VariableDefaultValue) == 1
@test getmetadata(a, VariableConnectType) == Flow
@test getmetadata(a, VariableUnit) == u

@parameters p=2 [unit=u"m",]
@test getmetadata(p, VariableDefaultValue) == 2
@test !hasmetadata(p, VariableConnectType)
@test getmetadata(p, VariableUnit) == u"m"
@test ModelingToolkit.isparameter(p)

@test_throws Any (@macroexpand @parameters p=2 [unit=u"m",abc=2])

ext: jl

max_stars_repo_name: paulrschrater/ModelingToolsJulia

max_issues_repo_name: paulrschrater/ModelingToolsJulia

max_forks_repo_name: paulrschrater/ModelingToolsJulia


text:
# Events for timing

export CuEvent, record, synchronize, elapsed

@enum_without_prefix CUevent_flags_enum CU_

"""
    CuEvent()

Create a new CUDA event.
"""
mutable struct CuEvent
    handle::CUevent
    ctx::CuContext

    function CuEvent(flags=EVENT_DEFAULT)
        handle_ref = Ref{CUevent}()
        cuEventCreate(handle_ref, flags)

        ctx = current_context()
        obj = new(handle_ref[], ctx)
        finalizer(unsafe_destroy!, obj)
        return obj
    end
end

function unsafe_destroy!(e::CuEvent)
    @finalize_in_ctx e.ctx cuEventDestroy_v2(e)
end

Base.unsafe_convert(::Type{CUevent}, e::CuEvent) = e.handle

Base.:(==)(a::CuEvent, b::CuEvent) = a.handle == b.handle
Base.hash(e::CuEvent, h::UInt) = hash(e.handle, h)

"""
    record(e::CuEvent, [stream::CuStream])

Record an event on a stream.
"""
record(e::CuEvent, stream::CuStream=stream()) =
    cuEventRecord(e, stream)

"""
    synchronize(e::CuEvent)

Waits for an event to complete.
"""
function synchronize(e::CuEvent)
    # fast path
    isdone(e) && @goto(exit)

    # spin (initially without yielding to minimize latency)
    spins = 0
    while true
        if spins < 32
            ccall(:jl_cpu_pause, Cvoid, ())
            # Temporary solution before we have gc transition support in codegen.
            ccall(:jl_gc_safepoint, Cvoid, ())
        else
            yield()
        end
        isdone(e) && @goto(exit)
        spins += 1
    end

    @label(exit)
    #cuEventSynchronize(e)
end

"""
    isdone(e::CuEvent)

Return `false` if there is outstanding work preceding the most recent
call to `record(e)` and `true` if all captured work has been completed.
"""
function isdone(e::CuEvent)
    res = unsafe_cuEventQuery(e)
    if res == ERROR_NOT_READY
        return false
    elseif res == SUCCESS
        return true
    else
        throw_api_error(res)
    end
end

"""
    wait(e::CuEvent, [stream::CuStream])

Make a stream wait on a event. This only makes the stream wait, and not the host; use
[`synchronize(::CuEvent)`](@ref) for that.
"""
wait(e::CuEvent, stream::CuStream=stream()) =
    cuStreamWaitEvent(stream, e, 0)

"""
    elapsed(start::CuEvent, stop::CuEvent)

Computes the elapsed time between two events (in seconds).
"""
function elapsed(start::CuEvent, stop::CuEvent)
    time_ref = Ref{Cfloat}()
    cuEventElapsedTime(time_ref, start, stop)
    return time_ref[]/1000
end

"""
    @elapsed ex

A macro to evaluate an expression, discarding the resulting value, instead returning the
number of seconds it took to execute on the GPU, as a floating-point number.
"""
macro elapsed(ex)
    quote
        t0, t1 = CuEvent(), CuEvent()
        record(t0)
        $(esc(ex))
        record(t1)
        synchronize(t1)
        elapsed(t0, t1)
    end
end


text:
using Test, LatticeSites, StaticArrays

@testset "site type" begin

    @test up(Bit{Float64}) == Bit(1.0)
    @test down(Bit{Float64}) == Bit(0.0)

    @test up(Spin{Float64}) == Spin(1.0)
    @test down(Spin{Float64}) == Spin(-1.0)

    @test up(Half{Float64}) == Half(0.5)
    @test down(Half{Float64}) == Half(-0.5)

end

@testset "hilbert space" begin
    for (i, each) in enumerate(HilbertSpace{Bit{Float64}}(2, 3))
        @test size(each) == (2, 3)
        @test i-1 == convert(Int, each)
    end
end

@testset "conversion" begin
    @test 1 == convert(Int,  Bit[1,      0])
    @test 1 == convert(Int, Spin[1,     -1])
    @test 1 == convert(Int, Half[0.5, -0.5])
end

@testset "rounding" begin
    @test round(Bit{Float64}, 1.2) == up(Bit{Float64})
    @test round(Bit{Float64}, 0.9) == up(Bit{Float64})
    @test round(Bit{Float64}, 0.1; threshold=0.5) == down(Bit{Float64})
    @test round(Bit{Int}, 2) == up(Bit{Int})
    @test round(Bit{Int}, 0) == down(Bit{Int})
end

@testset "static array" begin
    @test all(ups(SMatrix{2, 2, Bit{Float64}}) .== up(Bit{Float64}))
    @test all(downs(SMatrix{2, 2, Bit{Float64}}) .== down(Bit{Float64}))
end


text:
using WrightOmega
using Test

@testset "WrightOmega.jl" begin
    z_vals = [
        # R1
        4im
        -1 + 3.5im
        1 + 3.5im
        -1 + π
        # R2
        -4im
        -1 - 3.5im
        1 - 3.5im
        -1 - π
        # R3
        -5 + 0im
        -5
        -3 + 2im
        -3 + 0.9999π * im
        -3 + π * im # uses regularization
        -3 - 0.999π * im # uses regularization
        # R4
        0 + 0im
        0
        0.5im
        -1 + 0im
        -1
        1 + im
        1 - im
        1 + π * im
        1 - π * im
        # R5
        -5 + 3im / 2
        -2 + (π + 3 / 4)im
        # R6
        -5 - 3im / 2
        -2 - (π + 3 / 4)im
        # R7
        5 + 0im
        5
        5 + 5im
        ]
    conv = [Float32, identity, big]
    for z in z_vals, T in conv
        zT = T(real(z)) + T(imag(z)) * im
        w = wrightomega(zT)
        @test w + log(w) ≈ zT
    end
    @test wrightomega(NaN) === NaN
    @test wrightomega(NaN + NaN * im) === NaN + NaN * im
end


text:
module Transfer

include("momentum.jl")
include("heat.jl")
include("mass.jl")

# export submodule functions to the current level
using .Momentum
using .Heat
using .Mass

end  # module


text:
## In this notebook, we'll look at least absolute deviation on biometric data

##
using Plots
pyplot()
theme(:dark)
##
# https://vincentarelbundock.github.io/Rdatasets/csv/carData/Davis.csv
using CSV
df = CSV.read(download("https://vincentarelbundock.github.io/Rdatasets/csv/carData/Davis.csv"))
X = Float64.([df[:weight] df[:height]])
# Filter the data
goodpts = X[:,1] .<= 115
Xf = X[goodpts,:]
##
scatter(Xf[:,1],Xf[:,2],label="",xlabel="weight (kg)", ylabel="height (cm)")
##
x = Xf[:,1]
A = [x ones(length(x))]
b = Xf[:,2]
ab_ls = A\b # solve the least squares problem

## Solve the Least Absolute Deviation version
using Convex, SCS
xvar = Variable(2)
problem = minimize(sum(abs(A * xvar - b)))
solve!(problem, SCSSolver(max_iters=20000))
ab_lad = xvar.value
##
using Printf
scatter(Xf[:,1],Xf[:,2],color=2,size=(300,300), label="")
plot!(x, x*ab_ls[1] .+ ab_ls[2], label="",color=5)
plot!(x, x*ab_lad[1] .+ ab_lad[2], label="",color=6)
title!(@sprintf("LS: height ≈ %.2f weight + %.2f\nLAD:  height ≈ %.2f weight + %.2f    ",
ab_ls[1],ab_ls[2],ab_lad[1],ab_lad[2]), titlefontsize=12)
xlabel!("Weight (kg)")
ylabel!("Height (cm)")
savefig("weight-height-fit-lad.pdf")
## Except, we actually filtered the data.
# to remove an outlier
scatter(X[:,1],X[:,2],color=2,size=(300,300), label="",xlabel="weight (kg)", ylabel="height (cm)")
savefig("weight-height-outliers.pdf")
##
x = X[:,1]
A = [x ones(length(x))]
b = X[:,2]
ab_ls = A\b # solve the least squares problem
xvar = Variable(2)
problem = minimize(sum(abs(A * xvar - b)))
solve!(problem, SCSSolver(max_iters=20000))
ab_lad = xvar.value
scatter(X[:,1],X[:,2],color=2,size=(300,300), label="")
plot!(x, x*ab_ls[1] .+ ab_ls[2], label="",color=5)
plot!(x, x*ab_lad[1] .+ ab_lad[2], label="",color=6)
title!(@sprintf("LS: height ≈ %.2f weight + %.2f\nLAD:  height ≈ %.2f weight + %.2f    ",
ab_ls[1],ab_ls[2],ab_lad[1],ab_lad[2]), titlefontsize=12)
xlabel!("Weight (kg)")
ylabel!("Height (cm)")
savefig("weight-height-outliers-fit-lad.pdf")


text:
export MinorBody, pluto, Pluto, pluto_barycenter, PlutoBarycenter

abstract type MinorBody <: CelestialBody end

const MINOR_BODY_NAMES = (
    "Ceres",
    "Pallas",
    "Vesta",
    "Psyche",
    "Lutetia",
    "Ida",
    "Eros",
    "Davida",
    "Gaspra",
    "Steins",
    "Itokawa",
    "Tempel1",
    "Borrelly",
)

for body in MINOR_BODY_NAMES
    str_sym = Symbol(body)
    con_sym = Symbol(lowercase(body))
    @eval begin
        struct $str_sym <: MinorBody end
        const $con_sym = $str_sym()
        parent(::$str_sym) = ssb
        export $str_sym, $con_sym
    end
end

struct PlutoBarycenter <: Barycenter end
const pluto_barycenter = PlutoBarycenter()
Base.show(io::IO, ::PlutoBarycenter) = print(io, "Pluto Barycenter")
parent(::PlutoBarycenter) = ssb
naifid(::PlutoBarycenter) = 9
from_naifid(::Val{9}) = pluto_barycenter
add_edge!(BODIES, 0, 9)

struct Pluto <: MinorBody end
const pluto = Pluto()
parent(::Pluto) = pluto_barycenter
naifid(::Pluto) = 999
from_naifid(::Val{999}) = pluto
add_edge!(BODIES, 9, 999)

naifid(::Ceres) = 2000001
from_naifid(::Val{2000001}) = ceres
add_edge!(BODIES, 0, 2000001)

naifid(::Pallas) = 2000002
from_naifid(::Val{2000002}) = pallas
add_edge!(BODIES, 0, 2000002)

naifid(::Vesta) = 2000004
from_naifid(::Val{2000004}) = vesta
add_edge!(BODIES, 0, 2000004)

naifid(::Psyche) = 2000016
from_naifid(::Val{2000016}) = psyche
add_edge!(BODIES, 0, 2000016)

naifid(::Lutetia) = 2000021
from_naifid(::Val{2000021}) = lutetia
add_edge!(BODIES, 0, 2000021)

naifid(::Ida) = 2431010
from_naifid(::Val{2431010}) = ida
add_edge!(BODIES, 0, 2431010)

naifid(::Eros) = 2000433
from_naifid(::Val{2000433}) = eros
add_edge!(BODIES, 0, 2000433)

naifid(::Davida) = 2000511
from_naifid(::Val{2000511}) = davida
add_edge!(BODIES, 0, 2000511)

naifid(::Gaspra) = 9511010
from_naifid(::Val{9511010}) = gaspra
add_edge!(BODIES, 0, 9511010)

naifid(::Steins) = 2002867
from_naifid(::Val{2002867}) = steins
add_edge!(BODIES, 0, 2002867)

naifid(::Itokawa) = 2025143
from_naifid(::Val{2025143}) = itokawa
add_edge!(BODIES, 0, 2025143)

naifid(::Tempel1) = 1000093
Base.show(io::IO, ::Tempel1) = print(io, "Tempel 1")
from_naifid(::Val{1000093}) = tempel1
add_edge!(BODIES, 0, 1000093)

naifid(::Borrelly) = 1000005
from_naifid(::Val{1000005}) = borrelly
add_edge!(BODIES, 0, 1000005)


text:
###
### push
###
function Base.push!(a::IndicesVector, items...)
    push_index!(a, items...)
    push!(parent(a), items...)
end
function Base.push!(x::IndicesVector, items::Pair...)
    push_index!(x, items...)
    for i in items
        k, v = i
        push!(parent(x), v)
    end
    return x
end

###
### push
###
function StaticRanges.push(x::IndicesVector, items...)
    return rebuild(x, push_index(x, items...), push(parent(x), items...))
end
function StaticRanges.push(x::IndicesVector, items::Pair...)
    p = parent(x)
    for i in items
        k, v = i
        p = push(parent(x), v)
    end
    return rebuild(x, p, push_index(x, items...))
end

###
### pushfirst!
###
function Base.pushfirst!(x::IndicesVector, items...)
    pushfirst_index!(x, items...)
    pushfirst!(parent(x), items...)
end
function Base.pushfirst!(x::IndicesVector, items::Pair...)
    pushfirst_index!(x, items...)
    for i in items
        k, v = i
        pushfirst!(parent(x), v)
    end
    return x
end

###
### pushfirst
###
function StaticRanges.pushfirst(x::IndicesVector, items...)
    return rebuild(x, pushfirst_index(x, items...), pushfirst(parent(x), items...))
end
function StaticRanges.pushfirst(x::IndicesVector, items::Pair...)
    p = parent(x)
    for i in items
        k, v = i
        p = pushfirst(parent(x), v)
    end
    return rebuild(x, p, pushfirst_index(x, items...))
end

###
### pop[!]
###
function Base.pop!(a::IndicesVector)
    pop_index!(axes(a, 1))
    return pop!(parent(a))
end

function StaticRanges.pop(a::IndicesVector)
    return rebuild(a, pop(parent(a)), (pop_index(axes(a, 1)),))
end

###
### popfirst[!]
###
function Base.popfirst!(a::IndicesVector)
    popfirst_index!(axes(a, 1))
    return popfirst!(parent(a))
end

function StaticRanges.popfirst(a::IndicesVector)
    return rebuild(a, popfirst(parent(a)), (popfirst_index(axes(a, 1)),))
end


text:
VERSION >= v"0.4.0-dev+6521" && __precompile__()

include("plain.jl")


text:
import Base: sin, cos, tan, cot, sec, csc, atan

import Base: sinh, cosh, tanh, coth, sech, csch

import Base: abs, exp, log, zero, one

import Base: +, -, *, /, ^

struct quadcomplex
    i1
    i2
end

function mat(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    return [i1 -i2; i2 i1]
end

function mat2quadcomplex(matrix)
    out1, out2 = matrix[1, 1], matrix[2, 1]
    return quadcomplex(out1, out2)
end

## Basic operators: +, -, *, /, ^

+(quad1::quadcomplex, quad2::quadcomplex) = mat2quadcomplex(mat(quad1)+mat(quad2))
+(n, quad::quadcomplex) = mat2quadcomplex(n.+mat(quad))
+(quad::quadcomplex, n) = +(n, quad)

-(quad1::quadcomplex, quad2::quadcomplex) = mat2quadcomplex(mat(quad1)-mat(quad2))
-(n, quad::quadcomplex) = mat2quadcomplex(n.-mat(quad))
-(quad::quadcomplex) = mat2quadcomplex(-mat(quad))

*(quad1::quadcomplex, quad2::quadcomplex) = mat2quadcomplex(mat(quad1)*mat(quad2))
*(n, quad::quadcomplex) = mat2quadcomplex(n*mat(quad))
*(quad::quadcomplex, n) = *(n, quad)

/(quad1::quadcomplex, quad2::quadcomplex) = mat2quadcomplex(mat(quad1)/mat(quad2))
/(n, quad::quadcomplex) = n*inv(quad)

^(quad::quadcomplex, power) = mat2quadcomplex(mat(quad)^power)

function zero(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    return quadcomplex(zero(i1), zero(i2))
end

function one(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    return quadcomplex(one(i1), one(i2))
end

## Basic functions: abs, exp, log

function abs(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    return sqrt(i1^2+i2^2)
end

function exp(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    out1 = exp(i1)*cos(i2)
    out2 = exp(i1)*sin(i2)
    return quadcomplex(out1, out2)
end

## Basic math functions: sin, cos, tan, cot, sec, csc

function sin(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    out1 = cosh(i2)*sin(i1)
    out2 = sinh(i2)*cos(i1)
    return quadcomplex(out1, out2)
end

function cos(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    out1 = cosh(i2)*cos(i1)
    out2 = -sinh(i2)*sin(i1)
    return quadcomplex(out1, out2)
end

tan(quad::quadcomplex) = sin(quad)/cos(quad)
cot(quad::quadcomplex) = cos(quad)/sin(quad)
sec(quad::quadcomplex) = 1/cos(quad)
csc(quad::quadcomplex) = 1/sin(quad)

## Basic hyperbolic functions: sinh, cosh, tanh, coth, sech, csch

function sinh(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    out1 = cosh(i1)*cos(i2)
    out2 = sinh(i1)*sin(i2)
    return quadcomplex(out1, out2)
end

function cosh(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    out1 = sinh(i1)*cos(i2)
    out2 = cosh(i1)*sin(i2)
    return quadcomplex(out1, out2)
end

tanh(quad::quadcomplex) = sinh(quad)/cosh(quad)
coth(quad::quadcomplex) = cosh(quad)/sinh(quad)
sech(quad::quadcomplex) = 1/cosh(quad)
csch(quad::quadcomplex) = 1/sinh(quad)

function image4(quad::quadcomplex)
    i1, i2 = quad.i1, quad.i2
    return image3(i2)
end

function quadderivative(f, point, h)
    result = image4(f(quadcomplex(tricomplex(bicomplex(point+im*h, h), h), h)))/h^4
    return result
end


text:
correct_nchildren(::Leaf) = 0
correct_nchildren(::SingletonVertex) = 1
correct_nchildren(::BinaryVertex) = 2
correct_nchildren(t::Union{VectorVertex, NTVertex}) = length(t.chs)
correct_nchildren(t::Union{Vector, Dict, Tuple}) = length(t)

@testset "nchildren" for T in TEST_TREES
    for n in NodeIterator(T)
        @test nchildren(n) == correct_nchildren(n)
    end
end

@testset "nnodes" for T in TEST_TREES
    for n in NodeIterator(T)
        @test nnodes(n) == NodeIterator(n) |> collect |> length
    end
end

isleaf(::Leaf) = true
isleaf(t::Union{VectorVertex, NTVertex}) = correct_nchildren(t) == 0
isleaf(t::Union{Vector, Dict, Tuple}) = correct_nchildren(t) == 0
isleaf(t) = false

@testset "nleafs" for T in TEST_TREES
    for n in NodeIterator(T)
        @test nleafs(n) == count(isleaf, NodeIterator(n))
    end
end

@testset "treeheight" for T in TEST_TREES
    for n in NodeIterator(T)
        @test treeheight(n) == (isleaf(n) ?  0 : 1 + maximum(treeheight(ch) for ch in _iter(children(n))))
    end
end

@testset "nodes with zero children" begin
    @test nleafs(NTVertex(1, NamedTuple())) == 1
    @test nleafs(BinaryVertex(1,
                              VectorVertex(2, AbstractVertex[]),
                              Leaf(3))
                ) == 2
    @test nleafs(BinaryVertex(1,
                              VectorVertex(2, AbstractVertex[]),
                              NTVertex(3, (; a=Leaf(4))))
                ) == 2
end


text:
using Mux, Base64, DataFrames, Parameters
import Mux.WebSockets

PORT = 2333

function WS_IO(app)
    return x -> ws_io(x, app)
end

@with_kw struct EncodedOutput
    type::String
    content::String
    parameters::Union{Dict{String, String}, Nothing} = nothing
end

function ws_encode(x::String)
    EncodedOutput(
        type = "string",
        content = x
    )
end

# function ws_encode(x::Plot)
#
# end

function ws_encode(x::DataFrame)

end

function ws_encode(x::Number)

end

macro validate_input(conn, condition, error_msg)
    quote
        if $(esc(condition))
            @error $error_msg

            local response = json(
                Dict{String, String}(
                    "command" => "error",
                    "message" => $error_msg
                )
            )

            WebSockets.writeguarded($conn, response)

            continue
        end
    end
end

function ws_io(x, app::MATTApp)
    local connection_hash = uuid4()
    local conn = x[:socket]

    @info "Incomming connection" connection_hash

    while !eof(conn)
        local update_hash = uuid4()
        local data = String(WebSockets.readguarded(conn)[1])
        local parsed_data = try JSON.parse(data) catch e; end

        @info "Received message" update_hash parsed_data

        @validate_input(conn, isnothing(parsed_data), "Failed to parse the request to JSON")
        @validate_input(conn, !(typeof(parsed_data) <: Dict), "The request should be an Object")
        @validate_input(conn, !haskey(parsed_data, "command"), "No command provided")

        @info "Validated the message" update_hash

        if parsed_data["command"] == "update"

            @info "Matched command" update_hash

            """
            Client side should pass an update command in the following format:

            {
              "command": "update",
              "bind_set": "<UUID of bind set>",
              "input": {
                "<UUID of input>": "<value of input>",
                "...": "..."
              }
            }

            Example requirement:

            ```
            {
              "command": "update",
              "bind_set": "4c274ad0-9373-4e08-84b1-9a86f9aba145",
              "input": {
                "bdea432c-e94f-4def-ab43-6587beb93607": true
              }
            }
            ```

            Error messages:
            * **1-02-001**: No bind set provided, provide a UUID of the bind set;
            * **1-02-002**: Invalid bind set hash, will be thrown while faild to parse the bind set hash to UUID;
            * **1-02-003**: Bind set not found, the bind set client side provided is not defined in the MATT app;
            * **1-02-004**: No input provided, will be thrown while no input field found in the request;
            * **1-02-005**: Input should be an object, the input field should be a Javascript Object, but something else provided;
            * **1-02-006**: Mismatch input type, the input parameters provided can't be converted to predefinded type.
            """
            @validate_input(conn, !haskey(parsed_data, "bind_set"), "No bind set provided")
            @validate_input(conn, !haskey(parsed_data, "input"), "No input provided")

            @info "validated the input" update_hash

            local bind_set_hash = try UUID(parsed_data["bind_set"]) catch e; end

            @validate_input(conn, isnothing(bind_set_hash), "Invalid bind set hash, should be an UUID")
            @validate_input(conn, !haskey(app.bind_output, bind_set_hash), "Bind set not found")
            @validate_input(conn, !(typeof(parsed_data["input"]) <: Dict{String, Any}), "Input should be an Object")

            @info "validated bind set" update_hash

            local bind_set = app.bind_sets[bind_set_hash]
            local paras_valid = true

            local output_fn_paras = Vector{Pair{Symbol, Any}}([Pair(:__update_hash, update_hash)])

            for bind in bind_set.binds
                local input_hash = bind.component.hash
                local input_hash_str = string(input_hash)
                if !haskey(parsed_data["input"], input_hash_str)
                    paras_valid = false
                    break
                end

                local input_data = parsed_data["input"][input_hash_str]
                local input_type = typeof(app.input_components[input_hash]).parameters[1]
                local input_var_name = app.binds[bind.hash].variable
                local parsed_input = try input_type(input_data) catch e; end

                if isnothing(parsed_input)
                    paras_valid = false
                    break
                end

                append!(output_fn_paras, [Pair(Symbol(input_var_name), parsed_input)])
            end

            @validate_input(conn, !paras_valid, "Mismatch input type")

            @info "validated input" update_hash

            local output_hashes = app.bind_output[bind_set.hash]

            for output_hash in output_hashes
                local callback = app.output_components[output_hash].callback
                local call_result = callback.fn(;output_fn_paras...)
                local encoded_output = ws_encode(call_result)

                local response = json(
                    Dict(
                        "command" => "update",
                        "output" => output_hashes,
                        "detail" => call_result
                    )
                )

                WebSockets.writeguarded(conn, response)
            end
        else
            @validate_input(conn, true, "Invalid command")
        end
    end
end

function run_app(x::StaticComponent; port::Int64 = 2333)
    run_app(setup_app(x), port = port)
end

function run_app(x::MATTApp; port::Int64 = 2333)
    @app h = (
        Mux.defaults,
        page("/", respond("
Hello World!
")),
        page("/ui", respond(x.serialized_app)),
        Mux.notfound());

    @app w = (
        Mux.wdefaults,
        route("/MATT-io", WS_IO(x)),
        Mux.wclose,
        Mux.notfound());

    local app_hash = x.hash

    @info "MATT initialized" app_hash

    WebSockets.serve(
        WebSockets.ServerWS(
            Mux.http_handler(h),
            Mux.ws_handler(w),
        ), port);
end


text:
module problem106

description = """
Special subset sums: meta-testing
Problem 106

Let S(A) represent the sum of elements in set A of size n. We shall call it a special sum set if for any two non-empty disjoint subsets, B and C, the following properties are true:

    S(B) ≠ S(C); that is, sums of subsets cannot be equal.
    If B contains more elements than C then S(B) > S(C).

For this problem we shall assume that a given set contains n strictly increasing elements and it already satisfies the second rule.

Surprisingly, out of the 25 possible subset pairs that can be obtained from a set for which n = 4, only 1 of these pairs need to be tested for equality (first rule). Similarly, when n = 7, only 70 out of the 966 subset pairs need to be tested.

For n = 12, how many of the 261625 subset pairs that can be obtained need to be tested for equality?

NOTE: This problem is related to problems 103 and 105.
"""

# I have not put any thought into how the solution here can be used to optimize problems 103 and 105
# as the solutions I have to those problems are already pretty fast.

# tests if a sum check would be required, given the indexes into the sorted list of items making two subsets A and B
function checking_required(a :: Vector{Int}, b :: Vector{Int})

  # by the second property of special sets, non-equal subset sizes have different sums
  if length(a) != length(b)
    return false
  end

  # must be disjoint
  if length(intersect(a, b)) > 0
    return false
  end

  # checking is not required if for each item in A, there is a corresponding item in B with a higher index (or vice versa)
  largerA, largerB = 0,0
  sort!(a)
  sort!(b)
  for n = length(a):-1:1
    if a[n] > b[n]
      largerA += 1
    else
      largerB += 1
    end
  end
  return (largerA > 0) && (largerB > 0)
end

# total number of checks required for sets of size N
# is number of checks required for each pair of subsets sized from 2 to N/2
function count_checking_required(n)
  total = 0
  for m = 2:floor(n/2)
    cs = collect(combinations([1:n], m))
    for i = 1:length(cs)-1
      for j = i+1:length(cs)
        if checking_required(cs[i], cs[j])
          total += 1
        end
      end
    end
  end
  return total
end

using Base.Test

@test count_checking_required(4) == 1
@test count_checking_required(7) == 70

#println(count_checking_required(12))

end

max_stars_repo_name: mbuhot/mbuhot-euler-solutions

max_issues_repo_name: mbuhot/mbuhot-euler-solutions

max_forks_repo_name: mbuhot/mbuhot-euler-solutions


text:
struct Measurement
    mean
    error

    variance
    tau
    R
end

value(x::Measurement)       = x.mean
Statistics.mean(x::Measurement) = x.mean
uncertainty(x::Measurement) = x.error
Base.real(x::Measurement) = Measurement(real(x.mean), x.error, x.variance, x.tau, x.R)
Base.imag(x::Measurement) = Measurement(imag(x.mean), x.error, x.variance, x.tau, x.R)

Measurement(x::Measurement) = copy(x)

Base.copy(x::Measurement) =
    Measurement(x.mean, x.error, x.variance, x.tau, x.R)

stat_analysis(vals::AbstractMatrix, par_data::NotParallel) =
    _single_stat_analysis(vals)

function _single_stat_analysis(vals::AbstractMatrix)
    tmp = similar(vals, size(vals, 1))
    n    = size(vals, 1)
    L    = size(vals, 2)

    tmp = similar(vals, size(vals, 1))

    μ_chains = mean!(tmp, vals)
    μ        = mean(μ_chains)

    var_chains = var(vals, dims=2, mean=μ_chains)
    var_μ_ch   = var(μ_chains)
    var_μ      = var(vals, mean=μ)

    μ_err = sqrt(var_μ_ch/n)
    μ_var = mean(var_chains)

    t = var_μ_ch/var_μ
    corr = max(0.0, 0.5 * ( t * L - 1))
    R = sqrt((L-1)/L + t)

    return Measurement(μ,
            μ_err, μ_var, corr, R)
end

function stat_analysis(vals::AbstractMatrix, par_data)
    tmp = similar(vals, size(vals, 1))
    n    = size(vals, 1)
    L    = size(vals, 2)

    tmp = similar(vals, size(vals, 1))
    #println("Stat $(Threads.threadid())")

    μ_chains = mean!(tmp, vals)
    μ        = workers_mean(μ_chains, par_data)

    var_chains = var(vals, dims=2, mean=μ_chains)
    var_μ_ch   = var(μ_chains)
    var_μ      = var(vals, mean=μ)

    μ_err = sqrt(var_μ_ch/n)
    μ_var = mean(var_chains)

    t = var_μ_ch/var_μ
    corr = max(0.0, 0.5 * ( t * L - 1))
    R = sqrt((L-1)/L + t)

    return Measurement(μ,
            μ_err, μ_var, corr, R)
end

Base.show(io::IO, ::MIME"text/plain", v::Measurement) =
    print(io, _meas_to_str(v))

Base.show(io::IO, v::Measurement) =
    print(io, _meas_to_str(v))

function _meas_to_str(v)
    μ = v.mean
    if μ isa Complex
        sgn = sign(imag(μ)) == 1 ? "+" : "-"
        μs = @sprintf "%6.4f %s %6.4f im" real(μ) sgn abs(imag(μ))
    else
        μs = @sprintf "%6.4f" real(μ)
    end

    @sprintf "(%s) ± %6.4f [var=%6.4f, tau=%6.4f, R=%6.4f]" μs v.error v.variance v.tau v.R
end


text:
function tuple_stencil(d::Int64)
    l = []
    for j = 1:d
        push!(l, CartesianIndex(tuple([i == j ? 1 : 0 for i = 1:d]...)))
        push!(l, CartesianIndex(tuple([i == j ? -1 : 0 for i = 1:d]...)))
    end
    return l
end

#assumes squre lattice
#non-periodic boundary
function laplacian(A::AbstractArray, d::Int64, stencil)
    out = zero(A)
    l = size(a)[1]
    @inbounds for I in R
        out[I] = (
            sum(all(x -> x > 0 && x < l, Tuple(I + s)) ? A[I+s] : 0 for s in stencil) -
            4 * A[I]
        )
    end
    return out
end

#square lattice
#PBC
function tuple_stencil_bc(A::AbstractArray)
    d = length(size(A))
    R = CartesianIndices(A)
    N = size(A)[1]
    stencil = []
    midpoint = []
    for I in R
        neighbours = []
        for j = 1:d
            push!(
                neighbours,
                CartesianIndex(tuple([
                    i == j ? (I[i] + 1 <= N ? I[i] + 1 : 1) : I[i] for i = 1:d
                ]...)),
            )
            push!(
                neighbours,
                CartesianIndex(tuple([
                    i == j ? (I[i] - 1 >= 1 ? I[i] - 1 : N) : I[i] for i = 1:d
                ]...)),
            )
        end
        push!(stencil, [n for n in neighbours]) #ugly list comprahension fixes type instability (fix this to be better code)
        push!(midpoint, I)
    end
    return zip([i for i in midpoint], [i for i in stencil])
    # fixes the type instability
    # rewrite this function
end

function sampler_complex(shape::Tuple)
    1 / sqrt(2.0) * (randn(shape) + 1im * randn(shape))
end

function sampler(shape::Tuple)
    randn(shape)
end

function V_gaussian(V::Array{<:Array{Float64}}, x::Array, t::Float64, xarray::Array{Float64,1},
                    re::Float64, L::Float64)
    R = CartesianIndices(V[1])
    d = length(size(V[1]))
    m = 0.5*L
    for I in R
        temp = exp(-sum(((x[i] - xarray[I[i]] +m )%(2.0*m) -m )^2 for i = 1:d) / (2*re))
        V[1][I] = temp
        for j = 2:length(V)
            V[j][I] =  (((xarray[I[j-1]] - x[j-1]+m )%(2.0*m) -m) / (re) ) * temp
        end
    end
    return (1 / sqrt(2.0*pi*re)^d) * V
end

function V_fct_pinned(V, x, t, xarray, re)
    R = CartesianIndices(V[1])
    d = length(size(V[1]))

    for I in R
        V[1][I] = (
            exp(-sum(((x[i] - xarray[I[i]] ))^2 / (2*re^2) for i = 1:d)) / re +
            exp(-sum((-x[i] - xarray[I[i]])^2 / (2*re^2) for i = 1:d)) / re
        )
        for j = 2:length(V)
            V[j][I] = 0
        end
    end
    return 1 / sqrt(pi) * V
end

function observables(phi, x, xdot, t)
    []
end

max_stars_repo_name: phyjonas/ColloidFluctuatingField


text:
using Pkg

pkg"activate ."
Pkg.add.(["ArgParse", "Documenter", "PrettyTables"])

max_stars_repo_name: LuRenJiasWorld/Git-Work-Tracker

max_issues_repo_name: LuRenJiasWorld/Git-Work-Tracker

max_forks_repo_name: LuRenJiasWorld/Git-Work-Tracker


text:
module _Finance

using Brainstorm._Finance
using Base.Test

include("daycount.jl")
include("cashflow.jl")

function test_all()
    println("")
    test_daycount_all()
    test_cashflow_all()
end

end


text:
# Choose model and dimension of x array and y array
model_type, kx, ky, ky_nn = "Plasticity", 1, 2, 2
#model_type, kx, ky, ky_nn  = "PlasticityLawBased", 1, 1, 1

include("CommonFuncs.jl")
# m set of data, each has n time steps(including initial points)
m, n = 4, 201

xs_set, ys_set = generate_data(model_type, m, n)
sess = Session()
Random.seed!(2333)
loss = compute_point2point_loss(xs_set, ys_set, nn)
init(sess)
BFGS!(sess, loss)

# point2point test
ys_pred_set = point2point_test(xs_set, ys_set, sess)

colors = ["blue", "green" , "red", "cyan", "magenta", "yellow", "black"]
close("all")
for i = 1:m
    plot(xs_set[i], ys_set[i][:,1], color=colors[i])
    plot(xs_set[i], ys_pred_set[i][:,1], color=colors[i], ".-")
end
savefig("P2P_Train_P2P_Test_NN$(nn_type)_Prob$(model_type)_ky_nn$(ky_nn).png")

# sequence test
ys_pred_set = sequence_test(xs_set, sess)

colors = ["blue", "green" , "red", "cyan", "magenta", "yellow", "black"]
close("all")
for i = 1:m
    plot(xs_set[i], ys_set[i][:,1], color=colors[i])
    plot(xs_set[i], ys_pred_set[i][:,1], color=colors[i], ".-")
end
savefig("P2P_Train_S_Test_NN$(nn_type)_Prob$(model_type)_ky_nn$(ky_nn).png")


text:
# MovingAverageFunction.jl - Tipo para computar medias móviles de medidas de inflación

"""
    InflationMovingAverage{F <: InflationFunction} <: InflationFunction
Función de inflación que computa el promedio móvil de `k` períodos de la
trayectoria interanual de la medida de inflación `inflfn` almacenada.

## Ejemplo

Para computar la media móvil de 6 meses de la variación interanual del IPC:
```julia-repl
julia> inflfn = InflationMovingAverage(InflationTotalCPI(), 6)
(::InflationMovingAverage{InflationTotalCPI}) (generic function with 5 methods)
```
"""
struct InflationMovingAverage{F <: InflationFunction} <: InflationFunction
    inflfn::F
    periods::Int
end

# 2. Extender el método de nombre
measure_name(mafn::InflationMovingAverage) = "Promedios Móvil de $(mafn.periods) períodos de " * measure_name(mafn.inflfn)

# Método que opera sobre CountryStructure: computa la trayectoria de inflación
# con la función inflfn y luego computa el promedio móvil de k períodos
function (mafn::InflationMovingAverage)(cs::CountryStructure)

    # Cómputo usual de inflación
    tray_infl = mafn.inflfn(cs)

    # Algoritmo de promedio móvil
    k = mafn.periods
    k == 1 && return tray_infl

    # Computar el promedio móvil (in-place)
    ma_tray_infl = moving_average(tray_infl, k)

    # Devolver la trayectoria de inflación
    ma_tray_infl
end

# Actualmente, se define el resumen intermensual por el obtenido con la función
# de inflación interna
# function (mafn::InflationMovingAverage)(base::VarCPIBase)
#     # Obtener resumen intermensual y aplicarle media móvil
#     vm = mafn.inflfn(base)
#     moving_average!(vm, mafn.periods)
#     vm
# end

# Función para computar el promedio móvil de la serie `v` con `k` períodos. Esta
# función modifica los elementos de `v` con el promedio móvil.
function moving_average(v, k)
    ma = similar(v)
    ma[1] = v[1]
    for j = 2:k-1
        ma[j] = mean(@view v[1:j])
    end
    for t = k:length(v)
        ma[t] = mean(@view v[t-k+1:t])
    end

    ma
end


text:
"""
````
function simplexgrid(Generator;
                     points=Array{Cdouble,2}(undef,0,0),
                     bfaces=Array{Cint,2}(undef,0,0),
                     bfaceregions=Array{Cint,1}(undef,0),
                     regionpoints=Array{Cdouble,2}(undef,0,0),
                     regionnumbers=Array{Cint,1}(undef,0),
                     regionvolumes=Array{Cdouble,1}(undef,0);
                     kwargs...
                  )
````
Create Grid from a number of input arrays.
The 2D input arrays are transposed if necessary and converted to
the proper data types for Triangulate or TetGen

This conversion is not performed if the data types are those
indicated in the defaults and the leading dimension of 2D arrays
corresponds to the space dimension.

See [`default_options`](@ref) for available `kwargs`.

"""
function ExtendableGrids.simplexgrid(Generator::Module;
                                     points=Array{Cdouble,2}(undef,0,0),
                                     bfaces=Array{Cint,2}(undef,0,0),
                                     bfaceregions=Array{Cint,1}(undef,0),
                                     regionpoints=Array{Cdouble,2}(undef,0,0),
                                     regionnumbers=Array{Cint,1}(undef,0),
                                     regionvolumes=Array{Cdouble,1}(undef,0),
                                     kwargs...
                                     )
    if size(points,1)==2
        tio=triangulateio(Generator,points=points,
                          bfaces=bfaces,
                          bfaceregions=bfaceregions,
                          regionpoints=regionpoints,
                          regionnumbers=regionnumbers,
                          regionvolumes=regionvolumes)
        ExtendableGrids.simplexgrid(TriangulateType,Generator,tio; kwargs...)
    else
        tio=tetgenio(Generator,
                     points=points,
                     bfaces=bfaces,
                     bfaceregions=bfaceregions,
                     regionpoints=regionpoints,
                     regionnumbers=regionnumbers,
                     regionvolumes=regionvolumes)
        ExtendableGrids.simplexgrid(TetGenType,Generator,tio; kwargs...)
    end

end


text:
@warn "Running the generic build script for unrecognized architectures. If you would like contribute to improving performance on your CPU architecture, please see https://github.com/chriselrod/VectorizationBase.jl/issues/9."

cpu_info_string = """
const REGISTER_SIZE = 16
const REGISTER_COUNT = 16
const FP256 = true
const CACHELINE_SIZE = 64
const CACHE_SIZE = $((1<<15,1<<20,0))
const NUM_CORES = $(Sys.CPU_THREADS)
const FMA3 = false
const AVX2 = false
const AVX512F = false
const AVX512ER = false
const AVX512PF = false
const AVX512VL = false
const AVX512BW = false
const AVX512DQ = false
const AVX512CD = false
const SIMD_NATIVE_INTEGERS = true

"""


text:
# Rational polynomial interpolation

"""
Linear Rational LeastSquares

The following curvit is done:

`y = p(x) / q(x)`

where `p(x)` and `q(x)` are polynomials.

The linear case is solved by doing a least square fit on

`y*q(x) = p(x)`

where the zero order term o `q(x)` is assumed to be 1.
"""
function linear_rational_fit(x::AbstractVector{T}, y::AbstractVector{T}, p, q) where T<:Number
    n = size(x,1)
    A = zeros(T, n, q+p+1)
    for i = 1:n
        A[i,1] = one(T)
        for k = 1:p
            A[i,k+1] = x[i]^k
        end
        for k = 1:q
            A[i, p+1+k] = -y[i] * x[i]^k
        end
    end

    A \ y
#    coefs[1:p+1], [1.0; coefs[p+2:end]]

end

"""
# Type defining a rational polynomial

A rational polynomial is the ratio of two polynomials
and it is often useful in approximating functions.
"""
struct RationalPoly{T<:Number} <: LeastSquares
    num::Poly{T}
    den::Poly{T}
end
RationalPoly(a::AbstractVector{T}, b::AbstractVector{T}) where {T<:Number} = RationalPoly(Poly(a), Poly(b))
RationalPoly(p::Integer, q::Integer, ::Type{T}=Float64) where {T<:Number} = RationalPoly{T}(Poly(zeros(T,p+1)), Poly(zeros(T,q+1)))
RationalPoly(coefs::AbstractVector{T}, p, q) where {T<:Number} = RationalPoly(coefs[1:p+1],[1.0; coefs[p+2:end]])

"Evaluate a rational polynomial"
ratval(r::RationalPoly{T}, x) where {T<:Number} = polyval(r.num, x) ./ polyval(r.den, x)

"`call` overload for calling directly `ratval`"
(r::RationalPoly)(x) = ratval(r, x)

"Auxiliary function used in nonlinear least squares"
function make_rat_fun(p, q)
    r = RationalPoly(p, q, Float64)

    function(x, a)
        for i=0:p
            r.num[i] = a[i+1]
        end
        r.den[0] = 1
        for i = 1:q
            r.den[i] = a[p+1+i]
        end
        polyval(r.num, x[1]) / polyval(r.den, x[1]) - x[2]
    end

end

"""
# Carry out a nonlinear least squares of rational polynomials

Find the polynomial coefficients that best approximate
the points given by `x` and `y`.
"""
function rational_fit(x, y, p, q, eps=1e-8, maxiter=200)

    coefs0  = linear_rational_fit(x, y, p, q)

    fun = make_rat_fun(p, q)

    coefs, converged, niter = nonlinear_fit(hcat(x, y), fun, coefs0, eps, maxiter)

    coefs

end

function curve_fit(::Type{RationalPoly}, x, y, p, q, eps=1e-8, maxiter=200)
    RationalPoly(rational_fit(x, y, p, q, eps, maxiter), p, q)
end


text:
using GeometryTypes: Point, Vec
using GeometryTypes: HyperSphere, HyperRectangle, HyperCube
using ConvexBodyProximityQueries: support

@testset "support functions" begin
    @testset "array of vertices" begin
        vertices = SMatrix{2, 3}([3.0 5.0 7.0; 13.0 15.0 11.0])
        dir = SVector{2}([1.0, 2.0])
        @test all(support(vertices, dir) .≈ [5.0, 15.0])
        dir = SVector{2}([-1.0, 2.0])
        @test all(support(vertices, dir) .≈ [5.0, 15.0])
        dir = SVector{2}([-1.0, -2.0])
        @test all(support(vertices, dir) .≈ [3.0, 13.0])
        dir = SVector{2}([1.0, -2.0])
        @test all(support(vertices, dir) .≈ [7.0, 11.0])

        vertices = SMatrix{3, 4}([3.0 5.0 7.0 5.0; 13.0 15.0 11.0 13.0; 1.0 2.0 3.0 4.0])
        dir = SVector{3}([1.0, 1.0, 2.0])
        @test all(support(vertices, dir) .≈ [5.0, 13.0, 4.0])
        dir = SVector{3}([1.0, 1.0, -2.0])
        @test all(support(vertices, dir) .≈ [5.0, 15.0, 2.0])
        dir = SVector{3}([1.0, -1.0, -2.0])
        @test all(support(vertices, dir) .≈ [7.0, 11.0, 3.0])
        dir = SVector{3}([-1.0, -1.0, -2.0])
        @test all(support(vertices, dir) .≈ [3.0, 13.0, 1.0])
    end # array of vertices
end # support functions


text:
# AUTO GENERATED FILE - DO NOT EDIT

export ''_gridlayout

"""
    ''_gridlayout(;kwargs...)
    ''_gridlayout(children::Any;kwargs...)
    ''_gridlayout(children_maker::Function;kwargs...)

A GridLayout component.
GridLayout is a component for building
dashboards with draggable and resizable items.
It takes a list of children and display them in
div elements that can be moved around the page.
The initial size of each element can either be
defined with the layout argument or by wrapping
each element with the DashboardItem component.
By default, GridLayout will saved the
position of the elements on client side, when
moved on the page. But you can also save it
on server side by defining a callback with :
`Input("<my-id>", "layout")`.
Keyword arguments:
- `children` (Array of a list of or a singular dash component, string or numbers | a list of or a singular dash component, string or number; optional): Children is a list of the elements to drag and resize on the dashboard.
It can be a list of dash Components and/or DashboardItem.
- `id` (String; optional): (string) The ID used to identify this component in Dash callbacks.
The id is also used to automatically save the layout on client side.
- `layout` (Array of Dicts; optional): Layout is a list of dictionnary with the format:
{x: number, y: number, w: number, h: number}
The index into the layout must match the id used on each item component with DashboardItem.
If you choose to use custom keys, you can specify that key in the layout
array objects like so:
{i: string, x: number, y: number, w: number, h: number}
The ID used to identify this component in Dash callbacks.
The id is also used to automatically save the layout on client side.
- `save` (Bool; optional): (bool) If False, then the layout is not saved in the browser.
Default value is True.
- `clearSavedLayout` (Bool; optional): (bool) If set to true, then the layout saved in the client browser
will be cleared on page load.
- `ncols` (Real; optional): (number) the default number of columns by item.
Default value is 6.
- `nrows` (Real; optional): (number) the default number of row by item.
Default value is 8.
- `width` (Real; optional): (number) width (in px).
Default value is 1200.
- `gridCols` (Real; optional): (number) number of columns in the grid layout.
Default value is 12.
- `height` (Real; optional): (number) height of a row (in px).
Default value is 30.
- `className` (String; optional): (string) class passed to the react-grid-layout component
- `style` (Dict; optional): (dict) css style passed to the react-grid-layout component
- `autoSize` (Bool; optional)
- `draggableCancel` (String; optional)
- `draggableHandle` (String; optional)
- `verticalCompact` (Bool; optional)
- `compactType` (a value equal to: 'vertical', 'horizontal'; optional)
- `margin` (Array of Reals; optional)
- `containerPadding` (Array of Reals; optional)
- `isDraggable` (Bool; optional)
- `isResizable` (Bool; optional)
- `isBounded` (Bool; optional)
- `useCSSTransforms` (Bool; optional)
- `transformScale` (Real; optional)
- `preventCollision` (Bool; optional)
- `isDroppable` (Bool; optional)
- `resizeHandles` (Array of a value equal to: 's', 'w', 'e', 'n', 'sw', 'nw', 'se', 'ne's; optional)
"""
function ''_gridlayout(; kwargs...)
        available_props = Symbol[:children, :id, :layout, :save, :clearSavedLayout, :ncols, :nrows, :width, :gridCols, :height, :className, :style, :autoSize, :draggableCancel, :draggableHandle, :verticalCompact, :compactType, :margin, :containerPadding, :isDraggable, :isResizable, :isBounded, :useCSSTransforms, :transformScale, :preventCollision, :isDroppable, :resizeHandles]
        wild_props = Symbol[]
        return Component("''_gridlayout", "GridLayout", "dash_draggable", available_props, wild_props; kwargs...)
end

''_gridlayout(children::Any; kwargs...) = ''_gridlayout(;kwargs..., children = children)
''_gridlayout(children_maker::Function; kwargs...) = ''_gridlayout(children_maker(); kwargs...)

max_stars_repo_name: tcgvn/dash-draggable

max_issues_repo_name: tcgvn/dash-draggable

max_forks_repo_name: tcgvn/dash-draggable


text:
#!/bin/bash
#=
exec julia --color=yes --startup-file=no "${BASH_SOURCE[0]}" "$@"
=#

# ./autogen.jl [--patch=false] [StructName...]

const patch = "--patch=false" ∈ ARGS ? (popfirst!(ARGS); false) : true

const outstructs = [
    "User", "CalendarLink", "Term", "CourseProgress", "Course", "Group", "LockInfo",
    "File", "Folder", "TurnitinSettings", "ExternalToolTagAttributes", "DiscussionTopic",
    "Assignment", "Submission", "GradingRules", "AssignmentGroup", "AssignmentOverride",
    "Section", "Account", "Tab",
]

import JSON, OrderedCollections
# git = mktempdir()
git = "/tmp/jl_NR65ip"
commit = "c72bf19e9dba9948ed6bc745f9335510fc51633c"
# run(Cmd(`git clone https://github.com/instructure/canvas-lms.git .`; dir=git))
run(pipeline(Cmd(`git checkout $(commit)`; dir=git), stdout=devnull))

model_regex = r"#\s*@model\s*(\w+)\n(#     {.*?\n#     })"s

function jsontype(v)
    if haskey(v, "type")
        t = v["type"]
        if t == "string"
            return "String"
        elseif t == "integer"
            return "Int"
        elseif t == "number"
            return "Float64"
        elseif t == "datetime"
            return "TimeZones.ZonedDateTime"
        elseif t == "boolean"
            return "Bool"
        elseif t == "array"
            return "Vector"
        elseif t == "object"
            return "Dict"
        else
            @show v["description"]
            error("unknown object type: $t")
        end
    elseif haskey(v, "\$ref")
        return v["\$ref"]
    else
        error("unknown object")
    end
end

all_structs = OrderedCollections.OrderedDict{String,Any}()
for (root, dirs, files) in walkdir(joinpath(git, "app", "controllers"))
    for f in files
        file = joinpath(root, f)
        endswith(f, ".rb") || continue
        occursin("/lti/", file) && continue
        @debug "Parsing file..." file
        content = read(joinpath(root, f), String)
        for m in eachmatch(model_regex, content)
            # Name of the object
            struct_name = String(m.captures[1])
            @debug "Parsing object '$(struct_name)'..."
            # Strip initial #'s
            json_io = IOBuffer()
            for line in eachline(IOBuffer(m.captures[2]))
                println(json_io, chop(line; head=1, tail=0))
            end
            json = JSON.parse(seekstart(json_io); dicttype=OrderedCollections.OrderedDict)
            if json["id"] != struct_name
                @warn "Object id mismatch, skipping" json["id"] struct_name f
                continue
            end
            if haskey(all_structs, struct_name)
                @debug "duplicate struct definition: $(struct_name)" file
                delete!(all_structs, struct_name)
            else
                push!(all_structs, struct_name => json)
            end
        end
    end
end

function print_json(io_out, json; patch)
    io = IOBuffer()
    println(io, "# ", json["id"])
    println(io, "struct ", json["id"], " <: CanvasObject")
    for (k, v) in json["properties"]
        field_name = replace(k, "-"=>"_") # some names have "-" in them
        field_type = jsontype(v)
        if (desc = get(v, "description", nothing); desc !== nothing)
            iob = IOBuffer()
            b = 0
            for d in split(desc)
                if b == 0
                    print(iob, "\"\"\"")
                    b += 3
                elseif b > 70
                    print(iob, "\n")
                    b = 0
                else
                    print(iob, " "); b += 1
                end
                print(iob, d); b += length(d)
            end
            print(iob, "\"\"\"")
            for line in eachline(seekstart(iob))
                print(io, "    ", line, "\n")
            end
        end
        println(io, "    ", field_name, "::Union{", field_type, ",Nothing}")
    end
    println(io, "end")
    if length(json["properties"]) == 1
        # need to print disambiguation constructor for structs with just one field
        println(io, "# Disambiguating constructor needed for single field structs")
        println(io, json["id"], "(data::AbstractDict) = Internals.json2canvas(", json["id"], ", data)")
    end
    println(io)
    # Apply patches
    patchfile = joinpath(@__DIR__, "patches", "$(json["id"]).patch")
    if patch && isfile(patchfile)
        dir = mktempdir(; cleanup=false)
        #=mktempdir() do dir;=# cd(dir) do
            # Copy the patch
            cp(patchfile, basename(patchfile))
            # Write out the source
            source = "$(json["id"]).jl"
            open(source, "w") do io_patch
                write(io_patch, seekstart(io))
            end
            # Apply the patch
            run(pipeline(`patch`, stdin=patchfile, stdout=devnull))
            # Read back in
            write(truncate(io, 0), read(source))
        end #end
    end
    write(io_out, seekstart(io))
    return nothing
end

if isempty(ARGS)
    print(stdout, """
        # This file is automatically generated from the Canvas LMS source
        # code (https://github.com/instructure/canvas-lms) using the
        # bin/autogen.jl script and should not be directly modified.

        """)
end

for struct_name in (isempty(ARGS) ? outstructs : ARGS)
    if !haskey(all_structs, struct_name)
        @warn "Struct with name '$(struct_name)' missing from parsed structs"
        continue
    end
    json = all_structs[struct_name]
    print_json(stdout, json; patch=patch)
end


text:
using DataFrames
using CSV
using FileIO
using Statistics

include("experiments/experimentalutils.jl")

resultsFolder = mainfolder * "experiments/twostage_vae_scoretest/"
files = readdir(resultsFolder)

results = []
for f in files
    if isfile(resultsFolder * f) && occursin(".csv", f)
        push!(results, CSV.read(resultsFolder * f))
    end
end
results = vcat(results...)

using Plots
using StatsPlots
plotlyjs()

# p1 = plot()
# for (i, n) in enumerate(names(results)[7:13])
#     scatter!(p1, ones(4) .* i, results[n], ylim = (0,1), label = String(n))
# end

# p2 = plot()
# for i in 1:4
#     scatter!(p2, 1:7, [results[i, c] for c in 7:13], ylim = (0,1))
# end

# for n in names(results)[7:end]
#     @df results boxplot(:dataset, n, size = [700, 700])
# end
pp = []
for n in names(results)[8:14]
    i = 1
    p = plot(title = String(n))
    for d in unique(results[:dataset])
        data = vec(results[results[:dataset] .== d, n])
        scatter!(p, ones(size(data)) .* i, data, ylim = (0,1), label = d)
        # scatter!(p, ones(size(data)) .* i, data, zcolor = vec(results[results[:dataset] .== d, 14]), ylim = (0,1), label = d)
        i += 1
    end
    push!(pp, p)
end
push!(pp, plot())
plot(pp..., layout = (2,4), size = (1200, 700))

aucs = names(results)[8:14]
# fit = names(results)[15:20]
fit = names(results)[[15, 16, 19, 20]]

pp = []
for (i, f) in enumerate(fit)
    for (j, a) in enumerate(aucs)
        p = plot()
        for d in unique(results[:dataset])
            p = scatter!(results[results[:dataset] .== d, a], results[results[:dataset] .== d, f])
        end
        if j == 1
            ylabel!(p, String(f))
        end
        if i == length(fit)
            xlabel!(p, String(a))
        end
        push!(pp, p)
    end
end
plot(pp..., layout = (length(fit), length(aucs)), size = (1400, 800), legend = nothing)

ps = plot()
for d in unique(results[:dataset])
    scatter3d!(ps, results[results[:dataset] .== d, :rec_err_test], results[results[:dataset] .== d, :u_test_dst], results[results[:dataset] .== d, :auc_pxv_pz_jacobian_dec])
end
xlabel!(ps, "rec_err_test")
ylabel!(ps, "u_test_dst")
plot(ps, title = "auc_pxv_pz_jacobian_dec")

ps = plot()
d = "blood-transfusion"
res = results[results[:dataset] .== d, :]
for i in unique(results[:i])
    scatter3d!(ps, res[res[:i] .== i, :rec_err_test], res[res[:i] .== i, :u_test_dst], res[res[:i] .== i, :auc_pxv_pz_jacobian_dec])
end
xlabel!(ps, "rec_err_test")
ylabel!(ps, "u_test_dst")
plot(ps, title = "auc_pxv_pz_jacobian_dec")

gdfs = [by(results, [:dataset, :i], df -> DataFrame([[maximum(df[n])]],[n])) for n in names(results)[8:14]]
all = reduce((a...) -> join(a..., on = [:dataset, :i]), gdfs)

pp = []
for n in names(all)[3:9]
    i = 1
    p = plot(title = String(n))
    for d in unique(all[:dataset])
        data = vec(all[all[:dataset] .== d, n])
        scatter!(p, ones(size(data)) .* i, data, ylim = (0,1), label = d)
        # scatter!(p, ones(size(data)) .* i, data, zcolor = vec(all[all[:dataset] .== d, 14]), ylim = (0,1), label = d)
        i += 1
    end
    push!(pp, p)
end
push!(pp, plot())
plot(pp..., layout = (2,4), size = (1200, 700))

# aggres = []
# for d in unique(results[:dataset])
#     ddf = results[results[:dataset] .== d, :]
#     mean_auc_pxv = mean(ddf[:auc_pxv])
#     mean_auc_pz = mean(ddf[:auc_pz])
#     push!(aggres, DataFrame(dataset = d, auc_pxv = mean_auc_pxv, auc_pz = mean_auc_pz))
# end
# aggres = vcat(aggres...)


text:
################################################################################
#
#          EllCrv/FieldsRings.jl : Fields of definition for Elliptic Curves,
#           Field Extensions --> Number Fields
#           Local Rings --> Function Fields
#
################################################################################

################################################################################
#
#  Submodules
#
################################################################################

include("..src/EllCrv/EllCrv.jl")

################################################################################
#
#  Exports
#
################################################################################

export ExtField, NumField, Loc, LocElem, FuncField

################################################################################
#
#  Abstract Types/Structs
#
################################################################################

abstract type AbstractField{T} <: AbstractAlgebra.Field end
mutable struct ExtField{T} <: AbstractField{T}
    degree::Int
    base_field::AbstractAlgebra.Field
end

mutable struct NumField{T} <: AbstractAlgebra.SimpleNumField{T}
   base_field::AbstractAlgebra.Field
   pol::AbstractAlgebra.Poly{T}
   S::Symbol
   primitive::Bool
   primitive_element::AbstractAlgebra.NumFieldElem

   ###
end

mutable struct Loc{T} <: AbstractAlgebra.Ring
    base_ring::AbstractAlgebra.Ring
    prime::T
    primes::Array{T,1}  # in general, not set.
    comp::Bool  # false: den has to be coprime to prime
                # true:  den can ONLY use prime (and powers)

    function Loc{T}(prime::T, primes::Array{T,1}, cached::Bool = true, comp::Bool = false) where
     {T <: AbstractAlgebra.RingElem}
       length(primes) == 0 && error("No element to localize at since array of primes is empty")
       if cached && haskey(LocDict, (AbstractAlgebra.parent(prime), prime, comp))
          return LocDict[AbstractAlgebra.parent(prime), prime, comp]::Loc{T}
       else
          z = new(AbstractAlgebra.parent(prime), prime, primes, comp)
          if cached
             LocDict[AbstractAlgebra.parent(prime), prime, comp] = z
          end
          return z
       end
    end

    function Loc{T}(prime::T, cached::Bool = true, comp::Bool = false) where
     {T <: AbstractAlgebra.RingElem}
      isunit(prime) && error("no-point")
      if cached && haskey(LocDict, (AbstractAlgebra.parent(prime), prime, comp))
        return LocDict[AbstractAlgebra.parent(prime), prime, comp]::Loc{T}
      else
        r = new()
        r.base_ring = AbstractAlgebra.parent(prime)
        r.prime = prime
        r.comp = comp
        if cached
           LocDict[AbstractAlgebra.parent(prime), prime, comp] = r
        end
        return r
      end
    end
 end

const LocDict = Dict{Tuple{AbstractAlgebra.Ring, AbstractAlgebra.RingElement, Bool},
AbstractAlgebra.Ring}()

function isin(a, L::Loc{T}) where {T <: AbstractAlgebra.RingElem}
  iszero(a) && return true
  L.comp || (!isone(gcd(denominator(a), prime(L))) && return false)
  L.comp && ppio(denominator(a), prime(L))[1] != denominator(a.data) && return false
  return true
end

mutable struct LocElem{T} <: AbstractAlgebra.RingElem
   data::AbstractAlgebra.FieldElem
   parent::Loc{T}
   function LocElem{T}(data::AbstractAlgebra.FracElem{T}, par::Loc, checked::Bool = true) where
    {T <: AbstractAlgebra.RingElem}
     checked && (isin(data, par) || error("illegal elt"))
     return new{T}(data,par)
   end
end

# Function fields of curves.
mutable struct FuncField{T} <: Loc{T}
    # The function field K[E] of the elliptic curve E
    # consists of ratios of polynomials. Taking an
    # elliptic curve E as an integral, regular scheme of
    # finite type, then the function field K[E] is
    # just the local ring of the generic point.

    base_curve::EllCrv
    generic_point::EllCrvPt

    function FuncField{T}()
end

###############################################################################
#
#   Data type and parent object methods
#
###############################################################################

elem_type(::Type{Loc{T}}) where {T} = LocElem{T}

parent_type(::Type{LocElem{T}}) where {T} = Loc{T}

base_ring(L::Loc) = L.base_ring

base_ring(a::LocElem) = base_ring(parent(a))

parent(a::LocElem) = a.parent

function check_parent(a::LocElem{T}, b::LocElem{T})  where
    {T <: AbstractAlgebra.RingElem}
    parent(a) !== parent(b) && error("Parent objects do not match")
end


text:
# This file was generated, do not modify it. # hide
trace = simulate(m(x=x, λ=1.0)).trace
y = trace.y

max_stars_repo_name: cscherrer/InformativePrior

max_issues_repo_name: cscherrer/InformativePrior

max_forks_repo_name: cscherrer/InformativePrior


text:
@testset "construct matrix" begin
    q = 5
    A, coarse_domains, scales, basis_functions, multicolor_ordering, fine_domains, tree_function = CompressingSolvers.FD_Laplacian_subdivision_2d(q, 3.0)

    I, J = CompressingSolvers.sparsity_set(multicolor_ordering, CompressingSolvers.center.(fine_domains), tree_function)
    @test allunique(zip(I, J))

    measurement_matrix = CompressingSolvers.form_measurement_matrix(multicolor_ordering)
    measurement_results = CompressingSolvers.measure(cholesky(A), measurement_matrix)

    L = CompressingSolvers.reconstruct(multicolor_ordering, CompressingSolvers.center.(fine_domains), measurement_matrix, measurement_results, tree_function)

    @show norm(inv(Matrix(A)) - L * L')
end


text:
module TestPermutation
  using Base.Test
  using Brim

  # Test utility functions

  c1 = [1 0; 0 1]
  c2 = [0 1; 1 0]
  c3 = [0 0; 1 1]
  c4 = [1 1; 1 1]
  c5 = [0 0; 0 0]

  @test Brim.free_swapable(c1) == true
  @test Brim.free_swapable(c2) == true
  @test Brim.free_swapable(c3) == true
  @test Brim.free_swapable(c4) == false
  @test Brim.free_swapable(c5) == false

  @test Brim.constrained_swapable(c1) == true
  @test Brim.constrained_swapable(c2) == true
  @test Brim.constrained_swapable(c3) == false
  @test Brim.constrained_swapable(c4) == false
  @test Brim.constrained_swapable(c5) == false

  @test Brim.constrained_swap(c1) == c2
  @test Brim.constrained_swap(c2) == c1

  @test Brim.no_empty_rows(c3) == false
  @test Brim.no_empty_rows(c1) == true
  @test Brim.no_empty_columns(c3') == false
  @test Brim.no_empty_columns(c1') == true

  @test Brim.same_row_marginals(c1, c2) == true
  @test Brim.same_row_marginals(c1, c1) == true
  @test Brim.same_row_marginals(c1, c3) == false

  A = [1 1 1 0 0 0; 1 1 1 0 0 0; 1 1 1 0 0 0; 0 0 0 1 1 1; 0 0 0 1 1 1; 0 0 0 1 1 1]

  # null_preserve_marginals
  @test sum(A) == sum(null_preserve_marginals(A))
  @test sum(A) == sum(null_preserve_marginals(A))
  @test sum(A) == sum(null_preserve_marginals(A))

  # null_preserve_rows_marginals
  @test sum(A, 2) == sum(null_preserve_rows_marginals(A), 2)
  @test sum(A, 2) == sum(null_preserve_rows_marginals(A), 2)
  @test sum(A, 2) == sum(null_preserve_rows_marginals(A), 2)

  # null_preserve_columns_marginals
  @test sum(A, 1) == sum(null_preserve_columns_marginals(A), 1)
  @test sum(A, 1) == sum(null_preserve_columns_marginals(A), 1)
  @test sum(A, 1) == sum(null_preserve_columns_marginals(A), 1)

  # null_preserve_fill
  X = null_preserve_fill(A)
  @test sum(A) == sum(X)
  @test Brim.no_empty_rows(X)
  @test Brim.no_empty_columns(X)

end


text:
"""Create a `storage` array for [`propagate`](@ref).

```julia
storage = init_storage(state, tlist)
```

creates a storage array suitable for storing a `state` for each point in
`tlist`.

```julia
storage = init_storage(state, tlist, observables))
```

creates a storage array suitable for the data generated by the `observables`
applied to `state`, see [`map_observables`](@ref), for each point in `tlist`.

```julia
storage = init_storage(data, nt))
```

creates a storage arrays suitable for storing `data` nt times, where
`nt=length(tlist)`. By default, this will be a vector of `typeof(data)` and
length `nt`, or a `n × nt` Matrix with the same `eltype` as `data` if `data` is
a Vector of length `n`.
"""
function init_storage(state, tlist::AbstractVector)
    nt = length(tlist)
    return init_storage(state, nt)
end

function init_storage(state, tlist, observables)
    data = map_observables(observables, state)
    nt = length(tlist)
    return init_storage(data, nt)
end

init_storage(data, nt::Integer) = Vector{typeof(data)}(undef, nt)

init_storage(data::Vector, nt::Integer) = Matrix{eltype(data)}(undef, length(data), nt)

"""Obtain "observable" data from `state`.

```julia
data = map_observables(observables, state)
```

calculates the data for a tuple of `observables` applied to `state`.
For a single observable (tuple of length 1), simply return the result of
[`map_observable`](@ref).

For multiple observables, return the tuple resulting from applying
[`map_observable`](@ref) for each observable. If the tuple is "uniform" (all
elements are of the same type, e.g. if each observable calculates the
expectation value of a Hermitian operator), it is converted to a Vector. This
allows for compact storage in a storage array, see [`init_storage`](@ref).
"""
function map_observables(observables, state)
    if length(observables) == 1
        return map_observable(observables[1], state)
    else
        val_tuple = Tuple(map_observable(O, state) for O in observables)
        uniform_type = typeof(val_tuple[1])
        is_uniform = all(typeof(v) == uniform_type for v in val_tuple[2:end])
        if is_uniform
            return collect(val_tuple)  # convert to Vector
        else
            return val_tuple
        end
    end
end

"""Apply a single `observable` to `state`.

```julia
data = map_observable(observable, state)
```

By default, `observable` is assumed to be callable, and the above is equivalent
to `data = observable(state)`.

If `observable` is a matrix and `state` is a vector evaluate the expectation
value of the observable as `dot(state, observable, state)`.

"""
function map_observable(observable, state)
    return observable(state)
end

function map_observable(observable::AbstractMatrix, state::AbstractVector)
    return dot(state, observable, state)
end

"""Place data into `storage` for time slot `i`.

```julia
    write_to_storage!(storage, i, state, observables)
```

For a `storage` array created by [`init_storage`](@ref), store the data obtains
from [`map_observables`](@ref) into the `storage` for time slot `i`. This
delegates to the more general

```julia
    write_to_storage!(storage, i, data)
```

Conceptually, this corresponds roughly to `storage[i] = data`, but `storage`
may have its own idea on how to store data for a specific time slot. For
example, with the default [`init_storage`](@ref) Vector data will be stored in
a matrix, and `write_to_storage!` will in this case write data to the i'th
column of the matrix.

For a given type of `storage` and `data`, it is the developer's responsibility
that `init_storage` and `write_to_storage!` are compatible.
"""
function write_to_storage!(storage, i::Integer, state, observables)
    data = map_observables(observables, state)
    write_to_storage!(storage, i, data)
end

function write_to_storage!(storage::AbstractVector, i::Integer, data)
    storage[i] = data
end

function write_to_storage!(storage::Matrix{T}, i::Integer, data::Vector{T}) where T
    storage[:, i] .= data
end

"""Obtain data from storage

```julia
get_from_storage!(state, storage, i)
```

extracts data from the `storage` for the i'th time slot. Invese of
[`write_to_storage!`](@ref)
"""
get_from_storage!(state, storage::AbstractVector, i) = copyto!(state, storage[i])
get_from_storage!(state, storage::Matrix, i) = copyto!(state, storage[:, i])


text:
module RegistratorServerless

import GitHub
import LocalRegistry
import Pkg
import Registrator
import RegistryTools

include("types.jl")

include("assert.jl")
include("branch-name.jl")
include("config.jl")
include("credentials.jl")
include("github.jl")
include("local-registry.jl")
include("parse-trigger-issue.jl")
include("project.jl")
include("pull-requests.jl")
include("register.jl")
include("user.jl")
include("utils.jl")

end # module RegistratorServerless


text:
export FuseLowlevelOps, register, main_loop
export FuseFileInfo, FuseEntryParam, FuseArgs, FuseCmdlineOpts, FuseReq, FuseIno
export Cstat, Cflock

import Base.CFunction

const CFu = Ptr{Cvoid}

struct FuseLoopConfig
    clone_fd::Cint
    max_idle_threads::Cuint
end

struct FuseArgs <: Layout
    argc::Cint
    argv::Ptr{LVarVector{Cstring, (x) -> x.argc}}
    allocated::Cint
end

struct FuseCmdlineOpts
    singlethread::Cint
    foreground::Cint
    debug::Cint
    nodefault_subtype::Cint
    mountpoint::Cstring
    show_version::Cint
    show_help::Cint
    clone_fd::Cint
    max_idle_threads::Cuint
end

struct FuseSession <: Layout
end
struct FuseLowlevelOps
    init::CFu
    destroy::CFu
    lookup::CFu
    forget::CFu
    getattr::CFu
    setattr::CFu
    readlink::CFu
    mknod::CFu
    mkdir::CFu
    unlink::CFu
    rmdir::CFu
    symlink::CFu
    rename::CFu
    link::CFu
    open::CFu
    read::CFu
    write::CFu
    flush::CFu
    release::CFu
    fsync::CFu
    opendir::CFu
    readdir::CFu
    releasedir::CFu
    fsyncdir::CFu
    statfs::CFu
    setxattr::CFu
    getxattr::CFu
    listxattr::CFu
    removexattr::CFu
    access::CFu
    create::CFu
    getlk::CFu
    setlk::CFu
    bmap::CFu
    ioctl::CFu
    poll::CFu
    write_buf::CFu
    retrieve_reply::CFu
    forget_multi::CFu
    flock::CFu
    fallocate::CFu
    readdirplus::CFu
    copy_file_range::CFu
    lseek::CFu
end
const F_SIZE = sizeof(FuseLowlevelOps) ÷ sizeof(Ptr)

const FuseIno = UInt64
const FuseMode = UInt32
const FuseDev = UInt64

const Cuid_t = UInt32
const Cgid_t = UInt32
const Coff_t = Csize_t
const Coff64_t = UInt64
const Cpid_t = Cint
const Cfsblkcnt_t = UInt64
const Cfsfilcnt_t = UInt64

struct FuseBufFlags
    flag::Cint
end
const FUSE_BUF_IS_FD = FuseBufFlags(1 << 1)
const FUSE_BUF_FD_SEEK = FuseBufFlags(1 << 2)
const FUSE_BUF_FD_RETRY = FuseBufFlags(1 << 3)

struct FuseBufCopyFlags
    flag::Cint
end
const FUSE_BUF_NO_SPLICE = FuseBufCopyFlags(1 << 1)
const FUSE_BUF_FORCE_SPLICE = FuseBufCopyFlags(1 << 2)
const FUSE_BUF_SPLICE_MOVE = FuseBufCopyFlags(1 << 3)
const FUSE_BUF_SPLICE_NONBLOCK = FuseBufCopyFlags(1 << 4)

"""
    FuseReq

Opaque structure containing the pointer as obtained by fuselib.
"""
struct FuseReq
    pointer::Ptr{Nothing}
end

struct Timespec <: Layout
    seconds::Int64
    ns::Int64
end

struct FuseCtx <: Layout
    uid::UInt32
    gid::UInt32
    pid::UInt32
    umask::FuseMode
end

struct Cstat <: Layout
    dev     :: UInt64
    ino     :: UInt64
    nlink   :: UInt64
    mode    :: FuseMode
    uid     :: Cuid_t
    gid     :: Cgid_t
    pad0    :: UInt32
    rdev    :: UInt64
    size    :: Int64
    blksize :: Int64
    blocks  :: Int64
    atime   :: Timespec
    mtime   :: Timespec
    ctime   :: Timespec
end
struct FuseEntryParam <: Layout
    ino::FuseIno
    generation::UInt64
    attr::Cstat
    attr_timeout::Cdouble
    entry_timeout::Cdouble
end

# Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want'

const FUSE_CAP_ASYNC_READ = Cuint(1 << 0)
const FUSE_CAP_POSIX_LOCKS = Cuint(1 << 1)
const FUSE_CAP_ATOMIC_O_TRUNC = Cuint(1 << 3)
const FUSE_CAP_EXPORT_SUPPORT = Cuint(1 << 4)
const FUSE_CAP_DONT_MASK = Cuint(1 << 6)
const FUSE_CAP_SPLICE_WRITE = Cuint(1 << 7)
const FUSE_CAP_SPLICE_MOVE = Cuint(1 << 8)
const FUSE_CAP_SPLICE_READ = Cuint(1 << 9)
const FUSE_CAP_FLOCK_LOCKS = Cuint(1 << 10)
const FUSE_CAP_IOCTL_DIR = Cuint(1 << 11)
const FUSE_CAP_AUTO_INVAL_DATA = Cuint(1 << 12)
const FUSE_CAP_READDIRPLUS = Cuint(1 << 13)
const FUSE_CAP_READDIRPLUS_AUTO = Cuint(1 << 14)
const FUSE_CAP_ASYNC_DIO = Cuint(1 << 15)
const FUSE_CAP_WRITEBACK_CACHE = Cuint(1 << 16)
const FUSE_CAP_NO_OPEN_SUPPORT = Cuint(1 << 17)
const FUSE_CAP_PARALLEL_DIROPS = Cuint(1 << 18)
const FUSE_CAP_POSIX_ACL = Cuint(1 << 19)
const FUSE_CAP_HANDLE_KILLPRIV = Cuint(1 << 20)
const FUSE_CAP_CACHE_SYMLINKS = Cuint(1 << 23)
const FUSE_CAP_NO_OPENDIR_SUPPORT = Cuint(1 << 24)
const FUSE_CAP_EXPLICIT_INVAL_DATA = Cuint(1 << 25)

struct FuseConnInfo <: Layout
    proto_major::Cuint
    proto_minor::Cuint
    max_write::Cuint
    max_read::Cuint
    max_readahead::Cuint
    capable::Cuint
    want::Cuint
    max_backgrount::Cuint
    congestion_threshold::Cuint
    time_gran::Cuint
    reserved::LFixedVector{Cuint,22}
end

# bit masks for 2nd field of FuseFileInfo
const FUSE_FI_WRITEPAGE = Cuint(1 << 0)
const FUSE_FI_DIRECT_IO = Cuint(1 << 1)
const FUSE_FI_KEEP_CACHE = Cuint(1 << 2)
const FUSE_FI_FLUSH = Cuint(1 << 3)
const FUSE_FI_NONSEEKABLE = Cuint(1 << 4)
const FUSE_FI_CACHE_READDIR = Cuint(1 << 5)

struct FuseFileInfo <: Layout
    flags::Cint
    bits::Cuint
    fh::UInt64
    lock_owner::UInt64
    poll_events::UInt32
end

struct Cflock
    type::Cshort
    whence::Cshort
    start::Coff64_t
    len::Coff64_t
    pid::Cpid_t
end
struct Ciovec
    base::Ptr{Cvoid}
    len::Csize_t
end
struct Cstatvfs
    bsize::Culong
    frsize::Culong
    blocks::Cfsblkcnt_t
    bfree::Cfsblkcnt_t
    bavail::Cfsblkcnt_t
    files::Cfsfilcnt_t
    ffree::Cfsfilcnt_t
    favail::Cfsfilcnt_t
    fsid::Clong
    flag::Culong
    namemax::Culong
    __spare::NTuple{6,Cint}
end

struct FusePollHandle
end
struct FuseBuf <: Layout
    size::Csize_t
    flags::FuseBufFlags
    mem::Ptr{Cvoid}
    fd::Cint
    pos::Coff_t
end
struct FuseBufvec <: Layout
    count::Csize_t
    idx::Csize_t
    off::Csize_t
    buf::LVarVector{FuseBuf}
end
struct FuseForgetData
end

const FUSE_IOCTL_COMPAT = Cuint(1 << 0)
const FUSE_IOCTL_UNRESTRICTED = Cuint(1 << 1)
const FUSE_IOCTL_RETRY = Cuint(1 << 2)
const FUSE_IOCTL_DIR = Cuint(1 << 4)
const FUSE_IOCTL_MAX_IOV = 256

# dummy function - should never by actually called
noop(args...) = UV_ENOTSUP
const REGISTERED = Function[noop for i = 1:F_SIZE]
regops() = REGISTERED
# utility functions
function fcallback(which::Int, args...)
    regops()[which](args...)
end

function register(which::Int, f::Function)
    regops()[which] = f
end
function register(which::Symbol, f::Function)
    index = findfirst(isequal(which), fieldnames(FuseLowlevelOps))
    register(index, f)
end
register(f::Function) = register(nameof(f), f)

function FuseLowlevelOps(all::FuseLowlevelOps, reg::Vector{Function})
    FuseLowlevelOps(filter_ops(all, reg)...)
end
function filter_ops(all::Vector, reg::Vector{Function})
    [reg[i] == noop ? C_NULL : all[i] for i in eachindex(all)]
end

function filter_ops(fs::Module)
    all = ALL_FLO()
    res = fill(C_NULL, length(fieldnames(FuseLowlevelOps)))
    ro = regops()
    for (i, f) in enumerate(fieldnames(FuseLowlevelOps))
        if (c = getp(fs, f, noop)) != noop
            res[i] = all[i]
            ro[i] = c
        end
    end
    res
end

function getp(m, f::Symbol, def)
    try
        getproperty(m, f)
    catch
        def
    end
end

function create_args(CMD::String, arg::AbstractVector{String})
    argc = length(arg)
    data = create_bytes(FuseArgs, argc + 2)
    args = CStructGuided{FuseArgs}(data)
    argv = args.argv
    args.argc = argc + 1
    argv[1] = CMD
    for i = 1:argc
        argv[i+1] = arg[i]
    end
    args
end

function main_loop(args::AbstractVector{String}, fs::Module)

    fargs = create_args("command", args)
    opts = fuse_parse_cmdline(fargs)

    callbacks = filter_ops(fs)

    se = ccall((:fuse_session_new, :libfuse3), Ptr{Nothing},
        (Ptr{FuseArgs}, Ptr{CFu}, Cint, Ptr{Nothing}),
        fargs, callbacks, length(callbacks), C_NULL)

    se == C_NULL && throw(ArgumentError("fuse_session_new failed"))

    rc = ccall((:fuse_session_mount, :libfuse3), Cint, (Ptr{Nothing}, Cstring), se, opts.mountpoint)
    rc != 0 && throw(ArgumentError("fuse_session_mount failed"))

    rc = ccall((:fuse_session_loop, :libfuse3), Cint, (Ptr{Nothing},), se)
    rc != 0 && throw(ArgumentError("fuse_session_loop failed"))

    ccall((:fuse_session_unmount, :libfuse3), Cvoid, (Ptr{Nothing},), se)
    ccall((:fuse_session_destroy, :libfuse3), Cvoid, (Ptr{Nothing},), se)
end

function fuse_parse_cmdline(args::CStructAccess{FuseArgs})
    opts = create_bytes(FuseCmdlineOpts)
    popts = pointer_from_vector(opts)
    ccall((:fuse_parse_cmdline, :libfuse3), Cint, (Ptr{FuseArgs}, Ptr{UInt8}), args, popts)
    CStructGuided{FuseCmdlineOpts}(opts)
end

function log(args...)
    flush(stderr)
    println(stderr, args...)
end

# Base.unsafe_convert(::Type{Ptr{FuseReq}}, cs::FuseReq) where T = Ptr{FuseReq}(cs.pointer)