text:
"""
    fit!(estimator, num_iterations, X, y[, test...]; [verbosity = 1, is_row_major = false])
    fit!(estimator, X, y[, test...]; [verbosity = 1, is_row_major = false])
    fit!(estimator, X, y, train_indices[, test_indices...]; [verbosity = 1, is_row_major = false])
    fit!(estimator, train_dataset[, test_datasets...]; [verbosity = 1])

Fit the `estimator` with features data `X` and label `y` using the X-y pairs in `test` as
validation sets.
Alternatively, Fit the `estimator` with `train_dataset` and `test_datasets` in the form of Dataset class(es)

Return a dictionary with an entry for each validation set. Each entry of the dictionary is another
dictionary with an entry for each validation metric in the `estimator`. Each of these entries is an
array that holds the validation metric's value at each iteration.

# Arguments
* `estimator::LGBMEstimator`: the estimator to be fit.
* `X::Matrix{TX<:Real}`: the features data.
* `y::Vector{Ty<:Real}`: the labels.
* `test::Tuple{Matrix{TX},Vector{Ty}}...`: optionally contains one or more tuples of X-y pairs of
    the same types as `X` and `y` that should be used as validation sets.
* `train_dataset::Dataset`: prepared train_dataset
* `test_datasets::Vector{Dataset}`: (optional) prepared test_datasets
* `verbosity::Integer`: keyword argument that controls LightGBM's verbosity. `< 0` for fatal logs
    only, `0` includes warning logs, `1` includes info logs, and `> 1` includes debug logs.
* `is_row_major::Bool`: keyword argument that indicates whether or not `X` is row-major. `true`
    indicates that it is row-major, `false` indicates that it is column-major (Julia's default).
* `weights::Vector{Tw<:Real}`: the training weights.
* `init_score::Vector{Ti<:Real}`: the init scores.
"""
function fit!(
    estimator::LGBMEstimator, X::Matrix{TX}, y::Vector{Ty}, test::Tuple{Matrix{TX},Vector{Ty}}...;
    verbosity::Integer = 1,
    is_row_major = false,
    weights::Vector{Tw} = Float32[],
    init_score::Vector{Ti} = Float64[],
) where {TX<:Real,Ty<:Real,Tw<:Real,Ti<:Real}

    start_time = now()

    log_debug(verbosity, "Started creating LGBM training dataset\n")
    ds_parameters = stringifyparams(estimator, DATASETPARAMS)
    train_ds = LGBM_DatasetCreateFromMat(X, ds_parameters, is_row_major)
    LGBM_DatasetSetField(train_ds, "label", y)
    if length(weights) > 0
        LGBM_DatasetSetField(train_ds, "weight", weights)
    end
    if length(init_score) > 0
        LGBM_DatasetSetField(train_ds, "init_score", init_score)
    end

    test_dss = []

    for test_entry in test
        test_ds = LGBM_DatasetCreateFromMat(test_entry[1], ds_parameters, train_ds, is_row_major)
        LGBM_DatasetSetField(test_ds, "label", test_entry[2])
        push!(test_dss, test_ds)
    end

    return fit!(estimator, train_ds, test_dss..., verbosity=verbosity)
end

# Pass Dataset class directly. This will speed up the process if it is part of an iterative process and pre-constructed dataset(s) are available
function fit!(
    estimator::LGBMEstimator,
    train_dataset::Dataset,
    test_datasets::Dataset...;
    verbosity::Integer = 1,
)

    start_time = now()
    log_debug(verbosity, "Started creating LGBM booster\n")
    bst_parameters = stringifyparams(estimator, BOOSTERPARAMS) * " verbosity=$verbosity"
    estimator.booster = LGBM_BoosterCreate(train_dataset, bst_parameters)

    n_tests = length(test_datasets)
    tests_names = Array{String}(undef,n_tests)

    for (testset_enum, test_dataset) in enumerate(test_datasets)
        tests_names[testset_enum] = "test_$(testset_enum)"
        LGBM_BoosterAddValidData(estimator.booster, test_dataset)
    end

    log_debug(verbosity, "Started training...\n")
    results = train!(estimator, tests_names, verbosity, start_time)

    return results
end

function train!(
    estimator::LGBMEstimator,
    num_iterations::Int,
    tests_names::Vector{String},
    verbosity::Integer,
    start_time::DateTime,
)
    results = Dict{String,Dict{String,Vector{Float64}}}()
    metrics = LGBM_BoosterGetEvalNames(estimator.booster)

    bigger_is_better = Dict(metric => ifelse(in(metric, MAXIMIZE_METRICS), 1., -1.) for metric in metrics)
    best_score = Dict{String,Dict{String,Real}}()
    best_iter = Dict{String,Dict{String,Real}}()

    for metric in metrics
        best_score[metric] = Dict{String,Real}()
        best_iter[metric] = Dict{String,Real}()
        for tests_name in tests_names
            best_score[metric][tests_name] = -Inf
            best_iter[metric][tests_name] = 1
        end
    end

    start_iter = get_iter_number(estimator) + 1
    end_iter = start_iter + num_iterations - 1

    for (idx, iter) in enumerate(start_iter:end_iter)

        is_finished = LGBM_BoosterUpdateOneIter(estimator.booster)

        log_debug(verbosity, Dates.CompoundPeriod(now() - start_time), " elapsed, finished iteration ", iter, "\n")

        if is_finished == 0
            is_finished = eval_metrics!(
                results, estimator, tests_names, iter, verbosity,
                bigger_is_better, best_score, best_iter, metrics,
            )
        end

        if is_finished == 1
            break
        end
    end

    # save the model in serialised form, in case we should be deepcopied or serialised elsewhere
    estimator.model = LGBM_BoosterSaveModelToString(estimator.booster)

    return results
end
# Old signature, pass through args
function train!(
    estimator::LGBMEstimator, tests_names::Vector{String}, verbosity::Integer, start_time::DateTime
)
    return train!(estimator, estimator.num_iterations, tests_names, verbosity, start_time)
end

function eval_metrics!(
    results::Dict{String,Dict{String,Vector{Float64}}},
    estimator::LGBMEstimator,
    tests_names::Vector{String},
    iter::Integer,
    verbosity::Integer,
    bigger_is_better::Dict{String,Float64},
    best_score::Dict{String,Dict{String,Real}},
    best_iter::Dict{String,Dict{String,Real}},
    metrics::Vector{String},
)
    now_scores = Dict{String,Vector{Float64}}()

    if (iter - 1) % estimator.metric_freq == 0
        if estimator.is_training_metric
            now_scores["training"] = LGBM_BoosterGetEval(estimator.booster, 0)
        end
        for (test_idx, tests_name) in enumerate(tests_names)
            now_scores[tests_name] = LGBM_BoosterGetEval(estimator.booster, test_idx)
        end
    end

    # check early stopping condition
    if estimator.early_stopping_round > 0
        for tests_name in tests_names
            for (metric_idx, metric) in enumerate(metrics)
                maximize_score = bigger_is_better[metric] * now_scores[tests_name][metric_idx]
                # All good if maximize_score is better than previous best
                if maximize_score > best_score[metric][tests_name]
                    best_score[metric][tests_name] = maximize_score
                    best_iter[metric][tests_name] = iter
                    continue
                # All good if difference between current and best iter is within early_stopping_round
                elseif (iter - best_iter[metric][tests_name]) < estimator.early_stopping_round
                    continue
                end
                log_info(verbosity, "Early stopping at iteration ", iter, ", the best iteration round is ", best_iter[metric][tests_name], "\n")
                return 1
            end

        end
    end

    for (metric_idx, metric_name) in enumerate(metrics)
	    for dataset_key in keys(now_scores)
            store_scores!(results, dataset_key, metric_name, now_scores[dataset_key][metric_idx])

            # print scores
            log_info(verbosity, "Iteration: ", iter, ", ", dataset_key, "'s ")
            log_info(verbosity, metric_name, ": ", now_scores[dataset_key][metric_idx])
                metric_idx < length(metrics) && log_info(verbosity, ", ")
            log_info(verbosity, "\n")

        end
    end
    return 0
end

function store_scores!(
    results::Dict{String,Dict{String,Vector{Float64}}},
    dataset_key::String,
    metric_name::String,
    value_to_add::Float64,
)
    if !haskey(results, dataset_key)
        results[dataset_key] = Dict{String,Vector{Float64}}()
        results[dataset_key][metric_name] = Float64[]
    elseif !haskey(results[dataset_key], metric_name)
        results[dataset_key][metric_name] = Float64[]
    end
    push!(results[dataset_key][metric_name], value_to_add)
end

function merge_scores(
    old_scores::Dict{String,Dict{String,Vector{Float64}}},
    additional_scores::Dict{String,Dict{String,Vector{Float64}}},
)

    if keys(old_scores) != keys(additional_scores)
        throw(ErrorException("Tried to merge metrics with different data sets:\n    a=> $(keys(old_scores))\n    b=> $(keys(additional_scores))"))
    end

    new_scores = Dict{String,Dict{String,Vector{Float64}}}()
    for (key, oldvals) in old_scores
        new_scores[key] = merge_scores(old_scores[key], additional_scores[key])
    end

    return new_scores
end

function merge_scores(
    old_scores::Dict{String,Vector{Float64}},
    additional_scores::Dict{String,Vector{Float64}},
)

    if keys(old_scores) != keys(additional_scores)
        throw(ErrorException("Tried to merge metrics with different metrics:\n    a=> $(keys(old_scores))\n    b=> $(keys(additional_scores))"))
    end

    new_scores = Dict{String,Vector{Float64}}()
    for (key, oldvals) in old_scores
        new_scores[key] = cat(oldvals, additional_scores[key]; dims=1)
    end

    return new_scores
end

function stringifyparams(estimator::LGBMEstimator, params::Vector{Symbol})
    paramstring = ""
    n_params = length(params)
    valid_names = fieldnames(typeof(estimator))
    for (param_idx, param_name) in enumerate(params)
        if in(param_name, valid_names)
            param_value = getfield(estimator, param_name)
            if !isempty(param_value)
                # Convert parameters that contain indices to C's zero-based indices.
                if in(param_name, INDEXPARAMS)
                    param_value .-= 1
                end

                if typeof(param_value) <: Array
                    n_entries = length(param_value)
                    if n_entries >= 1
                        paramstring = string(paramstring, param_name, "=", param_value[1])
                        for entry_idx in 2:n_entries
                            paramstring = string(paramstring, ",", param_value[entry_idx])
                        end
                        paramstring = string(paramstring, " ")
                    end
                else
                    paramstring = string(paramstring, param_name, "=", param_value, " ")
                end
            end
        end
    end
    return paramstring[1:end - 1]
end


text:
using IDRsSolver
using Base.Test

srand(51)
n = 10
maxiter = n*n*n
tol = 1E-8
s = 8

## real

A = -eye(n) + 0.7*(2rand(n,n)-1)
B = -eye(n) + 0.7*(2rand(n,n)-1)
xsol = rand(n)
Xsol = 0.5eye(n) + 0.3(2rand(n,n)-1)
C = Xsol + A*Xsol*B
D = A*Xsol + Xsol*B
b = A*xsol

X, _ = stein(A, B, C; s=s, tol=tol, maxiter=maxiter)
@test vecnorm(Xsol - X) <= 10*tol*vecnorm(C)

X, _ = syl(A, B, D; s=s, tol=tol, maxiter=maxiter)
@test vecnorm(Xsol - X) <= 10*tol*vecnorm(D)

x, _ = idrs(A, b; s=s, tol=tol, maxiter=maxiter)
@test norm(xsol - x) <= 10*tol*norm(b)

# complex

A = -eye(n) + 0.7*(2rand(n,n)-1) + im*0.7*(2rand(n,n)-1)
B = -eye(n) + 0.7*(2rand(n,n)-1) + im*0.7*(2rand(n,n)-1)
xsol = rand(n) + im*rand(n)
Xsol = 0.5eye(n) + 0.3*(2rand(n,n)-1) + im*0.3*(2rand(n,n)-1)
C = Xsol + A*Xsol*B
D = A*Xsol + Xsol*B
b = A*xsol

X, _ = stein(A, B, C; s=s, tol=tol, maxiter=maxiter)
@test vecnorm(Xsol - X) <= 10*tol*vecnorm(C)

X, _ = syl(A, B, D; s=s, tol=tol, maxiter=maxiter)
@test vecnorm(Xsol - X) <= 10*tol*vecnorm(D)

x, _ = idrs(A, b; s=s, tol=tol, maxiter=maxiter)
@test norm(xsol - x) <= 10*tol*norm(b)

ext: jl


text:
using Compat
using ProtoBuf
import ProtoBuf.meta
import Base: hash, isequal, ==

# service methods for ContainerManagementProtocolService
const _ContainerManagementProtocolService_methods = MethodDescriptor[
        MethodDescriptor("startContainers", 1, StartContainersRequestProto, StartContainersResponseProto),
        MethodDescriptor("stopContainers", 2, StopContainersRequestProto, StopContainersResponseProto),
        MethodDescriptor("getContainerStatuses", 3, GetContainerStatusesRequestProto, GetContainerStatusesResponseProto)
    ] # const _ContainerManagementProtocolService_methods
const _ContainerManagementProtocolService_desc = ServiceDescriptor("ContainerManagementProtocolService", 1, _ContainerManagementProtocolService_methods)

ContainerManagementProtocolService(impl::Module) = ProtoService(_ContainerManagementProtocolService_desc, impl)

type ContainerManagementProtocolServiceStub <: AbstractProtoServiceStub{false}
    impl::ProtoServiceStub
    ContainerManagementProtocolServiceStub(channel::ProtoRpcChannel) = new(ProtoServiceStub(_ContainerManagementProtocolService_desc, channel))
end # type ContainerManagementProtocolServiceStub

type ContainerManagementProtocolServiceBlockingStub <: AbstractProtoServiceStub{true}
    impl::ProtoServiceBlockingStub
    ContainerManagementProtocolServiceBlockingStub(channel::ProtoRpcChannel) = new(ProtoServiceBlockingStub(_ContainerManagementProtocolService_desc, channel))
end # type ContainerManagementProtocolServiceBlockingStub

startContainers(stub::ContainerManagementProtocolServiceStub, controller::ProtoRpcController, inp::StartContainersRequestProto, done::Function) = call_method(stub.impl, _ContainerManagementProtocolService_methods[1], controller, inp, done)
startContainers(stub::ContainerManagementProtocolServiceBlockingStub, controller::ProtoRpcController, inp::StartContainersRequestProto) = call_method(stub.impl, _ContainerManagementProtocolService_methods[1], controller, inp)

stopContainers(stub::ContainerManagementProtocolServiceStub, controller::ProtoRpcController, inp::StopContainersRequestProto, done::Function) = call_method(stub.impl, _ContainerManagementProtocolService_methods[2], controller, inp, done)
stopContainers(stub::ContainerManagementProtocolServiceBlockingStub, controller::ProtoRpcController, inp::StopContainersRequestProto) = call_method(stub.impl, _ContainerManagementProtocolService_methods[2], controller, inp)

getContainerStatuses(stub::ContainerManagementProtocolServiceStub, controller::ProtoRpcController, inp::GetContainerStatusesRequestProto, done::Function) = call_method(stub.impl, _ContainerManagementProtocolService_methods[3], controller, inp, done)
getContainerStatuses(stub::ContainerManagementProtocolServiceBlockingStub, controller::ProtoRpcController, inp::GetContainerStatusesRequestProto) = call_method(stub.impl, _ContainerManagementProtocolService_methods[3], controller, inp)

export ContainerManagementProtocolService, ContainerManagementProtocolServiceStub, ContainerManagementProtocolServiceBlockingStub, startContainers, stopContainers, getContainerStatuses


text:
# Autogenerated wrapper script for wrfuser_jll for aarch64-linux-musl-libgfortran4
export WRFUser

using CompilerSupportLibraries_jll
JLLWrappers.@generate_wrapper_header("wrfuser")
JLLWrappers.@declare_library_product(WRFUser, "wrfuser.so")
function __init__()
    JLLWrappers.@generate_init_header(CompilerSupportLibraries_jll)
    JLLWrappers.@init_library_product(
        WRFUser,
        "lib/wrfuser.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
using Distributions

function nfold_sample_selection(filename, k=1, nfolds=5)
  #=
  Split a sample into training and testing data
  =#
  f = open(filename, "r")
  ftest = open("$(filename).test", "w")
  ftrain = open("$(filename).train", "w")

  for line in eachline(f)
    if rand(0:nfold)==k # test data
      write(ftest, line)
    else # training data
      write(ftrain, line)
    end
  end

  close(f)
  close(ftest)
  close(ftrain)
end

max_stars_repo_name: potterzot/jstats

max_issues_repo_name: potterzot/jstats

max_forks_repo_name: potterzot/jstats


text:
two32  = Float32(2)
twoR32 = Robust32(2)
sqrt_two32 = sqrt(two32)
sqrt_twoR32 = sqrt(twoR32)

@testset "low level functions" begin
  @test hash(sqrt_two32) == hash(sqrt_twoR32)
  @test string(sqrt_two32) == string(sqrt_twoR32)

  @test typemax(Float32) == typemax(Robust32)
  @test maxintfloat(Float32) == maxintfloat(Robust32)
  @test floatmin(Float32) == floatmin(Robust32)
  @test floatmax(Float32) == floatmax(Robust32)
end


text:
"""
	AllPass(f, order, BWoct, fs=96e3)

Return Biquad of sampling frequency fs as DSP.SecondOrderSections that resembles Lake 1st- or
2nd-order Allpass.

# Implementation

The 2nd order Allpass ist constructed according to

https://shepazu.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html (12.6.2019)

where the analog Q formula is utilized instead of the prewarped version to
fit the output of the Lake processor. The Bandwidth of the Lake processor
for some dubious reason is double that of the method proposed in the link, so
a factor 2 was added to account for this.

The 1st order Allpass is constructed from the simple zero position at 1 and
pole position at -1 and a polarity reversal, which already results in an
analog 1st order Allpass prototype centered around 1 rad/s that can be used
with the DSP.Lowpass responsetype (only shifts frequency) to design the Biquad.
"""
function AllPass(f, order, BWoct, fs=96e3)
	w0 = 2*pi*f/fs
	if order==2
		BWoct = 2*BWoct #somehow necessary in Lake
		alpha = sin(w0)*sinh(log(2)/2*BWoct)

		b0 = 1-alpha
		b1 = -2*cos(w0)
		b2 = 1+alpha
		a0 = 1+alpha
		a1 = -2*cos(w0)
		a2 = 1-alpha

		result = [b0 b1 b2 a1 a2]./a0
		Filter = SecondOrderSections(Biquad(result...))
	elseif order==1
		analogPrototype = ZeroPoleGain([1.], [-1.], -1.)
		Filter = convert(SecondOrderSections, digitalfilter(Lowpass(f, fs=fs), analogPrototype))
	else
		error(string("Allpass order must be 1 or 2. Was given ", order))
	end
	return Filter
end


text:
"""
    ndgrid(x,y,...)

For d vector inputs, return d matrices representing the coordinate functions on the
tensor product grid.
"""
function ndgrid(x...)
    I = CartesianIndices( fill(undef,length.(x)) )
    [ [ x[d][i[d]] for i in I]  for d = 1:length(x) ]
end

"""
    rectdisc(m,xspan,n,yspan)

Create matrices and helpers for finite-difference discretization of a rectangle that is
the tensor  product of intervals `xspan` and `yspan`, using `m`+1 and `n`+1 points in
the two coordinates.
"""
function rectdisc(m,xspan,n,yspan)
    # Initialize grid and finite differences.
    x,Dx,Dxx = diffmat2(m,xspan)
    y,Dy,Dyy = diffmat2(n,yspan)
    X = repeat(x,outer=(1,n+1))
    Y = repeat(y',outer=(m+1,1))

    # Locate boundary points.
    isbndy = fill(true,m+1,n+1)
    isbndy[2:m,2:n] .= false

    # Get the diff. matrices recognized as sparse. Also include reshaping functions.
    disc = (
        Dx=sparse(Dx), Dxx=sparse(Dxx),
        Dy=sparse(Dy), Dyy=sparse(Dyy),
        Ix=Diagonal(ones(m+1)), Iy=Diagonal(ones(n+1)),
        isbndy=isbndy,
        vec=vec,
        unvec=u -> reshape(u,m+1,n+1)
        )
    return X,Y,disc
end

"""
    poissonfd(f,g,m,xspan,n,yspan)

Solve Poisson's equation on a rectangle by finite differences. Function `f` is the
forcing function and function `g` gives the  Dirichlet boundary condition. The rectangle
is the tensor product of intervals `xspan` and `yspan`,  and the discretization uses
`m`+1 and `n`+1 points in the two coordinates.

Return matrices of the solution values, and the coordinate functions, on the grid.
"""
function poissonfd(f,g,m,xspan,n,yspan)
    # Initialize the rectangle discretization.
    X,Y,d = rectdisc(m,xspan,n,yspan)

    # Form the collocated PDE as a linear system.
    A = kron(d.Iy,d.Dxx) + kron(d.Dyy,d.Ix)  # Laplacian matrix
    b = d.vec(f.(X,Y))

    # Replace collocation equations on the boundary.
    scale = maximum(abs.(A[n+2,:]))
    I = kron(d.Iy,d.Ix)
    A[d.isbndy[:],:] = scale*I[d.isbndy[:],:]                 # Dirichet assignment
    b[d.isbndy[:]] = scale*g.( X[d.isbndy],Y[d.isbndy] )  # assigned values

    # Solve the linear sytem and reshape the output.
    u = A\b
    U = d.unvec(u)
    return U,X,Y
end

"""
    newtonpde(f,g,m,xspan,n,yspan)

Newton's method with finite differences to solve the PDE `f`(u,x,y,disc)=0 on the
rectangle `xspan` ``\times`` `yspan`, subject to `g`(x,y)=0 on the boundary. Use `m`+1
points in x by `n`+1 points in y.

Return matrices of the solution values, and the coordinate functions, on the grid.
"""

function newtonpde(f,g,m,xspan,n,yspan)
    # Discretization.
    X,Y,d = rectdisc(n,xspan,n,yspan)

    # This evaluates the discretized PDE and its Jacobian, with all the
    # boundary condition modifications applied.
    function residual(U)
        R,J = f(U,X,Y,d)
        Ixy = Diagonal(ones(size(J,1)))   # used for row replacements
        scale = maximum(abs.(J))
        J[vec(d.isbndy),:] = scale*Ixy[d.isbndy[:],:]
        XB = X[d.isbndy];  YB = Y[d.isbndy];
        @. R[d.isbndy] = scale*(U[d.isbndy] - g(XB,YB))
        r = d.vec(R)
        return r,J
    end

    # Intialize the Newton iteration.
    U = zeros(size(X))
    r,J = residual(U)
    tol = 1e-10;  itermax = 20;
    s = Inf;  normr = norm(r);  k = 1;

    lambda = 1
    while (norm(s) > tol) && (normr > tol)
        s = -(J'*J + lambda*I) \ Vector(J'*r)  # damped step
        Unew = U + d.unvec(s)
        rnew,Jnew = residual(Unew)

        if norm(rnew) < normr
            # Accept and update.
            lambda = lambda/6;   # dampen the Newton step less
            U = Unew;  r = rnew;  J = Jnew;
            normr = norm(r)
            k = k+1
            println("Norm of residual = $normr")
        else
            # Reject.
            lambda = lambda*4;   # dampen the Newton step more
        end

        if k==itermax
            @warn "Maximum number of Newton iterations reached."
            break
        end
    end
    return U,X,Y
end

max_stars_repo_name: snowdj/fnc-extras

max_issues_repo_name: snowdj/fnc-extras

max_forks_repo_name: snowdj/fnc-extras


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

using Markdown
using InteractiveUtils

# ╔═╡ c21d05c1-bd10-46cc-bc5a-d737d047131f
using SampledSignals

# ╔═╡ 99422a59-ffe4-4dc0-bb80-2245d41aaa74
include("definitions/NoteNames.jl")

# ╔═╡ f3cf3e66-b414-11eb-129f-1f82995a6e8e
md"# 3-Limit
One measure of the harmonic complexity of a system is
how much of the harmonic series it uses.
A 3-limit system treats the first 3 harmonics as important,
and so treats octaves and fifths as important intervals,
and also includes intervals derived from octaves and fifths."

# ╔═╡ 21ad163c-9031-4ebb-8dd2-a1a297f97456
fs = 48000

# ╔═╡ 5dedb960-1524-475b-b870-61a8254c7993
function tone(t)
	t = t/pi%2-1
	t = 3/2*sqrt(3)*t*(t*t-1)
end

# ╔═╡ e0aff7b7-a355-4138-87cd-d5113ee82623
function note(freq)
	return SampleBuf(tone.(Array(LinRange(1, 2*pi*freq, fs))), fs)
end

# ╔═╡ 752a031e-7c58-4af6-a2ab-965a1e43760e
md"## Important intervals
our important intervals are the octave and the fifth"

# ╔═╡ 8882303c-4ae7-44a5-8d38-8c4e73f15892
# Octave
note(C)/2 + note(2*C)/2

# ╔═╡ 87212fe7-ac94-4173-b3b6-a9afe58783ea
# Fifth
note(C)/2 + note(G)/2

# ╔═╡ 61482b04-b6fb-495a-94ae-92a84317f6f5
md"## General 3-limit intervals
Using octaves and fifths it is possible to construct any interval
that has integers made up of powers of $2$ and $3$: $2^n:3^m$ as a reduced ratio.
There are infinitely many intervals, most of which aren't very consonant.

## 3-limit note names
Using the concert pitch standard $A=440$ we can get a set of notes,
one note for each 3-limit interval.

"

# ╔═╡ 799e0825-ac5c-46e5-a34a-685a5382cf63
# An octave normalized cycle of fifths limited to single flats/sharps
vcat([note.(freq) for freq=[Fb, Cb, Gb, Db, Ab, Eb, Bb, F, C, G, D, A, E, B, Fs, Cs, Gs, Ds, As, Es, Bs]]...)

# ╔═╡ 69e54625-9e7a-4a62-995d-ff4550e9167b
md"## Scales
Commonly a specific set of pitches, a scale, is used.
This is both to structure the music to be more cohesive by repeating the same
notes instead of drifting harmonically throughout a piece,
and also so that instruments don't have to be tuned to infinite different notes.

### Octave repeating scales
A scale can be defined by the notes in a single octave
and repeated across all octaves.
This is convenient since any number of octaves is harmonious
so sounds in different registers will still sound nice together in the scale.

### Scales from stacked fifths
Scales made from stacking fifths
will have the most pure fifths possible
for the number of notes in the scale.
"

# ╔═╡ 61f66f37-1568-4fb6-b0b0-ae6d13110c73
# One fifth leaves large gaps
vcat([note.(freq) for freq=[C, G, 2C]]...)

# ╔═╡ 20b4c50b-39f8-494e-be2b-d9f9f81fa8e5
# Two fifths has one whole step but two large 4ths
vcat([note.(freq) for freq=[C, D, G, 2C]]...)

# ╔═╡ 4a6d05fb-341a-4487-9685-d6092dea902c
# Three fifths splits one fourth but not the other
vcat([note.(freq) for freq=[C, D, G, A, 2C]]...)

# ╔═╡ 28fe6d6b-bbab-4cde-b437-001f7894a2f0
# Four fifths make a pentatonic scale
vcat([note.(freq) for freq=[C, D, E, G, A, 2C]]...)

# ╔═╡ 1619d9c4-d151-4060-9172-954500935545
# five fifths introduce a semitone but leave a gap larger than a whole tone
vcat([note.(freq) for freq=[C, D, E, Fs, G, A, 2C]]...)

# ╔═╡ fe4516c3-2008-492f-8563-3daa92470175
# six fifths give a heptatonic scale with two semitones and 5 whole tones
vcat([note.(freq) for freq=[C, D, E, Fs, G, A, B, 2C]]...)

# ╔═╡ 9a19129d-3b2a-4a59-aa72-0f8f6a349e53
# Adding fifths splits whole tones into semitones until 11 when everything is semitones
vcat([note.(freq) for freq=[C, Cs, D, Ds, E, Es, Fs, G, Gs, A, As, B, 2C]]...)

# ╔═╡ cf4fe547-f2e1-4e2f-8e52-168cce001061
#Adding anything else leads to a very small interval that sounds more out of tune than like a distinct note
vcat([note.(freq) for freq=[Bs, 2C]]...)

# ╔═╡ 876750d7-d1c2-44d4-a367-984d060870c4
md"To get even intervals, 5 note, 7 note and 12 note scales
are the most natural to make from stacking fifths in octaves.
We can make modes of these scales by starting down some of the fifths instead of up.
This gives us the pentatonic scale and it's modes, the heptatonic modes, and the chromatic scale"

# ╔═╡ bbdace00-0b8e-4963-af37-528b2a4aaafc
# Pentationic major (all fifths)
vcat([note.(freq) for freq=[C, D, E, G, A, 2C]]...)

# ╔═╡ 0ea9acfe-4045-4804-bc78-c802cf0f5577
# 3 fifths one fourth
vcat([note.(freq) for freq=[C, D, F, G, A, 2C]]...)

# ╔═╡ 834e0df6-c976-4c22-b1c4-95e9c8d3cade
# 2 fifths 2 fourths
vcat([note.(freq) for freq=[C, D, F, G, Bb, 2C]]...)

# ╔═╡ a83525a3-1228-4d50-8f85-df63ee11552b
# one fifth 3 fourths
vcat([note.(freq) for freq=[C, Eb, F, G, Bb, 2C]]...)

# ╔═╡ 4708c80b-3166-4c21-992a-8d07ceb52bf2
# all fourths
vcat([note.(freq) for freq=[C, Eb, F, Gb, Bb, 2C]]...)

# ╔═╡ ee828da7-05f1-4fc2-9db7-589a9c1b735d
# Lydian
vcat([note.(freq) for freq=[C, D, E, Fs, G, A, B, 2C]]...)

# ╔═╡ 83223d7d-fd40-4043-ae12-77b501fe1136
# Ionian (major)
vcat([note.(freq) for freq=[C, D, E, F, G, A, B, 2C]]...)

# ╔═╡ b1d1a608-7474-4ee4-8b75-1459a848b188
# Myxolydian
vcat([note.(freq) for freq=[C, D, E, F, G, A, Bb, 2C]]...)

# ╔═╡ 8c45ec80-a4dc-4ebd-a296-8739a1eb86ff
# Dorian
vcat([note.(freq) for freq=[C, D, Eb, F, G, A, Bb, 2C]]...)

# ╔═╡ b6f61f04-f944-4030-91f3-f75e15dc7fc6
# Aeolian (minor)
vcat([note.(freq) for freq=[C, D, Eb, F, G, Ab, Bb, 2C]]...)

# ╔═╡ 52782ffe-02e8-4dd1-886a-97e8a3615560
# Phrygian
vcat([note.(freq) for freq=[C, Db, Eb, F, G, Ab, Bb, 2C]]...)

# ╔═╡ d2a2ebb6-3f2a-4165-a56a-d8a2a0cd5312
# Locrian
vcat([note.(freq) for freq=[C, Db, Eb, F, Gb, Ab, Bb, 2C]]...)

# ╔═╡ 90035d61-3dba-480e-8b4f-200b65b8f3f7
md"Generally speaking the more fifths are used in the scale the bighter it sounds
and the more fourths the darker.
This depends only on the relation to the tonic,
since modes by definition contain all the same intervals."

# ╔═╡ fc024776-6567-481b-bcce-c87d10460243
md"### Simple tetrachord constructions
If we put the closest intervals to the root, up and down a fifth,
we get an octave split into two intervals of a fourth."

# ╔═╡ e8f1a177-9a0e-48a0-9fd7-8c00defd286a
vcat([note.(freq) for freq=[C, F, G, 2C]]...)

# ╔═╡ ce64e368-01c3-49d3-ae11-ac889edfcff0
md"The interval in the middle, between the fourth and fifth, is $9:8$.
This gives a nice sounding interval that is small enough to use in melodic lines (as a step). We can fill in the remaining fourths with whole steps to bridge gaps in melodic lines.
If we use one whole step per fourth we get 4 of the pentatonic scales again,
and it is always one of the pentatonic modes derived from stacking.

If we use two whole steps per fourth
we get 7 note scalse with a semitone per fourth.
This is one kind of tuning by tetrachords: 4 notes to a 4th.
Tetrachord constructions include but go beyond this 3-limit construction using two whole steps and a semitone.
Using two whole steps there are 3 options per tetrachord, w w s, w s w, and s w w.
I call them major, dorian, and phrygian,
because if you use two major tetrachords you get a major scale,
two dorian and it's a dorian scale,
two phrygian and it's a phrygian scale.
We get 9 scales in total combining tetrachords,
only 5 of which are modes (the modes with both a fourth and fifth).
The four remaining scales are:"

# ╔═╡ ae376c87-f212-4e19-8c2d-af79875ef79f
# (s w w) (w w s) Neopolitan major
vcat([note.(freq) for freq=[C, Db, Eb, F, G, A, B, 2C]]...)

# ╔═╡ f8ff6af6-10f2-4f13-a5f4-b0e1a94ca95d
# (w s w) (w w s) Melodic minor
vcat([note.(freq) for freq=[C, D, Eb, F, G, A, B, 2C]]...)

# ╔═╡ c377016e-121a-4c9a-99c7-c81119576e52
# (w w s) (s w w) Myxolydian b6
vcat([note.(freq) for freq=[C, D, E, F, G, Ab, Bb, 2C]]...)

# ╔═╡ 8b82955f-3456-4e7a-a238-8e8a8690a718
# (s w w) (w s w) Dorian b2
vcat([note.(freq) for freq=[C, Db, Eb, F, G, A, Bb, 2C]]...)

# ╔═╡ 913b0f4d-b5cd-40c6-8148-1a227128a384
md"These have fewer perfect fifths
but still have the perfect intervals of the tonic
and good melodic structure.
Perhaps more importantly the modes which are also tetrachord scales
are the most used modes, with lydian and locrian being harder to use as they lack
either the perfect fourth or fifth of the tonic"

# ╔═╡ 65751878-9c60-4104-81b8-e4d07f77700a
md"## 3-Limit Harmony
Since the important intervals in 3-limit are the the fifth,
and by octave the fourth,
these are the intervals that are harmonic.
This doesn't allow the construction of triad based chords,
which are properly part of 5-limit harmony which includes thirds.
Because of this 3-limit harmony is fairly limited.
There are fewer notes which are consonant, limiting harmonic motion
and the number of voices that can be used at once compared to 5-limit.
Harmony is constructed by stacking 4ths or 5ths.
With 4 notes stacked we get 8 options for chords:"

# ╔═╡ 09210adf-a9f7-4c3c-99fa-99e41dc96e6c
# Stacked fifths, brightest
sum(note.(freq) for freq in [C, G, 2*D, 2*A])/4

# ╔═╡ 2d8892d1-c82c-4ec7-99c5-aad3059ce4d5
# 1 3/2 9/4 3 (5 5 4) octave on the 5th
# Probably best thought of as an inversion of (5 4 4)
sum(note.(freq) for freq in [C, G, 2*D, 2*G])/4

# ╔═╡ 02011bda-c1a0-4c30-a670-63bc4125fb44
# 1 3/2 2 3 (5 4 5) power chord w 5
sum(note.(freq) for freq in [C, G, 2*C, 2*G])/4

# ╔═╡ 403ee651-c86d-4ad7-b13d-5c0042a52d81
# 1 3/2 2 8/3 (5 4 4) 5 in octave 4 on top, most standard chord
sum(note.(freq) for freq in [C, G, 2*C, 2*F])/4

# ╔═╡ 55d4a2ed-4e28-43c2-b7ac-142d2c49f78a
# 1 4/3 2 3 (4 5 5) 4 in octave 5 on top, inverted (5 4 4) they have the same notes
sum(note.(freq) for freq in [C, F, 2*C, 2*G])/4

# ╔═╡ 53064534-4623-44a5-91d0-38f78b1092dd
# 1 4/3 2 8/3 (4 5 4) power chord w 4
sum(note.(freq) for freq in [C, F, 2*C, 2*F])/4

# ╔═╡ d307813b-9f62-4dc5-bc62-c0bdb07d4974
# 1 4/3 16/9 8/3 (4 4 5) octave on 4
# Probably best thought of as an inversion of (4 5 5)
sum(note.(freq) for freq in [C, F, Bb, 2*F])/4

# ╔═╡ 8921e867-7a01-4a2c-8704-a3469a4739af
# stacked 4ths
sum(note.(freq) for freq in [C, F, Bb, Eb])/4

# ╔═╡ da1614c8-08e6-499f-b97a-41da62e67fd2
md"We get stacked 5ths, power chords, balanced chords, and stacked 4ths,
not including the inversions.
Dropping powerchords as a simplification
we chose between 3 different chord qualities
for each chord:
the bright stacked 5ths,
the balanced chords with 4 and 5
and the dark stacked 4ths.
The harmony can be simplified with power chords,
and the balanced chords have inversions to help smooth root motion."

# ╔═╡ 1d078418-f252-403b-8205-dab834a2536a
# Stacked fifths
sum(note.(freq) for freq in [C, G, 2*D, 2*A])/4

# ╔═╡ b9eeff90-d4f2-4d7d-bf0f-7387922e1572
# balanced chord
sum(note.(freq) for freq in [C, G, 2*C, 2*F])/4

# ╔═╡ a13cfc17-3c9d-408d-a672-34ca1a28466d
# stacked 4ths
sum(note.(freq) for freq in [C, F, Bb, Eb])/4

# ╔═╡ dd3d10ca-8a70-417a-95cc-2398178403b1
md"## Building 3-limit chords on the C major scale"

# ╔═╡ 9158df86-039c-4497-90e9-cf3b1ad753d2
# I chord
sum(note.(freq) for freq in [C, F, 2*C, 2*G])/4

# ╔═╡ e1ca3cb4-f933-4895-9195-16f82a0cf8c8
# II chord
sum(note.(freq) for freq in [D, A, 2*D, 2*G])/4

# ╔═╡ 7f59447f-bfca-4d82-83d4-c9ffca771931
# III chord
sum(note.(freq) for freq in [E, A, 2*E, 2*B])/4

# ╔═╡ 79c5e37e-95d4-43d2-9972-ff69be40d97a
# IV chord
sum(note.(freq) for freq in [F, 2*C, 2*G, 2*D])/4

# ╔═╡ 2d5be56b-7f23-4a11-b29b-75559bf02af8
# V chord
sum(note.(freq) for freq in [G, 2*C, 2*G, 2*D])/4

# ╔═╡ 780a0596-9020-4195-89e1-9035c5d1ee43
# VI chord
sum(note.(freq) for freq in [A, E, 2*A, 2*D])/4

# ╔═╡ 6bfe1534-4844-4ec1-aef4-1e56b2667228
# VII chord
sum(note.(freq) for freq in [B, E, 2*A, 2*D])/4

# ╔═╡ Cell order:
# ╟─f3cf3e66-b414-11eb-129f-1f82995a6e8e
# ╠═c21d05c1-bd10-46cc-bc5a-d737d047131f
# ╠═99422a59-ffe4-4dc0-bb80-2245d41aaa74
# ╠═21ad163c-9031-4ebb-8dd2-a1a297f97456
# ╠═5dedb960-1524-475b-b870-61a8254c7993
# ╠═e0aff7b7-a355-4138-87cd-d5113ee82623
# ╠═752a031e-7c58-4af6-a2ab-965a1e43760e
# ╠═8882303c-4ae7-44a5-8d38-8c4e73f15892
# ╠═87212fe7-ac94-4173-b3b6-a9afe58783ea
# ╠═61482b04-b6fb-495a-94ae-92a84317f6f5
# ╠═799e0825-ac5c-46e5-a34a-685a5382cf63
# ╟─69e54625-9e7a-4a62-995d-ff4550e9167b
# ╠═61f66f37-1568-4fb6-b0b0-ae6d13110c73
# ╠═20b4c50b-39f8-494e-be2b-d9f9f81fa8e5
# ╠═4a6d05fb-341a-4487-9685-d6092dea902c
# ╠═28fe6d6b-bbab-4cde-b437-001f7894a2f0
# ╠═1619d9c4-d151-4060-9172-954500935545
# ╠═fe4516c3-2008-492f-8563-3daa92470175
# ╠═9a19129d-3b2a-4a59-aa72-0f8f6a349e53
# ╠═cf4fe547-f2e1-4e2f-8e52-168cce001061
# ╟─876750d7-d1c2-44d4-a367-984d060870c4
# ╠═bbdace00-0b8e-4963-af37-528b2a4aaafc
# ╠═0ea9acfe-4045-4804-bc78-c802cf0f5577
# ╠═834e0df6-c976-4c22-b1c4-95e9c8d3cade
# ╠═a83525a3-1228-4d50-8f85-df63ee11552b
# ╠═4708c80b-3166-4c21-992a-8d07ceb52bf2
# ╠═ee828da7-05f1-4fc2-9db7-589a9c1b735d
# ╠═83223d7d-fd40-4043-ae12-77b501fe1136
# ╠═b1d1a608-7474-4ee4-8b75-1459a848b188
# ╠═8c45ec80-a4dc-4ebd-a296-8739a1eb86ff
# ╠═b6f61f04-f944-4030-91f3-f75e15dc7fc6
# ╠═52782ffe-02e8-4dd1-886a-97e8a3615560
# ╠═d2a2ebb6-3f2a-4165-a56a-d8a2a0cd5312
# ╟─90035d61-3dba-480e-8b4f-200b65b8f3f7
# ╟─fc024776-6567-481b-bcce-c87d10460243
# ╠═e8f1a177-9a0e-48a0-9fd7-8c00defd286a
# ╟─ce64e368-01c3-49d3-ae11-ac889edfcff0
# ╠═ae376c87-f212-4e19-8c2d-af79875ef79f
# ╠═f8ff6af6-10f2-4f13-a5f4-b0e1a94ca95d
# ╠═c377016e-121a-4c9a-99c7-c81119576e52
# ╠═8b82955f-3456-4e7a-a238-8e8a8690a718
# ╟─913b0f4d-b5cd-40c6-8148-1a227128a384
# ╟─65751878-9c60-4104-81b8-e4d07f77700a
# ╠═09210adf-a9f7-4c3c-99fa-99e41dc96e6c
# ╠═2d8892d1-c82c-4ec7-99c5-aad3059ce4d5
# ╠═02011bda-c1a0-4c30-a670-63bc4125fb44
# ╠═403ee651-c86d-4ad7-b13d-5c0042a52d81
# ╠═55d4a2ed-4e28-43c2-b7ac-142d2c49f78a
# ╠═53064534-4623-44a5-91d0-38f78b1092dd
# ╠═d307813b-9f62-4dc5-bc62-c0bdb07d4974
# ╠═8921e867-7a01-4a2c-8704-a3469a4739af
# ╟─da1614c8-08e6-499f-b97a-41da62e67fd2
# ╠═1d078418-f252-403b-8205-dab834a2536a
# ╠═b9eeff90-d4f2-4d7d-bf0f-7387922e1572
# ╠═a13cfc17-3c9d-408d-a672-34ca1a28466d
# ╟─dd3d10ca-8a70-417a-95cc-2398178403b1
# ╠═9158df86-039c-4497-90e9-cf3b1ad753d2
# ╠═e1ca3cb4-f933-4895-9195-16f82a0cf8c8
# ╠═7f59447f-bfca-4d82-83d4-c9ffca771931
# ╠═79c5e37e-95d4-43d2-9972-ff69be40d97a
# ╠═2d5be56b-7f23-4a11-b29b-75559bf02af8
# ╠═780a0596-9020-4195-89e1-9035c5d1ee43
# ╠═6bfe1534-4844-4ec1-aef4-1e56b2667228

max_stars_repo_name: jnha/music

max_issues_repo_name: jnha/music

max_forks_repo_name: jnha/music


text:
# ---
# title: 2. Add Two Numbers
# id: problem2
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Linked List, Math
# link: <https://leetcode.com/problems/add-two-numbers/description/>
# hidden: true
# ---
#
# You are given two **non-empty** linked lists representing two non-negative
# integers. The digits are stored in **reverse order** , and each of their nodes
# contains a single digit. Add the two numbers and return the sum as a linked
# list.
#
# You may assume the two numbers do not contain any leading zero, except the
# number 0 itself.
#
#
#
# **Example 1:**
#
# ![](https://assets.leetcode.com/uploads/2020/10/02/addtwonumber1.jpg)
#
#
#
#     Input: l1 = [2,4,3], l2 = [5,6,4]
#     Output: [7,0,8]
#     Explanation: 342 + 465 = 807.
#
#
# **Example 2:**
#
#
#
#     Input: l1 = [0], l2 = [0]
#     Output: [0]
#
#
# **Example 3:**
#
#
#
#     Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
#     Output: [8,9,9,9,0,0,0,1]
#
#
#
#
# **Constraints:**
#
#   * The number of nodes in each linked list is in the range `[1, 100]`.
#   * `0 <= Node.val <= 9`
#   * It is guaranteed that the list represents a number that does not have leading zeros.
#
#
## @lc code=start
using LeetCode

function add_two_numbers(l1::ListNode, l2::ListNode)::ListNode
    carry = 0
    fake_head = cur = ListNode()

    while !isnothing(l1) || !isnothing(l2) || !iszero(carry)
        v1, v2 = 0, 0

        if !isnothing(l1)
            v1 = val(l1)
            l1 = next(l1)
        end

        if !isnothing(l2)
            v2 = val(l2)
            l2 = next(l2)
        end

        carry, v = divrem(v1 + v2 + carry, 10)
        next!(cur, ListNode(v))
        cur = next(cur)
        val!(cur, v)
    end
    return next(fake_head)
end
## @lc code=end


text:
##########################################################################################
# Node inspection on mouse hover
##########################################################################################

function Makie.show_data(inspector::DataInspector,
    plot::OSMPlot{<:Tuple{<:OSMGraph}}, idx, source::Scatter)
    osm = plot.osm[]
    a = inspector.plot.attributes
    scene = Makie.parent_scene(plot)

    pos = source[1][][idx]
    proj_pos = Makie.shift_project(scene, plot, to_ndim(Point3f, pos, 0))
    Makie.update_tooltip_alignment!(inspector, proj_pos)

    node = osm.nodes[osm.index_to_node[idx]]
    a._display_text[] = node2string(node)
    ms = source.markersize[][idx]
    a._bbox2D[] = Rect2f(proj_pos .- 0.5 .* ms .- Vec2f(5), Vec2f(ms) .+ Vec2f(10))
    a._px_bbox_visible[] = true
    a._bbox_visible[] = false
    a._visible[] = true
    a.range = 1
    a.textsize = 13

    return true
end

function node2string(node::N) where {N<:LightOSM.Node}
    nodestring = """
        ▶ $(nameof(N)) $(node.id)
        Location:
            Lon: $(node.location.lon)
            Lat: $(node.location.lat)
            Alt: $(node.location.alt)
        Tags:
        """
    for (key, val) in pairs(node.tags)
        nodestring *= "    $(key): $(val)\n"
    end

    return nodestring
end

# TODO copy current node ID on click

##########################################################################################
# Edge inspection on mouse hover
##########################################################################################

function Makie.show_data(inspector::DataInspector,
    plot::OSMPlot{<:Tuple{<:OSMGraph}}, idx, source::LineSegments)
    osm = plot.osm[]
    a = inspector.plot.attributes
    scene = Makie.parent_scene(plot)

    p0, p1 = source[1][][idx-1:idx]
    origin, dir = Makie.view_ray(scene)
    pos = Makie.closest_point_on_line(p0, p1, origin, dir)
    lw = source.linewidth[] isa Vector ? source.linewidth[][idx] : source.linewidth[]

    proj_pos = Makie.shift_project(scene, plot, to_ndim(Point3f, pos, 0))
    Makie.update_tooltip_alignment!(inspector, proj_pos)

    # Without plot.index_to_way:
    # i1, i2 = plot.sorted_edges[][idx÷2]
    # n1, n2 = osm.index_to_node[i1], osm.index_to_node[i2]
    # way = osm.edge_to_highway[[n1, n2]]

    # With plot.index_to_way:
    way = plot.index_to_way[][idx÷2]

    a._display_text[] = edge2string(way)
    a._bbox2D[] = Rect2f(proj_pos .- 0.5 .* lw .- Vec2f(5), Vec2f(lw) .+ Vec2f(10))
    a._px_bbox_visible[] = true
    a._bbox_visible[] = false
    a._visible[] = true
    a.range = 1
    a.textsize = 13

    return true
end

function edge2string(edge::E) where {E<:LightOSM.Way}
    edgestring = """
        ▶ $(nameof(E)) $(edge.id)
        Name: $(get(edge.tags, "name", "unnamed"))
        Tags:
        """
    for (key, val) in pairs(sort(edge.tags))
        key == "name" && continue
        edgestring *= "    $(key): $(val)\n"
    end

    return edgestring
end


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module TestLDLT

using Test, LinearAlgebra, Random

Random.seed!(123)

@testset "Factorization conversions of LDLT" begin
    S = SymTridiagonal(randn(5), randn(4))
    F = ldlt(S)
    @test Factorization{eltype(S)}(F) === F
    @test Array(Factorization{complex(eltype(S))}(F)) ≈ Array(ldlt(complex(S)))
    @test eltype(Factorization{complex(eltype(S))}) == complex(eltype(S))
end

@testset "REPL printing of LDLT" begin
    S = SymTridiagonal(randn(5), randn(4))
    F = ldlt(S)
    ldltstring = sprint((t, s) -> show(t, "text/plain", s), F)
    lstring = sprint((t, s) -> show(t, "text/plain", s), F.L)
    dstring = sprint((t, s) -> show(t, "text/plain", s), F.D)
    @test ldltstring == "$(summary(F))\nL factor:\n$lstring\nD factor:\n$dstring"
end

end # module TestLDLT

max_stars_repo_name: TimoLarson/julia

max_issues_repo_name: TimoLarson/julia

max_forks_repo_name: TimoLarson/julia


text:
"""
Handles a single request.
Invokes the process that would handle the CGI request, monitors it.
Reads inputs and channels them to the running process.
Reads outputs from the process and channels them to the connection.
"""
mutable struct ServerRequest
    id::UInt16                          # request id
    state::UInt8                        # 1: init, 2: run, 0: stop
    onclose::Function                   # onclose function to cleanup and close connection if keepconn is false
    in::Channel{FCGIRecord}             # in message channel
    out::Channel{FCGIRecord}            # out message channel (of the connection that originated this request)
    plumbing::Plumbing                  # plumbing required to communicate and monitor processes
    runner::Runner                      # runner task
    processor::Union{Task,Nothing}      # task to process messages for this request
    procmon::Union{Task,Nothing}        # process monitor
    inputmon::Union{Task,Nothing}       # input monitor
    outputmon::Union{Task,Nothing}      # output monitor
end
function ServerRequest(id::UInt16, onclose::Function, out::Channel{FCGIRecord})
    @debug("starting request", id)
    req = ServerRequest(id, 0x1, onclose, Channel{FCGIRecord}(128), out, Plumbing(), FCGI_RUNNER(), nothing, nothing, nothing, nothing)
    req.processor = @async process(req)
    req
end
function readparams(req::ServerRequest)
    params = Dict{String,String}()

    # accept params
    while req.state === 0x1
        @debug("readparams: waiting to take from req.in")
        rec = take!(req.in)
        @debug("readparams: got record", type=reqtypetostring(rec.header.type))
        if rec.header.type === FCGIHeaderType.ABORT_REQUEST
            req.state = 0x0
        elseif rec.header.type === FCGIHeaderType.PARAMS
            if isempty(rec.content)
                @debug("readparams: reached end of params")
                # empty params request indicates end of params
                req.state = 0x2
            else
                @debug("readparams: content", len=length(rec.content))
                for nv in FCGIParams(rec.content).nvpairs
                    params[nv.name] = nv.value
                end
            end
        else
            # ignore (but warn) any unexpected messages for this request id
            @warn("unexpected message type", type=rec.header.type)
        end
    end
    params
end
function streamstdin(req::ServerRequest)
    inp = req.plumbing.inp
    @debug("monitorinputs: reading stdin")
    try
        stdinclosed = false
        while !stdinclosed
            rec = take!(req.in)
            if rec.header.type === FCGIHeaderType.ABORT_REQUEST
                killproc(req.runner)
                req.state = 0x0
                stdinclosed = true
            elseif rec.header.type === FCGIHeaderType.STDIN
                if isempty(rec.content)
                    @debug("streamstdin: reached end of streamstdin")
                    close(inp)
                    stdinclosed = true
                else
                    @debug("streamstdin: content", len=length(rec.content))
                    write(Base.pipe_writer(inp), rec.content)
                end
            else
                # ignore (but warn) any unexpected messages for this request id
                @warn("unexpected message type", type=rec.header.type)
            end
        end
    catch ex
        if !isa(ex, InvalidStateException)
            @error("exception in streamstdin", ex)
            rethrow(ex)
        else
            @debug("exiting streamstdin: request closed")
        end
    end
end
function monitorabort(req::ServerRequest)
    @debug("monitorinputs: checking abort")
    try
        while req.state !== 0x0
            rec = take!(req.in)
            if rec.header.type === FCGIHeaderType.ABORT_REQUEST
                killproc(req.runner)
                req.state = 0x0
            else
                # ignore (but warn) any unexpected messages for this request id
                @warn("unexpected message type", type=rec.header.type)
            end
        end
    catch ex
        if !isa(ex, InvalidStateException)
            @error("exception in monitorabort", ex)
            rethrow(ex)
        else
            @debug("exiting monitorabort: request closed")
        end
    end
end
function monitorinputs(req::ServerRequest)
    streamstdin(req)
    (req.state === 0x0) || monitorabort(req)   # monitor ABORT_REQUEST if not already aborted
    nothing
end

function monitoroutput(req::ServerRequest, pipe::Base.PipeEndpoint, type::UInt8)
    sent = false
    buffpipe = BufferedOutput() do bytes
        @debug("sending output", type=reqtypetostring(type), nbytes=length(bytes))
        put!(req.out, FCGIRecord(type, req.id, bytes))
        sent = true
    end
    bytes = readavailable(pipe)
    while !isempty(bytes)
        write(buffpipe, bytes)
        bytes = readavailable(pipe)
    end
    flush(buffpipe)
    close(buffpipe)
    if sent
        # if we ever sent something on a stream, we should send an end marker for it
        @debug("sending end of output", type=reqtypetostring(type))
        put!(req.out, FCGIRecord(type, req.id, UInt8[]))
    end
    @debug("finished monitoroutput", type=reqtypetostring(type))
    nothing
end
function monitoroutputs(req::ServerRequest)
    @sync begin
        @async monitoroutput(req, Base.pipe_reader(req.plumbing.out), FCGIHeaderType.STDOUT)
        @async monitoroutput(req, Base.pipe_reader(req.plumbing.err), FCGIHeaderType.STDERR)
    end
end
function getcommand(params::Dict{String,String})
    get(params, "SCRIPT_FILENAME") do
        script_name = strip(params["SCRIPT_NAME"])
        # strip off leading `/` to ensure we look into scripts within document_root
        while startswith(script_name, '/')
            script_name = script_name[2:end]
        end
        joinpath(params["DOCUMENT_ROOT"], script_name)
    end
end
function close(req::ServerRequest, exitcode::Integer)
    @debug("closing request", id=req.id, state=req.state, exitcode)
    reqcomplete = FCGIEndRequest(UInt32(exitcode), FCGIEndRequestProtocolStatus.REQUEST_COMPLETE)
    put!(req.out, FCGIRecord(FCGIHeaderType.END_REQUEST, req.id, reqcomplete))
    close(req)
    nothing
end
function close(req::ServerRequest)
    close(req.plumbing)
    close(req.in)
    @debug("calling onclose")
    (req.onclose)()
    nothing
end
function process(req::ServerRequest)
    params = readparams(req)
    @info("processing", SCRIPT_FILENAME=get(params, "SCRIPT_FILENAME", ""), SCRIPT_NAME=get(params, "SCRIPT_NAME", ""))
    @debug("read request params", id=req.id, state=req.state, params)
    if req.state !== 0x2
        @warn("abandoning request", id=req.id)
        return close(req)
    end

    exitcode, errmsg = launchproc(req.runner, req.plumbing, params)
    @debug("launched process", exitcode, errmsg)
    if exitcode == 0
        try
            @sync begin
                # process was launched successfully
                req.procmon = @async begin
                    exitcode = waitproc(req.runner)
                    @debug("process terminated", exitcode)
                    # close the input ends of the stdio streams
                    close(req.plumbing; inputendsonly=true)
                    close(req.in)
                end
                req.inputmon = @async monitorinputs(req) # stream inputs
                req.outputmon = @async monitoroutputs(req) # stream stdout/stderr
            end
        catch ex
            @warn("process exception", ex, params)
            exitcode = 500
        end
    end
    close(req, exitcode)
end


text:
using Printf

function main()
    xy_or_r = 1          # 1:x,y 2:r,t
    xnum = 20           #       2:rnum
    ynum = 20            #       2:tnum
    znum = 20            # z方向に伸ばすだけ（準2次元）
    lenx = 0.1          #       2:inr
    leny = 0.1          #       2:outr
    lenz = 0.1          #       2:outr
    st_ang  = -1/2*pi       # 2:angle
    en_ang  = -3/2*pi          # 2:angle

    outdir = "grid"
    make_dir(outdir)
    result = "result"
    make_dir(result)
    result = "post_result"
    make_dir(result)
    nodes, xnum_max, ynum_max, znum_max= mk_gird(xnum,ynum,znum,lenx,leny,lenz,xy_or_r,st_ang,en_ang,outdir)
    vecA(nodes,xnum_max,ynum_max,znum_max,outdir)
end

function mk_gird(xnum,ynum,znum,lenx,leny,lenz,xy_or_r,st_ang,en_ang,outdir)
    """
    nodes[i,j,k]
    i   : x,r方向の番号
    j   : y,theta方向の番号
    k=1 : 点のx座標
    k=2 : 点のy座標

    nodes[1,:]      : x方向境界
    nodes[:,1]      : y方向境界
    nodes[xnum+2,:] : x方向境界
    nodes[:,ynum+2] : y方向境界
    """
    xnum_max = xnum+1+2
    ynum_max = ynum+1+2
    znum_max = znum+1+2
    nodes = zeros(xnum_max, ynum_max, znum_max,3)
    if xy_or_r == 1
        for i in 2:xnum_max-1
            for j in 2:ynum_max-1
                for k in 2:znum_max-1
                    x = lenx/(xnum)*(i-2)
                    y = leny/(ynum)*(j-2)
                    z = lenz/(znum)*(k-2)
                    nodes[i,j,k,1] = x
                    nodes[i,j,k,2] = y
                    nodes[i,j,k,3] = z
                end
            end
        end
    elseif xy_or_r == 2
        for i in 2:xnum_max-1
            for j in 2:ynum_max-1
                for k in 2:znum_max-1
                    r = lenx + (leny-lenx)/ynum*(j-2)
                    theta = st_ang - (st_ang-en_ang)/xnum*(i-2)
                    x = r * cos(theta)
                    y = r * sin(theta)
                    z = lenz/(znum)*(k-2)
                    nodes[i,j,k,1]=x
                    nodes[i,j,k,2]=y
                    nodes[i,j,k,3] = z
                end
            end
        end
    end

    #=
    仮想セルの作成：現在あるセル境界線を延長して作成
    ベクトルで考えれば下記のような計算になる．たぶん
    また、[1,1]等の角にはダミー値が入っている.
    =#
    for j in 1:ynum_max
        for k in 1:znum_max
            for l in 1:3
                nodes[1,j,k,l]        =  2.0*nodes[2,j,k,l] - nodes[3,j,k,l]
                nodes[xnum_max,j,k,l] =  2.0*nodes[xnum_max-1,j,k,l] - nodes[xnum_max-2,j,k,l]
            end
        end
    end
    for k in 1:znum_max
        for i in 1:xnum_max
            for l in 1:3
                nodes[i,1,k,l]        =  2.0*nodes[i,2,k,l] - nodes[i,3,k,l]
                nodes[i,ynum_max,k,l] =  2.0*nodes[i,ynum_max-1,k,l] - nodes[i,ynum_max-2,k,l]
            end
        end
    end
    for i in 1:xnum_max
        for j in 1:ynum_max
            for l in 1:3
                nodes[i,j,1,l]        =  2.0*nodes[i,j,2,l] - nodes[i,j,3,l]
                nodes[i,j,znum_max,l] =  2.0*nodes[i,j,znum_max-1,l] - nodes[i,j,znum_max-2,l]
            end
        end
    end

    fff=outdir*"/nodes"
    open(fff,"w") do f
        write(f,"nodes: xnum, ynum , x, y\n")
        for i in 1:xnum_max
            for j in 1:ynum_max
                for k in 1:znum_max
                    x = @sprintf("%8.8e", nodes[i,j,k,1])
                    y = @sprintf("%8.8e", nodes[i,j,k,2])
                    z = @sprintf("%8.8e", nodes[i,j,k,3])
                    write(f,string(i)*" "*string(j)*" "*string(k)*" "*x*" "*y*" "*z*"\n")
                end
            end
        end
    end
    println("write "*fff)

    # nodes_forvtk
    nodes_num = zeros(Int,xnum_max, ynum_max, znum_max)
    fff=outdir*"/nodes_forvtk"
    open(fff,"w") do f
        write(f,"nodes: xnum, ynum , x, y\n")
        l=1
        for i in 2:xnum_max-1
            for j in 2:ynum_max-1
                for k in 2:znum_max-1
                    x = @sprintf("%8.8e", nodes[i,j,k,1])
                    y = @sprintf("%8.8e", nodes[i,j,k,2])
                    z = @sprintf("%8.8e", nodes[i,j,k,3])
                    write(f,string(l)*" "*x*" "*y*" "*z*"\n")
                    nodes_num[i,j,k] = l
                    l = l+1
                end
            end
        end
    end
    println("write "*fff)

    fff=outdir*"/nodesnum"
    open(fff,"w") do f
        write(f,"nodesnum: xnum_max, ynum_max\n")
        write(f,string(xnum_max)*" "*string(ynum_max)*" "*string(znum_max)*"\n")
    end

    ### element ###
    fff=outdir*"/element_forvtk"
    open(fff,"w") do f
        write(f,"elements:cell_xnum, lup,rup,ldown,rdown \n")
        l=1
        for i in 2:xnum_max-2
            for j in 2:ynum_max-2
                for k in 2:znum_max-2
                    d1 = @sprintf("%1.0f", nodes_num[i,j,k])
                    d2 = @sprintf("%1.0f", nodes_num[i,j+1,k])
                    d3 = @sprintf("%1.0f", nodes_num[i+1,j+1,k])
                    d4 = @sprintf("%1.0f", nodes_num[i+1,j,k])
                    d5 = @sprintf("%1.0f", nodes_num[i,j,k+1])
                    d6 = @sprintf("%1.0f", nodes_num[i,j+1,k+1])
                    d7 = @sprintf("%1.0f", nodes_num[i+1,j+1,k+1])
                    d8 = @sprintf("%1.0f", nodes_num[i+1,j,k+1])
                    write(f,string(l)*" "*d1*" "*d2*" "*d3*" "*d4*" "*d5*" "*d6*" "*d7*" "*d8*"\n")
                    l = l+1
                end
            end
        end
    end
    println("write "*fff)

    return  nodes,xnum_max,ynum_max,znum_max
end

function vecA(nodes,xnum_max,ynum_max,znum_max,outdir)
    a = zeros(3)
    b = zeros(3)

    vecAx=zeros(xnum_max, ynum_max-1, znum_max-1, 3)
    for i in 1:xnum_max
        for j in 1:ynum_max-1
            for k in 1:znum_max-1
                # 3dim Ax=(a2b3-a3b2,a3b1-a1b3,a1b2-a2b1)
                # vec_a = (a1,a2,a3) = nodes[i,j+1,k+1] -nodes[i,j,k]
                # vec_b = (b1,b2,b3) = nodes[i,j,k+1] -nodes[i,j+1,k]
                for l in 1:3
                    a[l] = nodes[i,j+1,k+1,l]-nodes[i,j,k,l]
                    b[l] = nodes[i,j,k+1,l]-nodes[i,j+1,k,l]
                end
                vecAx[i,j,k,1] = 0.5*(a[2]*b[3]-a[3]*b[2])
                vecAx[i,j,k,2] = 0.5*(a[3]*b[1]-a[1]*b[3])
                vecAx[i,j,k,3] = 0.5*(a[1]*b[2]-a[2]*b[1])
            end
        end
    end

    vecAy=zeros(xnum_max-1, ynum_max, znum_max-1, 3)
    for i in 1:xnum_max-1
        for j in 1:ynum_max
            for k in 1:znum_max-1
                # 3dim Ay=(a2b3-a3b2,a3b1-a1b3,a1b2-a2b1)
                # vec_a = (a1,a2,a3) = nodes[i+1,j,k+1] -nodes[i,j,k]
                # vec_b = (b1,b2,b3) = nodes[i+1,j,k] -nodes[i,j,k+1]
                for l in 1:3
                    a[l] = nodes[i+1,j,k+1,l]-nodes[i,j,k,l]
                    b[l] = nodes[i+1,j,k,l]-nodes[i,j,k+1,l]
                end
                vecAy[i,j,k,1] = 0.5*(a[2]*b[3]-a[3]*b[2])
                vecAy[i,j,k,2] = 0.5*(a[3]*b[1]-a[1]*b[3])
                vecAy[i,j,k,3] = 0.5*(a[1]*b[2]-a[2]*b[1])
            end
        end
    end

    vecAz=zeros(xnum_max-1, ynum_max-1, znum_max, 3)
    for i in 1:xnum_max-1
        for j in 1:ynum_max-1
            for k in 1:znum_max
                # 3dim Az=(a2b3-a3b2,a3b1-a1b3,a1b2-a2b1)
                # vec_a = (a1,a2,a3) = nodes[i+1,j+1,k] -nodes[i,j,k]
                # vec_b = (b1,b2,b3) = nodes[i,j+1,k] -nodes[i+1,j,k]
                for l in 1:3
                    a[l] = nodes[i+1,j+1,k,l]-nodes[i,j,k,l]
                    b[l] = nodes[i,j+1,k,l]-nodes[i+1,j,k,l]
                end
                vecAz[i,j,k,1] = 0.5*(a[2]*b[3]-a[3]*b[2])
                vecAz[i,j,k,2] = 0.5*(a[3]*b[1]-a[1]*b[3])
                vecAz[i,j,k,3] = 0.5*(a[1]*b[2]-a[2]*b[1])
            end
        end
    end

    fff=outdir*"/vecAx"
    open(fff,"w") do f
        write(f,"vecAx: xnum, ynum, znum, x vec, y vec, z vec\n")
        for i in 1:xnum_max
            for j in 1:ynum_max-1
                for k in 1:znum_max-1
                    x = @sprintf("%8.8e", vecAx[i,j,k,1])
                    y = @sprintf("%8.8e", vecAx[i,j,k,2])
                    z = @sprintf("%8.8e", vecAx[i,j,k,3])
                    write(f,string(i)*" "*string(j)*" "*string(k)*" "*x*" "*y*" "*z*"\n")
                end
            end
        end
    end
    println("write "*fff)

    fff=outdir*"/vecAy"
    open(fff,"w") do f
        write(f,"vecAy: xnum, ynum, znum, x vec, y vec, z vec\n")
        for i in 1:xnum_max-1
            for j in 1:ynum_max
                for k in 1:znum_max-1
                    x = @sprintf("%8.8e", vecAy[i,j,k,1])
                    y = @sprintf("%8.8e", vecAy[i,j,k,2])
                    z = @sprintf("%8.8e", vecAy[i,j,k,3])
                    write(f,string(i)*" "*string(j)*" "*string(k)*" "*x*" "*y*" "*z*"\n")
                end
            end
        end
    end
    println("write "*fff)

    fff=outdir*"/vecAz"
    open(fff,"w") do f
        write(f,"vecAz: xnum, ynum, znum, x vec, y vec, z vec\n")
        for i in 1:xnum_max-1
            for j in 1:ynum_max-1
                for k in 1:znum_max
                    x = @sprintf("%8.8e", vecAz[i,j,k,1])
                    y = @sprintf("%8.8e", vecAz[i,j,k,2])
                    z = @sprintf("%8.8e", vecAz[i,j,k,3])
                    write(f,string(i)*" "*string(j)*" "*string(k)*" "*x*" "*y*" "*z*"\n")
                end
            end
        end
    end
    println("write "*fff)
end

function make_dir(outdir)
    k = 0
    try rm(outdir,recursive=true)
    catch
        mkdir(outdir)
        k = 1
    end

    if k == 0
        mkdir(outdir)
    end
end

# ---------------------------------
main()

max_stars_repo_name: hide-dog/test

max_issues_repo_name: hide-dog/test

max_forks_repo_name: hide-dog/test


text:
# This file is generated by autd_wrapper_generator (https://github.com/shinolab/autd-wrapper-generator)

function get_lib_ext()
    if Sys.iswindows()
        return ".dll"
    elseif Sys.isapple()
        return ".dylib"
    elseif Sys.islinux()
        return ".so"
    end
end

function get_lib_prefix()
    if Sys.iswindows()
        return ""
    else
        return "lib"
    end
end

@enum GainMode duty_phase_full = 1 phase_full = 2 phase_half = 4

const _autd3capi = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi" * get_lib_ext())
autd_create_controller(out) = ccall((:AUTDCreateController, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}},), out)

autd_open_controller(handle, p_link) = ccall((:AUTDOpenController, _autd3capi), Bool, (Ptr{Cvoid}, Ptr{Cvoid},), handle, p_link)

autd_add_device(handle, x, y, z, rz1, ry, rz2) = ccall((:AUTDAddDevice, _autd3capi), Int32, (Ptr{Cvoid}, Float64, Float64, Float64, Float64, Float64, Float64,), handle, x, y, z, rz1, ry, rz2)

autd_add_device_quaternion(handle, x, y, z, qw, qx, qy, qz) = ccall((:AUTDAddDeviceQuaternion, _autd3capi), Int32, (Ptr{Cvoid}, Float64, Float64, Float64, Float64, Float64, Float64, Float64,), handle, x, y, z, qw, qx, qy, qz)

autd_close_controller(handle) = ccall((:AUTDCloseController, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_clear(handle) = ccall((:AUTDClear, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_free_controller(handle) = ccall((:AUTDFreeController, _autd3capi), Cvoid, (Ptr{Cvoid},), handle)

autd_is_open(handle) = ccall((:AUTDIsOpen, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_get_output_enable(handle) = ccall((:AUTDGetOutputEnable, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_get_silent_mode(handle) = ccall((:AUTDGetSilentMode, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_get_force_fan(handle) = ccall((:AUTDGetForceFan, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_get_reads_fpga_info(handle) = ccall((:AUTDGetReadsFPGAInfo, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_get_output_balance(handle) = ccall((:AUTDGetOutputBalance, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_get_check_ack(handle) = ccall((:AUTDGetCheckAck, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_set_output_enable(handle, enable) = ccall((:AUTDSetOutputEnable, _autd3capi), Cvoid, (Ptr{Cvoid}, Bool,), handle, enable)

autd_set_silent_mode(handle, mode) = ccall((:AUTDSetSilentMode, _autd3capi), Cvoid, (Ptr{Cvoid}, Bool,), handle, mode)

autd_set_reads_fpga_info(handle, reads_fpga_info) = ccall((:AUTDSetReadsFPGAInfo, _autd3capi), Cvoid, (Ptr{Cvoid}, Bool,), handle, reads_fpga_info)

autd_set_output_balance(handle, output_balance) = ccall((:AUTDSetOutputBalance, _autd3capi), Cvoid, (Ptr{Cvoid}, Bool,), handle, output_balance)

autd_set_check_ack(handle, check_ack) = ccall((:AUTDSetCheckAck, _autd3capi), Cvoid, (Ptr{Cvoid}, Bool,), handle, check_ack)

autd_set_force_fan(handle, force) = ccall((:AUTDSetForceFan, _autd3capi), Cvoid, (Ptr{Cvoid}, Bool,), handle, force)

autd_get_wavelength(handle) = ccall((:AUTDGetWavelength, _autd3capi), Float64, (Ptr{Cvoid},), handle)

autd_get_attenuation(handle) = ccall((:AUTDGetAttenuation, _autd3capi), Float64, (Ptr{Cvoid},), handle)

autd_set_wavelength(handle, wavelength) = ccall((:AUTDSetWavelength, _autd3capi), Cvoid, (Ptr{Cvoid}, Float64,), handle, wavelength)

autd_set_attenuation(handle, attenuation) = ccall((:AUTDSetAttenuation, _autd3capi), Cvoid, (Ptr{Cvoid}, Float64,), handle, attenuation)

autd_get_fpga_info(handle, out) = ccall((:AUTDGetFPGAInfo, _autd3capi), Bool, (Ptr{Cvoid}, Ptr{UInt8},), handle, out)

autd_update_ctrl_flags(handle) = ccall((:AUTDUpdateCtrlFlags, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_set_delay_offset(handle, delay, offset) = ccall((:AUTDSetDelayOffset, _autd3capi), Int32, (Ptr{Cvoid}, Array{UInt8,1}, Array{UInt8,1},), handle, delay, offset)

autd_get_last_error(error) = ccall((:AUTDGetLastError, _autd3capi), Int32, (Ref{UInt8},), error)

autd_num_devices(handle) = ccall((:AUTDNumDevices, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_trans_position(handle, device_idx, local_trans_idx, x, y, z) = ccall((:AUTDTransPosition, _autd3capi), Cvoid, (Ptr{Cvoid}, Int32, Int32, Ptr{Float64}, Ptr{Float64}, Ptr{Float64},), handle, device_idx, local_trans_idx, x, y, z)

autd_device_x_direction(handle, device_idx, x, y, z) = ccall((:AUTDDeviceXDirection, _autd3capi), Cvoid, (Ptr{Cvoid}, Int32, Ptr{Float64}, Ptr{Float64}, Ptr{Float64},), handle, device_idx, x, y, z)

autd_device_y_direction(handle, device_idx, x, y, z) = ccall((:AUTDDeviceYDirection, _autd3capi), Cvoid, (Ptr{Cvoid}, Int32, Ptr{Float64}, Ptr{Float64}, Ptr{Float64},), handle, device_idx, x, y, z)

autd_device_z_direction(handle, device_idx, x, y, z) = ccall((:AUTDDeviceZDirection, _autd3capi), Cvoid, (Ptr{Cvoid}, Int32, Ptr{Float64}, Ptr{Float64}, Ptr{Float64},), handle, device_idx, x, y, z)

autd_get_firmware_info_list_pointer(handle, out) = ccall((:AUTDGetFirmwareInfoListPointer, _autd3capi), Int32, (Ptr{Cvoid}, Ref{Ptr{Cvoid}},), handle, out)

autd_get_firmware_info(p_firm_info_list, index, cpu_ver, fpga_ver) = ccall((:AUTDGetFirmwareInfo, _autd3capi), Cvoid, (Ptr{Cvoid}, Int32, Ref{UInt8}, Ref{UInt8},), p_firm_info_list, index, cpu_ver, fpga_ver)

autd_free_firmware_info_list_pointer(p_firm_info_list) = ccall((:AUTDFreeFirmwareInfoListPointer, _autd3capi), Cvoid, (Ptr{Cvoid},), p_firm_info_list)

autd_gain_null(gain) = ccall((:AUTDGainNull, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}},), gain)

autd_gain_grouped(gain, handle) = ccall((:AUTDGainGrouped, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}), gain, handle)

autd_gain_grouped_add(grouped_gain, device_id, gain) = ccall((:AUTDGainGroupedAdd, _autd3capi), Cvoid, (Ptr{Cvoid}, Int32, Ptr{Cvoid},), grouped_gain, device_id, gain)

autd_gain_focal_point(gain, x, y, z, duty) = ccall((:AUTDGainFocalPoint, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Float64, Float64, Float64, UInt8,), gain, x, y, z, duty)

autd_gain_bessel_beam(gain, x, y, z, n_x, n_y, n_z, theta_z, duty) = ccall((:AUTDGainBesselBeam, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Float64, Float64, Float64, Float64, Float64, Float64, Float64, UInt8,), gain, x, y, z, n_x, n_y, n_z, theta_z, duty)

autd_gain_plane_wave(gain, n_x, n_y, n_z, duty) = ccall((:AUTDGainPlaneWave, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Float64, Float64, Float64, UInt8,), gain, n_x, n_y, n_z, duty)

autd_gain_custom(gain, data, data_length) = ccall((:AUTDGainCustom, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Array{UInt16,1}, Int32,), gain, data, data_length)

autd_gain_transducer_test(gain, idx, duty, phase) = ccall((:AUTDGainTransducerTest, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Int32, UInt8, UInt8,), gain, idx, duty, phase)

autd_delete_gain(gain) = ccall((:AUTDDeleteGain, _autd3capi), Cvoid, (Ptr{Cvoid},), gain)

autd_modulation_static(mod, duty) = ccall((:AUTDModulationStatic, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, UInt8,), mod, duty)

autd_modulation_custom(mod, buf, size) = ccall((:AUTDModulationCustom, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Array{UInt8,1}, UInt32,), mod, buf, size)

autd_modulation_sine(mod, freq, amp, offset) = ccall((:AUTDModulationSine, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Int32, Float64, Float64,), mod, freq, amp, offset)

autd_modulation_sine_squared(mod, freq, amp, offset) = ccall((:AUTDModulationSineSquared, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Int32, Float64, Float64,), mod, freq, amp, offset)

autd_modulation_sine_legacy(mod, freq, amp, offset) = ccall((:AUTDModulationSineLegacy, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Float64, Float64, Float64,), mod, freq, amp, offset)

autd_modulation_square(mod, freq, low, high, duty) = ccall((:AUTDModulationSquare, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Int32, UInt8, UInt8, Float64,), mod, freq, low, high, duty)

autd_modulation_sampling_freq_div(mod) = ccall((:AUTDModulationSamplingFreqDiv, _autd3capi), UInt32, (Ptr{Cvoid},), mod)

autd_modulation_set_sampling_freq_div(mod, freq_div) = ccall((:AUTDModulationSetSamplingFreqDiv, _autd3capi), Cvoid, (Ptr{Cvoid}, UInt32), mod, freq_div)

autd_modulation_sampling_freq(mod) = ccall((:AUTDModulationSamplingFreq, _autd3capi), Float64, (Ptr{Cvoid},), mod)

autd_delete_modulation(mod) = ccall((:AUTDDeleteModulation, _autd3capi), Cvoid, (Ptr{Cvoid},), mod)

autd_sequence(out) = ccall((:AUTDSequence, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}},), out)

autd_gain_sequence(out, handle, gain_mode) = ccall((:AUTDGainSequence, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, UInt16,), out, handle, gain_mode)

autd_sequence_add_point(seq, x, y, z, duty) = ccall((:AUTDSequenceAddPoint, _autd3capi), Bool, (Ptr{Cvoid}, Float64, Float64, Float64, UInt8,), seq, x, y, z, duty)

autd_sequence_add_gain(seq, gain) = ccall((:AUTDSequenceAddGain, _autd3capi), Bool, (Ptr{Cvoid}, Ptr{Cvoid},), seq, gain)

autd_sequence_set_freq(seq, freq) = ccall((:AUTDSequenceSetFreq, _autd3capi), Float64, (Ptr{Cvoid}, Float64,), seq, freq)

autd_sequence_freq(seq) = ccall((:AUTDSequenceFreq, _autd3capi), Float64, (Ptr{Cvoid},), seq)

autd_sequence_period(seq) = ccall((:AUTDSequencePeriod, _autd3capi), UInt32, (Ptr{Cvoid},), seq)

autd_sequence_sampling_period(seq) = ccall((:AUTDSequenceSamplingPeriod, _autd3capi), UInt32, (Ptr{Cvoid},), seq)

autd_sequence_sampling_freq(seq) = ccall((:AUTDSequenceSamplingFreq, _autd3capi), Float64, (Ptr{Cvoid},), seq)

autd_sequence_sampling_freq_div(seq) = ccall((:AUTDSequenceSamplingFreqDiv, _autd3capi), UInt32, (Ptr{Cvoid},), seq)

autd_sequence_set_sampling_freq_div(seq, freq_div) = ccall((:AUTDSequenceSetSamplingFreqDiv, _autd3capi), Cvoid, (Ptr{Cvoid}, UInt32), seq, freq_div)

autd_delete_sequence(seq) = ccall((:AUTDDeleteSequence, _autd3capi), Cvoid, (Ptr{Cvoid},), seq)

autd_stop(handle) = ccall((:AUTDStop, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_pause(handle) = ccall((:AUTDPause, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_resume(handle) = ccall((:AUTDResume, _autd3capi), Int32, (Ptr{Cvoid},), handle)

autd_send_header(handle, header) = ccall((:AUTDSendHeader, _autd3capi), Int32, (Ptr{Cvoid}, Ptr{Cvoid},), handle, header)

autd_send_body(handle, body) = ccall((:AUTDSendBody, _autd3capi), Int32, (Ptr{Cvoid}, Ptr{Cvoid},), handle, body)

autd_send_header_body(handle, header, body) = ccall((:AUTDSendHeaderBody, _autd3capi), Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid},), handle, header, body)

autd_stm_controller(out, handle) = ccall((:AUTDSTMController, _autd3capi), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid},), out, handle)

autd_add_stm_gain(handle, gain) = ccall((:AUTDAddSTMGain, _autd3capi), Bool, (Ptr{Cvoid}, Ptr{Cvoid},), handle, gain)

autd_start_stm(handle, freq) = ccall((:AUTDStartSTM, _autd3capi), Bool, (Ptr{Cvoid}, Float64,), handle, freq)

autd_stop_stm(handle) = ccall((:AUTDStopSTM, _autd3capi), Bool, (Ptr{Cvoid},), handle)

autd_finish_stm(handle) = ccall((:AUTDFinishSTM, _autd3capi), Bool, (Ptr{Cvoid},), handle)

const _autd3capi_emulator_link = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-emulator-link" * get_lib_ext())
autd_link_emulator(out, port, cnt) = ccall((:AUTDLinkEmulator, _autd3capi_emulator_link), Cvoid, (Ref{Ptr{Cvoid}}, UInt16, Ptr{Cvoid},), out, port, cnt)

const _autd3capi_from_file_modulation = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-from-file-modulation" * get_lib_ext())
autd_modulation_raw_pcm(mod, filename, sampling_freq, mod_sampling_freq_div) = ccall((:AUTDModulationRawPCM, _autd3capi_from_file_modulation), Cvoid, (Ref{Ptr{Cvoid}}, Cstring, Float64, UInt16,), mod, filename, sampling_freq, mod_sampling_freq_div)

autd_modulation_wav(mod, filename, mod_sampling_freq_div) = ccall((:AUTDModulationWav, _autd3capi_from_file_modulation), Cvoid, (Ref{Ptr{Cvoid}}, Cstring, UInt16,), mod, filename, mod_sampling_freq_div)

const _autd3capi_holo_gain = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-holo-gain" * get_lib_ext())
autd_eigen_backend(out) = ccall((:AUTDEigen3Backend, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}},), out)

autd_delete_backend(backend) = ccall((:AUTDDeleteBackend, _autd3capi_holo_gain), Cvoid, (Ptr{Cvoid},), backend)

autd_gain_holo_sdp(gain, backend, points, amps, size, alpha, lambda, repeat, normalize) = ccall((:AUTDGainHoloSDP, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Float64, Float64, UInt64, Bool,), gain, backend, points, amps, size, alpha, lambda, repeat, normalize)

autd_gain_holo_evd(gain, backend, points, amps, size, gamma, normalize) = ccall((:AUTDGainHoloEVD, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Float64, Bool,), gain, backend, points, amps, size, gamma, normalize)

autd_gain_holo_naive(gain, backend, points, amps, size) = ccall((:AUTDGainHoloNaive, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32,), gain, backend, points, amps, size)

autd_gain_holo_gs(gain, backend, points, amps, size, repeat) = ccall((:AUTDGainHoloGS, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, UInt64,), gain, backend, points, amps, size, repeat)

autd_gain_holo_gspat(gain, backend, points, amps, size, repeat) = ccall((:AUTDGainHoloGSPAT, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, UInt64,), gain, backend, points, amps, size, repeat)

autd_gain_holo_lm(gain, backend, points, amps, size, eps_1, eps_2, tau, k_max, initial, initial_size) = ccall((:AUTDGainHoloLM, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Float64, Float64, Float64, UInt64, Array{Float64,1}, Int32,), gain, backend, points, amps, size, eps_1, eps_2, tau, k_max, initial, initial_size)

autd_gain_holo_gauss_newton(gain, backend, points, amps, size, eps_1, eps_2, k_max, initial, initial_size) = ccall((:AUTDGainHoloGaussNewton, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Float64, Float64, UInt64, Array{Float64,1}, Int32,), gain, backend, points, amps, size, eps_1, eps_2, k_max, initial, initial_size)

autd_gain_holo_gradient_descent(gain, backend, points, amps, size, eps, step, k_max, initial, initial_size) = ccall((:AUTDGainHoloGradientDescent, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Float64, Float64, UInt64, Array{Float64,1}, Int32,), gain, backend, points, amps, size, eps, step, k_max, initial, initial_size)

autd_gain_holo_apo(gain, backend, points, amps, size, eps, lambda, k_max) = ccall((:AUTDGainHoloAPO, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Float64, Float64, UInt64,), gain, backend, points, amps, size, eps, lambda, k_max)

autd_gain_holo_greedy(gain, backend, points, amps, size, phase_div) = ccall((:AUTDGainHoloGreedy, _autd3capi_holo_gain), Cvoid, (Ref{Ptr{Cvoid}}, Ptr{Cvoid}, Array{Float64,1}, Array{Float64,1}, Int32, Int32,), gain, backend, points, amps, size, phase_div)

const _autd3capi_remote_twincat_link = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-remote-twincat-link" * get_lib_ext())
autd_link_remote_twincat(out, remote_ip_addr, remote_ams_net_id, local_ams_net_id) = ccall((:AUTDLinkRemoteTwinCAT, _autd3capi_remote_twincat_link), Cvoid, (Ref{Ptr{Cvoid}}, Cstring, Cstring, Cstring,), out, remote_ip_addr, remote_ams_net_id, local_ams_net_id)

const _autd3capi_soem_link = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-soem-link" * get_lib_ext())
autd_get_adapter_pointer(out) = ccall((:AUTDGetAdapterPointer, _autd3capi_soem_link), Int32, (Ref{Ptr{Cvoid}},), out)

autd_get_adapter(p_adapter, index, desc, name) = ccall((:AUTDGetAdapter, _autd3capi_soem_link), Cvoid, (Ptr{Cvoid}, Int32, Ref{UInt8}, Ref{UInt8},), p_adapter, index, desc, name)

autd_free_adapter_pointer(p_adapter) = ccall((:AUTDFreeAdapterPointer, _autd3capi_soem_link), Cvoid, (Ptr{Cvoid},), p_adapter)

autd_link_soem(out, ifname, device_num, cycle_ticks) = ccall((:AUTDLinkSOEM, _autd3capi_soem_link), Cvoid, (Ref{Ptr{Cvoid}}, Cstring, Int32, UInt32,), out, ifname, device_num, cycle_ticks)

autd_set_soem_on_lost(link, callback) = ccall((:AUTDSetSOEMOnLost, _autd3capi_soem_link), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid},), link, callback)

const _autd3capi_twincat_link = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-twincat-link" * get_lib_ext())
autd_link_twincat(out) = ccall((:AUTDLinkTwinCAT, _autd3capi_twincat_link), Cvoid, (Ref{Ptr{Cvoid}},), out)

const _autd3capi_arrayfire_backend = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-arrayfire-backend" * get_lib_ext())
autd_array_fire_backend(out) = ccall((:AUTDArrayFireBackend, _autd3capi_arrayfire_backend), Cvoid, (Ref{Ptr{Cvoid}},), out)

const _autd3capi_blas_backend = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-blas-backend" * get_lib_ext())
autd_blas_backend(out) = ccall((:AUTDBLASBackend, _autd3capi_blas_backend), Cvoid, (Ref{Ptr{Cvoid}},), out)

const _autd3capi_cuda_backend = joinpath(@__DIR__, "bin", get_lib_prefix() * "autd3capi-cuda-backend" * get_lib_ext())
autd_cuda_backend(out) = ccall((:AUTDCUDABackend, _autd3capi_cuda_backend), Cvoid, (Ref{Ptr{Cvoid}},), out)


text:
# methods/inplace.jl
#
# Method-based access to tensor operations using inplace definitions.
tensorcopy!(A, IA, C, IC) = tensorcopy!(A, tuple(IA...), C, tuple(IC...))
tensoradd!(α, A, IA, β, C, IC) = tensoradd!(α, A, tuple(IA...), β, C, tuple(IC...))
tensortrace!(α, A, IA, β, C, IC) = tensortrace!(α, A, tuple(IA...), β, C, tuple(IC...))
tensorcontract!(α, A, IA, conjA, B, IB, conjB, β, C, IC) =
    tensorcontract!(α, A, tuple(IA...), conjA, B, tuple(IB...), conjB, β, C, tuple(IC...))
tensorproduct!(α, A, IA, B, IB, β, C, IC) = tensorproduct!(α, A, tuple(IA...), B, tuple(IB...), β, C, tuple(IC...))

"""
    tensorcopy!(A, IA, C, IC)

Copies `A` into `C` by permuting the dimensions according to the pattern specified by
`IA` and `IC`. Both iterables should contain the same elements in a different order.
The result of this method is equivalent to `permutedims!(C, A, p)` where `p` is the
permutation such that `IC=IA[p]`. The implementation of tensorcopy! is however more
efficient on average, especially if `Threads.nthreads() > 1`.
"""
tensorcopy!(A, IA::Tuple, C, IC::Tuple) = tensoradd!(1, A, IA, 0, C, IC)

"""
    tensoradd!(α, A, IA, β, C, IC)

Updates `C` to `β*C + α * tensorcopy(A,IA,IC)`, but without creating the temporary
permuted array.

See also: [`tensorcopy`](@ref)
"""
function tensoradd!(α, A, IA::Tuple, β, C, IC::Tuple)
    indCinA = add_indices(IA, IC)
    add!(α, A, :N, β, C, indCinA)
end

"""
    tensortrace!(α, A, IA, β, C, IC)

Updates `C` to `β*C + α tensortrace(A,IA,IC)`, but without creating the temporary
traced array.

See also: [`tensortrace`](@ref)
"""
function tensortrace!(α, A, IA::Tuple, β, C, IC::Tuple)
    indCinA, cindA1, cindA2 = trace_indices(IA, IC)
    trace!(α, A, :N, β, C, indCinA, cindA1, cindA2)
    return C
end

"""
    tensorcontract!(α, A, labelsA, conjA, B, labelsB, conjB, β, C, labelsC)

Replaces `C` with `β C + α A * B`, where some indices of array `A` are contracted with corresponding
indices in array `B` by assigning them identical labels in the iterables `labelsA` and `labelsB`.
The arguments `conjA` and `conjB` should be of type `Char` and indicate whether the data of
arrays `A` and `B`, respectively, need to be conjugated (value `'C'`) or not (value `'N'`).
Every label should appear exactly twice in the union of `labelsA`, `labelsB` and `labelsC`,
either in the intersection of `labelsA` and `labelsB` (for indices that need to be contracted)
or in the interaction of either `labelsA` or `labelsB` with `labelsC`, for indicating the order
in which the open indices should be match to the indices of the output array `C`.
"""
function tensorcontract!(α, A, IA::Tuple, conjA, B, IB::Tuple, conjB, β, C, IC::Tuple)

    conjA == 'N' || conjA == 'C' || throw(ArgumentError("Value of conjA should be 'N' or 'C' instead of $conjA"))
    conjB == 'N' || conjB == 'C' || throw(ArgumentError("Value of conjB should be 'N' or 'C' instead of $conjB"))
    CA = conjA == 'N' ? :N : :C
    CB = conjB == 'N' ? :N : :C

    oindA, cindA, oindB, cindB, indCinoAB = contract_indices(IA, IB, IC)
    contract!(α, A, CA, B, CB, β, C, oindA, cindA, oindB, cindB, indCinoAB)
    return C
end

"""
    tensorproduct!(α, A, labelsA, B, labelsB, β, C, labelsC)

Replaces C with `β C + α A * B` without any indices being contracted.
"""
function tensorproduct!(α, A, IA::Tuple, B, IB::Tuple, β, C, IC::Tuple)
    isempty(intersect(IA, IB)) || throw(LabelError("not a valid tensor product"))
    tensorcontract!(α, A, IA, 'N', B, IB, 'N', β, C, IC)
end


text:
using Test

@testset "config" begin
    include("config.jl")
end

@testset "fileio" begin
    include("fileio.jl")
end

@testset "json" begin
    include("json.jl")
end


text:
"""
    asdataframe(table) :: DataFrame

Robust table-to-`DataFrame` conversion.  Missing columns are filled
with `missing`s.

# Examples
```jldoctest
julia> using DataUtils: asdataframe

julia> asdataframe([(a=1, b=2), (a=3,)])
2×2 DataFrames.DataFrame
│ Row │ a     │ b       │
│     │ Int64 │ Int64⍰  │
├─────┼───────┼─────────┤
│ 1   │ 1     │ 2       │
│ 2   │ 3     │ missing │
```
"""
asdataframe(df::DataFrames.AbstractDataFrame) = df
function asdataframe(table::T) where {T}
    if (
        Base.IteratorEltype(T) isa Base.HasEltype && eltype(T) <: NamedTuple &&
        !(isconcretetype(eltype(T)) && Tables.istable(typeof(table)))
    )
        # In this case, `DataFrame` constructor does not work well.
        return _asdataframe(table)
    elseif Tables.istable(table)
        return DataFrame(table)
    elseif !(table isa AbstractArray)
        return asdataframe(collect(table))
    end
    return _asdataframe(table)
end

# Not sure if an iterable is stateless; so let's collect it first:
_asdataframe(itr) = _asdataframe(collect(itr)::AbstractArray)

_getvalue(x, name, default) =
    hasproperty(x, name) ? getproperty(x, name) : default
_getvalue(x::NamedTuple, name, default) = get(x, name, default)

function _asdataframe(table::AbstractArray)
    # Merge all column names of all rows:
    allnames = foldl(table; init=Symbol[]) do allnames, row
        newnames = setdiff(propertynames(row), allnames)
        append!(allnames, newnames)
    end

    # Create an empty DataFrame with known column names:
    df = DataFrame(fill(Union{}[], length(allnames)), allnames)

    # An iterable that yields named tuples with a fixed set of names:
    rows = let allnames = Tuple(allnames)
        Base.Generator(table) do row
            kvs = map(allnames) do name
                (name => _getvalue(row, name, missing))
            end
            return (; kvs...)
        end
    end

    # BangBang will appropriately widen column vectors:
    return append!!(df, rows)
end

function refineeltype(xs)
    if isconcretetype(Core.Compiler.typesubtract(Union{eltype(xs),Missing}, Missing))
        return xs
    else
        return identity.(xs)
    end
end

"""
    slimdataforvegalite(table) -> df

Remove columns that are not usable in vega-lite.  It also renames
column names with `.` and `-` to use `_` instead.

See also: <https://github.com/queryverse/VegaLite.jl/pull/195>

# Examples
```jldoctest
julia> using DataUtils

julia> slimdataforvegalite([(a=1, b=2, c=Ref(0)), (a=3,)])
2×2 DataFrames.DataFrame
│ Row │ a     │ b       │
│     │ Int64 │ Int64⍰  │
├─────┼───────┼─────────┤
│ 1   │ 1     │ 2       │
│ 2   │ 3     │ missing │
```
"""
function slimdataforvegalite(table)
    df = asdataframe(table)
    size(df, 1) == 0 && return df

    # To use `eltype(column)` below, refine `eltype` of all columns first:
    cols = map(refineeltype, eachcol(df))
    cnames = propertynames(df)

    idx = [
        i
        for (i, column) in enumerate(cols) if (
            eltype(column) <: Union{AbstractString,Missing,Nothing,Number,Symbol}
        )
    ]

    df = DataFrame(cols[idx], cnames[idx])

    rename!(df) do name
        str = String(name)
        str = replace(str, "." => "_")
        str = replace(str, "-" => "_")
        return Symbol(str)
    end
    return df
end


text:
# Compute the scaling factors for each measurement technique to ensure that
# analog signal is 99.9% below -1dBFS. Random gaussian noise is technically
# unbounded, so it's not useful to find a normalization level that will ensure
# we never clip, but we can at least find a reasonable level where any clipping
# should have a minimal impact.

"""
    percentilethresh(x, p)

Find the threshold where `p` percent of `x` will be below it.
"""
function percentilethresh(x, p)
    xs = sort(abs.(x))
    xs[ceil(Int, p/100*length(x))]
end

# expsweep and impulse are naturally limited, so no need to compute a scaling
# factor for them

using MeasureIR

rawsig(g::MeasureIR.GolaySequence) = [g.A; g.B]
rawsig(g::MeasureIR.IRMeasurement) = g.sig

data = Dict()
for f in [expsweep, golay, mls, rpms]
    fname = split(string(f),".")[2]
    m = f(2^24)
    thresh = percentilethresh(resample(rawsig(m), 8//1), 99.99)
    data[f] = thresh
    print(".")
end
println()

ref = db2amp(-1)
println("===================")
println("Impulse Gain: ", ref)
println("ExpSweep Gain: ", ref / data[expsweep])
println("Golay Gain: ", ref / data[golay])
println("MLS Gain: ", ref / data[mls])
println("RPMS Gain: ", ref / data[rpms])
println("===================")


text: # This file intentionally empty

max_forks_repo_name: MillironX/wphl-bioinformatics


text:
# Find Ω(t), dΩ(t), and computational stencils
# Alex Tam, 02/11/2021

"Data structure for an interior grid point"
struct GridPoint
    xInd::Int # Index of x-coordinate
    yInd::Int # Index of y-coordinate
    Ω::Bool # Boolean for whether grid point is inside Ω
    dΩ::Bool # Boolean for whether grid point is close to dΩ
    θxp::Float64 # Relative distance to plus stencil node (x)
    θyp::Float64 # Relative distance to plus stencil node (y)
    θxm::Float64 # Relative distance to minus stencil node (x)
    θym::Float64 # Relative distance to minus stencil node (y)
end

"Data structure for interface point"
struct InterfacePoint
    m::GridPoint # Grid point to negative side of interface
    p::GridPoint # Grid point to positive side of interface
end

"Classify and find stencils for interior grid points"
function find_domain(par, ϕ)
    D = Vector{GridPoint}() # Pre-allocate empty vector of interior grid points
    for i = 2:par.Nx-1 # Loop over interior grid points
        for j = 2:par.Ny-1 # Loop over interior grid points
            # Grid points inside Ω
            if ϕ[i,j] < 0
                if ϕ[i+1,j] >= 0
                    θxp = ϕ[i,j]/(ϕ[i,j] - ϕ[i+1,j]) # Linear interpolation to find interface
                else
                    θxp = 1.0
                end
                if ϕ[i-1,j] >= 0
                    θxm = ϕ[i,j]/(ϕ[i,j] - ϕ[i-1,j]) # Linear interpolation to find interface
                else
                    θxm = 1.0
                end
                if ϕ[i,j+1] >= 0
                    θyp = ϕ[i,j]/(ϕ[i,j] - ϕ[i,j+1]) # Linear interpolation to find interface
                else
                    θyp = 1.0
                end
                if ϕ[i,j-1] >= 0
                    θym = ϕ[i,j]/(ϕ[i,j] - ϕ[i,j-1]) # Linear interpolation to find interface
                else
                    θym = 1.0
                end
                if (θxp < par.θb) || (θxm < par.θb) || (θyp < par.θb) || (θym < par.θb) # If point is close to interface
                    push!(D, GridPoint(i, j, true, true, θxp, θyp, θxm, θym))
                else # If point is far enough from interface
                    push!(D, GridPoint(i, j, true, false, θxp, θyp, θxm, θym))
                end
            # Grid points outside Ω
            else
                if ϕ[i+1,j] < 0
                    θxp = ϕ[i,j]/(ϕ[i,j] - ϕ[i+1,j]) # Linear interpolation to find interface
                else
                    θxp = 1.0
                end
                if ϕ[i-1,j] < 0
                    θxm = ϕ[i,j]/(ϕ[i,j] - ϕ[i-1,j]) # Linear interpolation to find interface
                else
                    θxm = 1.0
                end
                if ϕ[i,j+1] < 0
                    θyp = ϕ[i,j]/(ϕ[i,j] - ϕ[i,j+1]) # Linear interpolation to find interface
                else
                    θyp = 1.0
                end
                if ϕ[i,j-1] < 0
                    θym = ϕ[i,j]/(ϕ[i,j] - ϕ[i,j-1]) # Linear interpolation to find interface
                else
                    θym = 1.0
                end
                if (θxp < par.θb) || (θxm < par.θb) || (θyp < par.θb) || (θym < par.θb) # If point is close to interface
                    push!(D, GridPoint(i, j, false, true, θxp, θyp, θxm, θym))
                else # If point is far enough from interface
                    push!(D, GridPoint(i, j, false, false, θxp, θyp, θxm, θym))
                end
            end
        end
    end
    return D
end

"Locate interface and associated grid points"
function find_interface(D, ϕ)
    dΩ = Vector{InterfacePoint}() # Pre-allocate interface
    for gp in D # Loop over all grid points
        if gp.Ω == true # Check points inside domain
            if ϕ[gp.xInd+1, gp.yInd] >= 0
                for p in D # Find grid point opposite interface
                    if (p.xInd == gp.xInd+1) && (p.yInd == gp.yInd)
                        push!(dΩ, InterfacePoint(gp, p))
                    end
                end
            end
            if ϕ[gp.xInd-1, gp.yInd] >= 0
                for m in D # Find grid point opposite interface
                    if (m.xInd == gp.xInd-1) && (m.yInd == gp.yInd)
                        push!(dΩ, InterfacePoint(m, gp))
                    end
                end
            end
            if ϕ[gp.xInd, gp.yInd+1] >= 0
                for p in D # Find grid point opposite interface
                    if (p.xInd == gp.xInd) && (p.yInd == gp.yInd+1)
                        push!(dΩ, InterfacePoint(gp, p))
                    end
                end
            end
            if ϕ[gp.xInd, gp.yInd-1] >= 0
                for m in D # Find grid point opposite interface
                    if (m.xInd == gp.xInd) && (m.yInd == gp.yInd-1)
                        push!(dΩ, InterfacePoint(m, gp))
                    end
                end
            end
        end
    end
    return dΩ
end


text:
export Node, CGPInd, get_genes, set_genes!, reset!, forward_connections, get_output_trace
import Base.copy, Base.String, Base.show, Base.summary
import Cambrian.print

"default function for nodes, will cause error if used as a function node"
function f_null(args...)::Nothing
    nothing
end

struct Node
    x::Int16
    y::Int16
    f::Function
    p::Array{Float64}
    active::Bool
end

struct CGPInd <: Cambrian.Individual
    n_in::Int16
    n_out::Int16
    n_parameters::Int16
    chromosome::Array{Float64}
    genes::Array{Float64}
    outputs::Array{Int16}
    nodes::Array{Node}
    buffer::AbstractArray
    fitness::Array{Float64}
end

function recur_active(active::BitArray, n_in::Integer, ind::Int16,
                      xs::Array{Int16}, ys::Array{Int16}, fs::Array{Int16},
                      two_arity::BitArray)::BitArray
    if ind > 0 && ~active[ind]
        active[ind] = true
        active = recur_active(active, n_in, xs[ind], xs, ys, fs, two_arity)
        if two_arity[fs[ind]]
            active = recur_active(active, n_in, ys[ind], xs, ys, fs, two_arity)
        end
    end
    active
end

function find_active(cfg::NamedTuple, genes::Array{Float64},
                     outputs::Array{Int16})::BitArray
    R = cfg.rows
    C = cfg.columns
    n = Int16(cfg.n_in)
    active = falses(R, C)
    xs = Int16.(genes[:, :, 1] .- n)
    ys = Int16.(genes[:, :, 2] .- n)
    fs = Int16.(genes[:, :, 3])
    for i in eachindex(outputs)
        active = recur_active(active, cfg.n_in, outputs[i] - n, xs, ys, fs,
                              cfg.two_arity)
    end
    active
end

function CGPInd(cfg::NamedTuple, chromosome::Array{Float64},
                genes::Array{Float64}, outputs::Array{Int16}; kwargs...)::CGPInd
    R = cfg.rows
    C = cfg.columns
    nodes = Array{Node}(undef, R * C + cfg.n_in)
    p = Float64[]
    for i in 1:cfg.n_in
        nodes[i] = Node(0, 0, f_null, p, false)
    end
    i = cfg.n_in
    active = find_active(cfg, genes, outputs)
    for y in 1:C
        for x in 1:R
            i += 1
            if cfg.n_parameters > 0
                p = genes[x, y, 4:end]
            end
            nodes[i] = Node(Int16(genes[x, y, 1]), Int16(genes[x, y, 2]),
                            cfg.functions[Int16(genes[x, y, 3])], p,
                            active[x, y])
        end
    end
    kwargs_dict = Dict(kwargs)
    # Use given input buffer or default to Array{Float64, 1} type
    if haskey(kwargs_dict, :buffer)
        buffer = kwargs_dict[:buffer]
    else
        buffer = zeros(R * C + cfg.n_in)
    end
    fitness = -Inf .* ones(cfg.d_fitness)
    CGPInd(cfg.n_in, cfg.n_out, cfg.n_parameters, chromosome, genes, outputs,
           nodes, buffer, fitness)
end

function CGPInd(cfg::NamedTuple, chromosome::Array{Float64}; kwargs...)::CGPInd
    R = cfg.rows
    C = cfg.columns
    P = cfg.n_parameters
    # chromosome: node genes, output genes
    genes = reshape(chromosome[1:(R*C*(3+P))], R, C, 3+P)
    # TODO: recurrency is ugly and slow
    maxs = collect(1:R:R*C)
    maxs = round.((R*C .- maxs) .* cfg.recur .+ maxs)
    maxs = min.(R*C + cfg.n_in, maxs .+ cfg.n_in)
    maxs = repeat(maxs, 1, R)'
    genes[:, :, 1] .*= maxs
    genes[:, :, 2] .*= maxs
    genes[:, :, 3] .*= length(cfg.functions)
    genes[:, :, 1:3] = Int16.(ceil.(genes[:, :, 1:3])) # ceil all genes except parameters that stay in [0,1]
    outputs = Int16.(ceil.(chromosome[(R*C*(3+P)+1):end] .* (R * C + cfg.n_in)))
    CGPInd(cfg, chromosome, genes, outputs; kwargs...)
end

function CGPInd(cfg::NamedTuple; kwargs...)::CGPInd
    chromosome = rand(cfg.rows * cfg.columns * (3 + cfg.n_parameters) + cfg.n_out)
    CGPInd(cfg, chromosome; kwargs...)
end

function CGPInd(cfg::NamedTuple, ind::String)::CGPInd
    dict = JSON.parse(ind)
    CGPInd(cfg, Array{Float64}(dict["chromosome"]))
end

function copy(n::Node)
    Node(n.x, n.y, n.f, n.active)
end

function copy(ind::CGPInd)
    buffer = zeros(length(ind.buffer))
    nodes = Array{Node}(undef, length(ind.nodes))
    for i in eachindex(ind.nodes)
        nodes[i] = copy(ind.nodes[i])
    end
    CGPInd(ind.n_in, ind.n_out, copy(ind.chromosome), copy(ind.genes),
           copy(ind.outputs), nodes, buffer, copy(ind.fitness))
end

function String(n::Node)
    JSON.json(Dict(:x=>n.x, :y=>n.y, :f=>string(n.f),  :p=>string(n.p),
              :active=>n.active))
end

function show(io::IO, n::Node)
    print(io, String(n))
end

function String(ind::CGPInd)
    JSON.json(Dict("chromosome"=>ind.chromosome, "fitness"=>ind.fitness,
                   "xs"=>ind.genes[:, :, 1][:], "ys"=>ind.genes[:, :, 2][:],
                   "fs"=>ind.genes[:, :, 3][:]))
end

function show(io::IO, ind::CGPInd)
    print(io, String(ind))
end

function get_active_nodes(ind::CGPInd)
    ind.nodes[[n.active for n in ind.nodes]]
end

function summary(io::IO, ind::CGPInd)
    print(io, string("CGPInd(", get_active_nodes(ind), ", ",
                     findall([n.active for n in ind.nodes]), ", ",
                     ind.outputs, " ,",
                     ind.fitness, ")"))
end

function interpret(i::CGPInd)
    x::AbstractArray->process(i, x)
end

function reset!(c::CGPInd)
    c.buffer .= 0.0
end

"""
    get_gene_indexes(ind::CGPInd, node_id::Integer)

Given an individual and the index of one of its nodes, return the indexes of the
chromosome used to encode this particular node.
"""
function get_gene_indexes(c::CGPInd, node_id::Integer)
    index_start = node_id - c.n_in
    step = length(c.nodes) - c.n_in
    index_end = (2 + c.n_parameters) * (length(c.nodes) - c.n_in) + node_id - c.n_in
    return index_start:step:index_end
end

"""
    get_genes(ind::CGPInd, node_id::Integer)::Array{Float64}

Given an individual and the index of one of its nodes, return the chromosome
used to encode this particular node.

Example:
    get_genes(ind, 42)
"""
function get_genes(c::CGPInd, node_id::Integer)::Array{Float64}
    if node_id > c.n_in
        return c.chromosome[get_gene_indexes(c, node_id)]
    else
        return zeros(3 + c.n_parameters)
    end
end

"""
    get_genes(c::CGPInd, nodes::Array{<:Integer})::Array{Float64}

Given an individual and an array of indexes of one of its nodes, return the
chromosomes used to encode these particular nodes.

Example:
    get_genes(ind, [7, 42])
"""
function get_genes(c::CGPInd, nodes::Array{<:Integer})::Array{Float64}
    if length(nodes) > 0
        return reduce(vcat, map(x->get_genes(c, x), nodes))
    else
        return Array{Float64}(0)
    end
end

"set the genes of node_id to genes"
function set_genes!(c::CGPInd, node_id::Integer, genes::Array{Float64})
    if node_id > c.n_in
        @assert length(genes) == 3 + c.n_parameters
        c.chromosome[get_gene_indexes(c, node_id)] = genes
    end
end

"a list for each node i of a list of all the nodes which have the node i as an input, and i"
function forward_connections(c::CGPInd)
    connections = [[i] for i in 1:length(c.nodes)]
    for ci in eachindex(c.nodes)
        conns = [c.nodes[ci].x, c.nodes[ci].y]
        for conn in conns
            if conn > 0
                push!(connections[conn], ci)
            end
        end
    end
    map(unique, connections)
end

"recursively walk back through inputs"
function recur_output_trace(c::CGPInd, ind::Int16, visited::Array{Int16})
    if ~(ind in visited)
        push!(visited, ind)
        if ind > c.n_in
            recur_output_trace(c, c.nodes[ind].x, visited)
            if CGPFunctions.arity[string(c.nodes[ind].f)] == 2
                recur_output_trace(c, c.nodes[ind].y, visited)
            end
        end
    end
    visited
end

"return a list of node indices which determine the output"
function get_output_trace(c::CGPInd, output_ind::Integer)
    recur_output_trace(c, c.outputs[output_ind], Array{Int16}(undef, 0))
end

"return a list of node indices which determine the output for multiple outputs"
function get_output_trace(c::CGPInd, outputs::Array{<:Integer})
    if length(outputs) > 0
        return unique(reduce(vcat, map(x->get_output_trace(c, x), outputs)))
    else
        return Array{Int16}(undef, 0)
    end
end

"return a list of node indices which determine the output for all outputs"
function get_output_trace(c::CGPInd)
    get_output_trace(c, collect(1:c.n_out))
end