text:
@testset "Test register initialisation" begin
    @test all(FullStateQuantumRegister{ComplexF64}(3, "000").state .=== convert(Array{ComplexF64, 1}, [1, 0, 0, 0, 0, 0, 0, 0]))
    @test all(FullStateQuantumRegister{ComplexF64}(3, "111").state .=== convert(Array{ComplexF64, 1}, [0, 0, 0, 0, 0, 0, 0, 1]))
    @test all(FullStateQuantumRegister{ComplexF16}(3, "101").state .=== convert(Array{ComplexF16, 1}, [0, 0, 0, 0, 0, 1, 0, 0]))
    @test begin
        qreg = FullStateQuantumRegister{Int}(3, "000")
        to_str(qreg) == "(1|000>)"
    end
    @test begin
        qreg = FullStateQuantumRegister{Int}(3, "000")
        qreg.state[end] = 1
        to_str(qreg) == "(1|000>) + (1|111>)"
    end
end

@testset "Test applying 1 qubit gates" begin
    @test begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        apply_1qubit(qreg, Gates.x, 3) == FullStateQuantumRegister{ComplexF64}(3, "001").state
    end
    @test begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        apply_1qubit!(qreg, Gates.x, 3)
        apply_1qubit(qreg, Gates.z, 3) == -FullStateQuantumRegister{ComplexF64}(3, "001").state
    end
    @test begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        apply_1qubit!(qreg, Gates.y, 3)
        apply_1qubit!(qreg, Gates.x, 2)
        apply_1qubit(qreg, Gates.y, 2) == FullStateQuantumRegister{ComplexF64}(3, "001").state
    end
    @testset begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        random_gate = rand(ComplexF64, (2, 2))
        for i = 1:3
            @test apply_1qubit_full(qreg, random_gate, i) == apply_1qubit(qreg, random_gate, i)
        end
    end
end

# Test by decomposing random matrices and recomposing
@test begin
    rmat = rand(ComplexF64, (4, 4))
    ops = decompose_2_qubit_gate(rmat)
    rrmat = nothing
    for op in ops
        mat = kron(op[2], op[1])
        if rrmat == nothing
            rrmat = mat
        else
            rrmat += mat
        end
    end
    rrmat ≈ rmat
end

@test kron(Gates.Id, Gates.x) == swap_2qubits(kron(Gates.x, Gates.Id))
@test begin
    A = rand(ComplexF64, (2, 2))
    B = rand(ComplexF64, (2, 2))
    kron(A, B) == swap_2qubits(kron(B, A))
end

@testset "Test some 2 qubit gates" begin
    @test begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        apply_1qubit!(qreg, Gates.x, 1)
        apply_2qubit!(qreg, Gates.cx, 2, 3)
        apply_2qubit!(qreg, Gates.cx, 1, 2)
        qreg ≈ FullStateQuantumRegister{ComplexF64}(3, "110")
    end

    @test begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        apply_1qubit!(qreg, Gates.h, 1)
        apply_2qubit_full(qreg, Gates.cy, 1, 2) ≈ apply_2qubit(qreg, Gates.cy, 1, 2)
    end
end

@testset begin
    @testset begin
        qreg = FullStateQuantumRegister{ComplexF64}(3, "000")
        apply_1qubit!(qreg, Gates.h, 1)
        apply_2qubit!(qreg, Gates.cx, 1, 2)
        apply_2qubit!(qreg, Gates.cx, 1, 3)
        @test measure_probs(qreg) ≈ [0.5, 0., 0., 0., 0., 0., 0., 0.5]
        counts = get_counts(measure(qreg, shots=100))
        @test counts["000"] + counts["111"] == 100
    end

    @testset begin
        cprobs = [0.5, 0.6, 0.75, 1.0]
        @test get_conf(cprobs, 0, 2) == "00"
        @test get_conf(cprobs, 0.25, 2) == "00"
        @test get_conf(cprobs, 0.5, 2) == "00"
        @test get_conf(cprobs, 0.65, 2) == "10"
        @test get_conf(cprobs, 0.99, 2) == "11"
    end
end


text:
printstyled("  convert\n", color=:light_green)
C = randSeisChannel()
C1 = convert(EventChannel, C)
TD = convert(EventTraceData, C1)
@test sizeof(TD) > 136

C2 = convert(SeisChannel, C)
@test C == C2

EC = convert(EventChannel, randSeisChannel())

TD = unsafe_convert(EventTraceData, randSeisData(10))
for f in datafields
  @test length(getfield(TD, f)) == 10
end

S = unsafe_convert(SeisData, randSeisEvent(10).data)
for f in datafields
  @test length(getfield(S, f)) == 10
end

printstyled("  show\n", color=:light_green)
redirect_stdout(out) do
  for i = 1:10
    for T in (SeisHdr, SeisSrc, SeisEvent, EventTraceData, EventChannel, EQMag, EQLoc, SourceTime)
      repr(T(), context=:compact=>true)
      repr(T(), context=:compact=>false)
      show(T())
    end
    summary(randSeisEvent())
    summary(randSeisHdr())
    summary(randSeisSrc())
    show(randSeisEvent())
    show(randSeisHdr())
    show(randSeisSrc())
  end
end

# EQMag
Δ = 75.3
m1 = EQMag(3.2f0, "Ml", 23, Δ, "localmag")
m2 = EQMag(3.2f0, "Ml", 23, Δ, "localmag")
@test hash(m1) == hash(m2)

# SourceTime
@test isempty(SourceTime())
ST1 = SourceTime()
@test hash(ST1) == hash(SourceTime())

# SeisSrc
@test isempty(SeisSrc())
@test isempty(SeisSrc(m0=1.0e22)) == false
@test isempty(SeisSrc(id = "123")) == false

ext: jl


text:
module metainfo
using Compat

type MetaVariable
    name::Symbol
    datatype::DataType
    dimensions::Array{Any}
    description::Compat.UTF8String
    unit::Compat.UTF8String
end

type MetaParameter
    name::Symbol
    datatype::DataType
    dimensions::Array{Any}
    description::Compat.UTF8String
    unit::Compat.UTF8String
end

type MetaDimension
    name::Symbol
end

type MetaComponent
    module_name::Symbol
    component_name::Symbol

    variables::Dict{Symbol,MetaVariable}
    parameters::Dict{Symbol,MetaParameter}
    dimensions::Dict{Symbol,MetaDimension}

    function MetaComponent(module_name::Symbol, component_name::Symbol)
        v = new(module_name, component_name, Dict{Symbol, MetaVariable}(), Dict{Symbol, MetaParameter}(), Dict{Symbol, MetaDimension}())
        return v
    end
end

const global _mimi_metainfo = Dict{Tuple{Symbol,Symbol},MetaComponent}()

function addcomponent(module_name::Symbol, component_name::Symbol)
    c = MetaComponent(module_name, component_name)
    _mimi_metainfo[(module_name, component_name)] = c
    nothing
end

function addvariable(module_name::Symbol, component_name::Symbol, name, datatype, dimensions, description, unit)
    c = _mimi_metainfo[(module_name, component_name)]

    v = MetaVariable(name, datatype, dimensions, description, unit)
    c.variables[name] = v
    nothing
end

function addparameter(module_name::Symbol, component_name::Symbol, name, datatype, dimensions, description, unit)
    c = _mimi_metainfo[(module_name, component_name)]

    p = MetaParameter(name, datatype, dimensions, description, unit)
    c.parameters[name] = p
    nothing
end

function adddimension(module_name::Symbol, component_name::Symbol, name)
    c = _mimi_metainfo[(module_name, component_name)]

    d = MetaDimension(name)
    c.dimensions[name] = d
    nothing
end

function getallcomps()
    _mimi_metainfo
end

function generate_comp_expressions(module_name, component_name)
    parameters = values(_mimi_metainfo[(module_name, component_name)].parameters)
    variables = values(_mimi_metainfo[(module_name, component_name)].variables)
    dimensions = values(_mimi_metainfo[(module_name, component_name)].dimensions)
    quote
        using Mimi

        # Define type for parameters
        type $(Symbol(string(component_name,"Parameters"))){T}
            $(begin
                x = Expr(:block)
                for p in parameters
                    concreteParameterType = p.datatype == Number ? :T : p.datatype

                    if length(p.dimensions)==0
                        push!(x.args, :($(p.name)::$(concreteParameterType)) )
                    else
                        push!(x.args, :($(p.name)::Array{$(concreteParameterType),$(length(p.dimensions))}) )
                    end
                end
                x
            end)

            function $(Symbol(string(component_name,"Parameters"))){T}(::Type{T})
                new{T}()
            end
        end

        # Define type for variables
        type $(Symbol(string(component_name,"Variables"))){T}
            $(begin
                x = Expr(:block)
                for v in variables
                    concreteVariableType = v.datatype == Number ? :T : v.datatype

                    if length(v.dimensions)==0
                        push!(x.args, :($(v.name)::$(concreteVariableType)) )
                    else
                        push!(x.args, :($(v.name)::Array{$(concreteVariableType),$(length(v.dimensions))}) )
                    end
                end
                x
            end)

            function $(Symbol(string(component_name, "Variables"))){T}(::Type{T}, indices)
                s = new{T}()

                $(begin
                    ep = Expr(:block)
                    for v in filter(i->length(i.dimensions)>0, variables)
                        concreteVariableType = v.datatype == Number ? :T : v.datatype

                        u = :(temp_indices = [])
                        for l in v.dimensions
                            if isa(l, Symbol)
                                push!(u.args[2].args, :(indices[$(QuoteNode(l))]))
                            elseif isa(l, Int)
                                push!(u.args[2].args, l)
                            else
                                error()
                            end
                        end
                        push!(ep.args,u)
                        push!(ep.args,:(s.$(v.name) = Array($(concreteVariableType),temp_indices...)))
                    end
                    ep
                end)

                return s
            end
        end

        # Define type for dimensions
        type $(Symbol(string(component_name,"Dimensions")))
            $(begin
                x = Expr(:block)
                for d in dimensions
                    push!(x.args, :($(d.name)::UnitRange{Int}) )
                end
                x
            end)

            function $(Symbol(string(component_name,"Dimensions")))(indices)
                s = new()
                $(begin
                    ep = Expr(:block)
                    for d in dimensions
                        push!(ep.args,:(s.$(d.name) = UnitRange{Int}(1,indices[$(QuoteNode(d.name))])))
                    end
                    ep
                end)
                return s
            end
        end

        # Define implementation typeof
        type $(Symbol(string(component_name, "Impl"))){T} <: Main.$(Symbol(module_name)).$(Symbol(component_name))
            nsteps::Int
            Parameters::$(Symbol(string(component_name,"Parameters"))){T}
            Variables::$(Symbol(string(component_name,"Variables"))){T}
            Dimensions::$(Symbol(string(component_name,"Dimensions")))

            function $(Symbol(string(component_name, "Impl"))){T}(::Type{T}, indices)
                s = new{T}()
                s.nsteps = indices[:time]
                s.Parameters = $(Symbol(string(component_name,"Parameters"))){T}(T)
                s.Dimensions = $(Symbol(string(component_name,"Dimensions")))(indices)
                s.Variables = $(Symbol(string(component_name,"Variables"))){T}(T, indices)
                return s
            end
        end

    end
end

end


text:
Reactive.__init__()
import Reactive: runner_task

facts("Queue runner") do
    context("Queue restarts during push!") do
        @fact queue_size() --> 0
        bcount = 0
        a = Signal(1)
        foreach(a; init=nothing) do _
            b = Signal(1)
            bcount += 1
            foreach(b; init=nothing) do _
                bcount += 1 #won't get run because of the init=nothing
            end
            nothing
        end
        function test_queue(expected_bcount, orig_runner)
            push!(a, 3)
            wait(Reactive.runner_task[])
            @fact queue_size() --> 0
            @fact orig_runner --> not(Reactive.runner_task[]) # we should have a new queue runner
            @fact bcount --> expected_bcount
        end
        @fact bcount --> 0
        test_queue(1, Reactive.runner_task[])
        test_queue(2, Reactive.runner_task[])
    end

    context("Multiple queue restarts during a single action") do
        @fact queue_size() --> 0
        bcount = 0
        a = Signal(1)
        foreach(a; init=nothing) do _
            b = Signal(1)
            bcount += 1
            foreach(b; init=nothing) do _
                bcount += 1 #won't get run because of the init=nothing
            end
            foreach(b; init=nothing) do _
                bcount += 1 #won't get run because of the init=nothing
            end
            nothing
        end
        function test_queue(expected_bcount, orig_runner)
            push!(a, 3)
            wait(Reactive.runner_task[])
            @fact queue_size() --> 0
            @fact orig_runner --> not(Reactive.runner_task[]) # we should have a new queue runner
            @fact bcount --> expected_bcount
        end
        @fact bcount --> 0
        test_queue(1, Reactive.runner_task[])
        test_queue(2, Reactive.runner_task[])
    end

    context("Queue restarts after more than one push!") do
        @fact queue_size() --> 0
        bcount = 0
        a = Signal(1)
        foreach(a; init=nothing) do _
            b = Signal(1)
            bcount += 1
            foreach(b; init=nothing) do _
                bcount += 1 #won't get run because of the init=nothing
            end
            nothing
        end
        function test_queue(expected_bcount, orig_runner)
            push!(a, 3)
            push!(a, 4)
            wait(Reactive.runner_task[])
            @fact queue_size() --> 0
            @fact orig_runner --> not(Reactive.runner_task[]) # we should have a new queue runner
            @fact bcount --> expected_bcount*2
        end
        @fact bcount --> 0
        test_queue(1, Reactive.runner_task[])
        test_queue(2, Reactive.runner_task[])
    end
end

if !istaskdone(Reactive.runner_task[])
    Reactive.stop()
    wait(Reactive.runner_task[])
end


text:
using Autotuning, CSV, DataFrames, Distributions

function sample_x_y(samples::Int,
                    distribution_x::Distribution,
                    distribution_y::Distribution)

    configuration = Configuration((x = Parameter(0.5, [0.0, 1.0]),
                                   y = Parameter(0.5, [0.0, 1.0])))

    distribution = (x = distribution_x,
                    y = distribution_y)

    configuration = perturb(configuration, distribution)

    sampled_data = configuration_table(configuration)

    for i = 2:samples
        configuration = perturb(configuration, distribution)
        push!(sampled_data, configuration)
    end

    return sampled_data
end

function sample()
    samples = 1000
    distributions = [
        (
            x = Truncated(Normal(0.5, 0.08), 0.0, 1.0),
            y = Truncated(Normal(0.5, 0.08), 0.0, 1.0),
            name = "mu:0.5,sig:0.08"
        ),
        (
            x = Truncated(Normal(0.5, 0.13), 0.0, 1.0),
            y = Truncated(Normal(0.5, 0.13), 0.0, 1.0),
            name = "mu:0.5,sig:0.13"
        ),
        (
            x = Truncated(Normal(0.1, 0.08), 0.0, 1.0),
            y = Truncated(Normal(0.5, 0.13), 0.0, 1.0),
            name = "mu:(0.1,0.5),sig:(0.08,0.13)"
        ),
        (
            x = MixtureModel(
                [
                    Truncated(Normal(0.0, 0.08), 0.0, 0.4),
                    Truncated(Normal(1.0, 0.08), 0.6, 1.0)
                ]
            ),
            y = MixtureModel(
                [
                    Truncated(Normal(0.0, 0.08), 0.0, 0.4),
                    Truncated(Normal(1.0, 0.08), 0.6, 1.0)
                ]
            ),
            name = "mu:(0.0,1.0)*2,sig:(0.08)*2"
        )
    ]

    sampled_data = sample_x_y(samples, distributions[1][:x], distributions[1][:y])
    sampled_data.name = repeat([distributions[1][:name]], samples)

    for distribution in distributions[2:end]
        new_data = sample_x_y(samples, distribution[:x], distribution[:y])
        new_data.name = repeat([distribution[:name]], samples)

        append!(sampled_data, new_data)
    end

    new_data = sample_x_y(samples, distributions[1][:x], distributions[end][:y])
    new_data.name = repeat([distributions[1][:name] * "x"], samples)

    append!(sampled_data, new_data)

    new_data = sample_x_y(samples, distributions[end][:x], distributions[1][:y])
    new_data.name = repeat([distributions[end][:name] * "x"], samples)

    append!(sampled_data, new_data)

    CSV.write("sampled_data.csv", sampled_data)
end

sample()


text:
module HarmonicBalance

    using Printf
    using DataStructures
    import Base: show, display; export show
    export *
    export @variables
    export d
    export plot
    using Symbolics
    using ProgressMeter
    import SymbolicUtils: Term, Add, Div, Mul, Pow, Sym
    using DocStringExtensions

    import Base: ComplexF64, Float64; export ComplexF64, Float64
    ComplexF64(x::Complex{Num}) = ComplexF64(Float64(x.re) + im*Float64(x.im))
    Float64(x::Complex{Num}) = Float64(ComplexF64(x))
    Float64(x::Num) = Float64(x.val)

   # default global settings
   export im_tol
   im_tol = 1E-6
   function set_imaginary_tolerance(x::Float64)
       @eval(im_tol = $x)
   end

   export is_real
    is_real(x) = abs(imag(x)) < im_tol
    is_real(x::Array) = any(is_real.(x))

    # Symbolics does not natively support complex exponentials of variables
    import Base: exp
    exp(x::Complex{Num}) = x.re.val == 0 ? exp(im*x.im.val) : exp(x.re.val + im*x.im.val)

    include("types.jl")

    include("utils.jl")
    include("Symbolics_customised.jl")
    include("Symbolics_utils.jl")
    include("DifferentialEquation.jl")
    include("HarmonicVariable.jl")
    include("HarmonicEquation.jl")
    include("solve_homotopy.jl")
    include("sorting.jl")
    include("classification.jl")
    include("saving.jl")
    include("plotting_static.jl")
    include("plotting_interactive.jl")
    include("hysteresis_sweep.jl")

    include("modules/HC_wrapper.jl")
    using .HC_wrapper

    include("modules/LinearResponse.jl")
    using .LinearResponse

    include("modules/TimeEvolution.jl")
    using .TimeEvolution

    include("modules/Hopf.jl")
    using .Hopf

end # module


text:
using DiffEqSensitivity
using Test

@testset "DiffEqSensitivity" begin

@testset "Local Sensitivity" begin include("local.jl") end
@testset "Adjoint Sensitivity" begin include("adjoint.jl") end
@testset "Morris Method" begin include("morris_method.jl") end
@testset "Sobol Method" begin include("sobol_method.jl") end

end


text:
const Point4f = Point{4,Float32}

abstract type VertexData end

struct PosColor{P<:Point,C<:RGBA} <: VertexData
    position::P
    color::C
end

struct PosUV{P <: Point, UV<:Point{2}} <: VertexData
    position::P
    uv::UV
end

Vulkan.VertexInputAttributeDescription(::Type{T}, binding) where {T<:VertexData} =
    VertexInputAttributeDescription.(
        0:fieldcount(T)-1,
        binding,
        Format.(fieldtypes(T)),
        fieldoffset.(T, 1:fieldcount(T)),
    )

Vulkan.VertexInputBindingDescription(
    ::Type{T},
    binding;
    input_rate = VERTEX_INPUT_RATE_VERTEX,
) where {T<:VertexData} = VertexInputBindingDescription(binding, sizeof(T), input_rate)

function invert_y_axis(p::Point)
    coords = map(x -> x[1] == 2 ? -x[2] : x[2], enumerate(coordinates(p)))
    typeof(p)(coords)
end

function Vulkan.Format(::Type{T}) where {T}
    @match T begin
        &Point1f => FORMAT_R32_SFLOAT
        &Point2f => FORMAT_R32G32_SFLOAT
        &Point3f || &RGB{Float16} => FORMAT_R32G32B32_SFLOAT
        &Point4f || &RGBA{Float32} => FORMAT_R32G32B32A32_SFLOAT
        &RGBA{Float16} => FORMAT_R16G16B16A16_SFLOAT
    end
end


text:
function try_symbolic(T, eq, x, basis, Δbasis; kwargs...)
    n = length(basis)
    @syms θ[1:n]

    Δeq = sum(θ[j]*Δbasis[j] for j=1:n) - eq
    Δeq = expand(Δeq)

    terms = collect_terms(Δeq, x)
    eqs = collect(values(terms))
    # eqs = filter(p->length(get_variables(p)) > 0, eqs)

    sol = solve_symbolic(eqs)

    for i = 1:n
        if !haskey(sol, θ[i])
            sol[θ[i]] = 0
        end
    end

    p = substitute(expand(sum(θ[j]*basis[j] for j=1:n)), sol)
    p, 0
end

mutable struct Fragment
    eq
    lhs
end

function solve_symbolic(eqs)
    n = length(eqs)
    solved = Set()
    unfinished = true
    frags = Fragment[]
    k = 1

    while unfinished
        unfinished = false
        for eq in eqs
            δf = [v for v in get_variables(eq) if v ∉ solved]
            if length(δf) == 1
                push!(solved, δf[1])
                push!(frags, Fragment(eq, δf[1]))
                unfinished = true
            end
        end
    end

    sol = Dict()
    for f in frags
        eq = substitute(f.eq, sol)
        u = Symbolics.solve_for(eq ~ 0, f.lhs)
        sol[f.lhs] = nice_parameter(u)
    end

    sys = []
    vars = Set()

    for eq in eqs
        δf = [v for v in get_variables(eq) if v ∉ solved]
        if length(δf) > 1
            for v in δf
                push!(vars, v)
            end
            q = substitute(eq, sol)
            push!(sys, q)
        end
    end

    sys = unique(sys)
    vars = [v for v in vars]

    if !isempty(vars) && length(vars) == length(sys)
        try
            vals = nice_parameters.(Symbolics.solve_for(sys .~ 0, vars))
            # vals = Symbolics.solve_for(sys .~ 0, vars)
            for (v,u) in zip(vars, vals)
                sol[v] = u
            end
        catch e
            # println("from symbolic: ", e)
        end
    end

    sol
end

function collect_terms(eq::SymbolicUtils.Add, x)
    d = Dict{Any,Any}(1 => 0)
    for t in arguments(eq)
        if isdependent(t, x)
            for s in collect_terms(t, x)
                v, c = first(s), last(s)
                if haskey(d, v)
                    d[v] += c
                else
                    d[v] = c
                end
            end
        else
            d[1] += t
        end
    end
    d
end

function collect_terms(eq, x)
    c = coef(eq, x)
    return Dict(eq/c => c)
end


text:
using Clang
using Test

@testset "wrap_c" begin
    ctx = DefaultContext()
    parse_header!(ctx, joinpath(@__DIR__, "c", "cbasic.h"))
    root_cursor = getcursor(ctx.trans_units[1])
    func1 = search(root_cursor, "func1")[1]
    ctx.libname = "test"

    wrap!(ctx, func1)

    exc = :(
        function func1(a::Cint,b::Cdouble,c,d)
            ccall((:func1,test),Cint,(Cint,Cdouble,Ptr{Cdouble},Ptr{Cvoid}),a,b,c,d)
        end)

    Base.remove_linenums!(exc)

    @test ctx.api_buffer[1] == exc
end


text:
# License for this file: MIT (expat)
# Copyright 2017-2018, DLR Institute of System Dynamics and Control

"""
    module Modia3D.Solids

Module `Solids` provides data structures and operations for solids, so objects that have a volume and
properties associated with the volume.
Solid parts can be associated with a [`Modia3D.Object3D`](@ref).
They are defined with struct [`Modia3D.Solid`](@ref) consisting of an **optional** solid geometry:

![Solids](../../resources/images/SolidGeos.jpg)

and other **optional** properties:

- mass propreties (defined by geometry+material-name, geometry+density, or directly defined mass properties),
- contact material (for elastic response calculation),
- visualization material (for visualization, see below).

Since the solid geometry itself is optional, it is possible to just define a
coordinate system with associated mass, center of mass and inertia matrix.

The following functions are provided for a solid geometry `geo::Modia3D.AbstractSolidGeometry` that
is associated with an Object3D `object3D`:
- [`Modia3D.volume`](@ref)`(geo)` returns the volume of `geo`.
- [`Modia3D.centroid`](@ref)`(geo)` returns the centroid of `geo` (= center of mass for uniform density).
- [`Modia3D.inertiaMatrix`](@ref)`(geo, mass)` returns the inertia matrix of `geo`.
- [`Modia3D.boundingBox!`](@ref)`(geo, <other arguments>)` returns the Axis Aligned Bounding Box of `geo`.
- [`Modia3D.supportPoint`](@ref)`(geo, <other arguments>)` returns the support point of `geo` along the desired direction.
- isVisible(object3D, renderer),
- dataHasMass(object3D),
- canCollide(object3D),
- and other functions.

Other functions in module `Solids`:
- [`Modia3D.SolidMaterial`](@ref)(name) returns the solid properties of material `name`.

# Main developers
Andrea Neumayr and Martin Otter, [DLR - Institute of System Dynamics and Control](https://www.dlr.de/sr/en)
"""
module Solids

# Concave properties
export ConcaveProperties

# Solid geometries
export Solid, SolidFileMesh, SolidWithConvexDecomposition
export SolidSphere, SolidEllipsoid, SolidBox, SolidCylinder, SolidCapsule, SolidBeam, SolidCone, SolidPipe
export volume, centroid, bottomArea, topArea, longestEdge, lengthGeo, inertiaMatrix, boundingBox!, supportPoint
# export canCollide

# Solid materials
export InternalMassProperties, MassProperties, SolidMaterial, ContactMaterialElastic, dummyMassProperties
export solidMaterial, solidMaterialPalette, defaultContactMaterial
export regularize, resultantCoefficientOfRestitution, resultantDampingCoefficient
export solidMaterialPairsPalette, CommonCollisionProperties, getCommonCollisionProperties

export contactPairMaterialPalette, ElasticContactPairMaterial, TwoNamesKey

using StaticArrays
import JSON
import Modia3D
import Modia3D.Basics
import Modia3D.Graphics
import ModiaMath

const NOTHING = Nothing

include("concaveProperties.jl")
include("geometry.jl")
include("solidMaterial.jl")
include("massProperties.jl")
include("contactPairMaterials.jl")
include("solid.jl")

end


text:
#
## Hash methods
#

function call(::Type{Sidef_Types_Hash_Hash}, s::Any...)
    d = Dict{Any,Any}()
    for i in 1:2:length(s)
        d[s[i]] = s[i+1]
    end
    Sidef_Types_Hash_Hash(d)
end

function getindex(h::Sidef_Types_Hash_Hash, k::Any)
    (h.value)[k]
end

function setindex!(h::Sidef_Types_Hash_Hash, v::Any, k::Any)
    (h.value)[k] = v
end

max_stars_repo_name: trizen/Sidef-Deparse-Julia

max_issues_repo_name: trizen/Sidef-Deparse-Julia

max_forks_repo_name: trizen/Sidef-Deparse-Julia


text:
"""
    run_chain!(graph, plan, config)

Run the chain specified by `config`.
"""
function update!(plan::Plan, graph::IndexedGraph, flip::Flip)
    assignment_map = Dict{Int, Int}(node => flip.new_assignments[index]
                                    for (index, node) in enumerate(flip.nodes))
    @inbounds for (index, node) in enumerate(flip.nodes)
        old_assignment = flip.old_assignments[index]
        new_assignment = flip.new_assignments[index]
        for neighbor_index in 1:graph.neighbors_per_node[node]
            # Fix the assignments of the edges connected to flipped nodes.
            # For each edge connected to a node in the set of flipped nodes,
            # verify that the assignment on both sides of the edge is the same
            # pre-flip and post-flip. Otherwise, adjust accordingly by removing
            # the edge from the appropriate set in `district_edges`.
            dst = graph.node_neighbors[neighbor_index, node]
            edge_index = graph.src_dst_to_edge[node, dst]
            old_dst_assignment = plan.assignment[dst]
            if dst in keys(assignment_map)
                new_dst_assignment = assignment_map[dst]
            else
                new_dst_assignment = plan.assignment[dst]
            end
            if old_assignment != new_assignment
                if new_dst_assignment != old_assignment
                    delete!(plan.district_edges[old_assignment], edge_index)
                end
                union!(plan.district_edges[new_assignment], edge_index)
            end
            if old_dst_assignment != new_dst_assignment
                if old_dst_assignment != new_assignment
                    delete!(plan.district_edges[old_dst_assignment], edge_index)
                end
                union!(plan.district_edges[new_dst_assignment], edge_index)
            end
        end
        plan.assignment[node] = new_assignment
        delete!(plan.district_nodes[old_assignment], node)
        union!(plan.district_nodes[new_assignment], node)
    end
    setdiff!(plan.cut_edges, flip.cut_delta.cut_edges_before)
    union!(plan.cut_edges, flip.cut_delta.cut_edges_after)
    @inbounds plan.district_populations[flip.left_district] = flip.left_pop
    @inbounds plan.district_populations[flip.right_district] = flip.right_pop
    # Recompute district-level adjacency (district outer boundaries are changed!)
    district_adj = zeros(Int, plan.n_districts, plan.n_districts)
    for edge_index in 1:graph.n_edges
        src, dst = graph.edges[:, edge_index]
        left_district = plan.assignment[src]
        right_district = plan.assignment[dst]
        if left_district != right_district
            district_adj[left_district, right_district] += 1
            district_adj[right_district, left_district] += 1
        end
    end
    plan.district_adj = district_adj
    plan.n_cut_edges += flip.cut_delta.Δ
end


text:
@testset "ischordal" begin
    g = path_graph(3)
    @test ischordal(g)
    add_edge!(g, 1, 3)
    @test ischordal(g)
    g = path_graph(4)
    add_edge!(g, 1, 4)
    @test !ischordal(g)
    add_edge!(g, 1, 4)
    add_edge!(g, 2, 4)
    @test ischordal(g)
end

max_stars_repo_name: charlyalizadeh/PowerFlowNetworks

max_issues_repo_name: charlyalizadeh/PowerFlowNetworks

max_forks_repo_name: charlyalizadeh/PowerFlowNetworks


text:
function MOI.add_variable(model::Optimizer)
    avar = _ensure_avar(model)
    rhp_add_var(model.ctx, avar)
    return MOI.VariableIndex(1+reshop_avar_get(avar, UInt32(0)))
end

function MOI.add_variables(model::Optimizer, n::Integer)
    avar = _ensure_avar(model)
    rhp_add_var(model.ctx, n, avar)
    # We have faith that we have a compact avar
    vidx = 1+reshop_avar_get(avar, UInt32(0))
    return [MOI.VariableIndex(i) for i=vidx:vidx+n-1]
end

# MathOptInterface Variables

##################################################
## Getters
MOI.get(model::Optimizer, ::MOI.NumberOfVariables) = number_variables(model)

function MOI.get(model::Optimizer, ::MOI.ListOfVariableIndices)
    return [MOI.VariableIndex(i) for i in 1:ctx_numvar(model.ctx)]
end

function check_inbounds(model::Optimizer, vi::MOI.VariableIndex)
    num_variables = ctx_numvar(model.ctx)
    if !(1 <= vi.value <= 1+num_variables)
        error("Invalid variable index $vi. ($num_variables variables in the model.)")
    end
    return
end

function check_inbounds(model::Optimizer, vi::Integer)
    num_variables = ctx_numvar(model.ctx)
    if !(1 <= vi <= 1+num_variables)
        error("Invalid variable index $vi. ($num_variables variables in the model.)")
    end
    return
end

##################################################
## Check inbounds for safety.
function check_inbounds(model::Optimizer, var::MOI.SingleVariable)
    return check_inbounds(model, var.variable)
end

function check_inbounds(model::Optimizer, aff::MOI.ScalarAffineFunction)
    for term in aff.terms
        check_inbounds(model, term.variable_index)
    end
    return
end

function check_inbounds(model::Optimizer, quad::MOI.ScalarQuadraticFunction)
    for term in quad.affine_terms
        check_inbounds(model, term.variable_index)
    end
    for term in quad.quadratic_terms
        check_inbounds(model, term.variable_index_1)
        check_inbounds(model, term.variable_index_2)
    end
    return
end

function has_upper_bound(model::Optimizer, vi::MOI.VariableIndex)
    (lb, ub) = ctx_getvarbounds(model.ctx, vi.value-1)
    return isfinite(ub)
end

function has_lower_bound(model::Optimizer, vi::MOI.VariableIndex)
    (lb, ub) = ctx_getvarbounds(model.ctx, vi.value-1)
    return isfinite(lb)
end

function is_fixed(model::Optimizer, vi::MOI.VariableIndex)
    (lb, ub) = ctx_getvarbounds(model.ctx, vi.value-1)
    return isfinite(lb) && isfinite(ub) && abs(ub-lb) < eps()
end

function has_box_bounds(model::Optimizer, vi::MOI.VariableIndex)
    (lb, ub) = ctx_getvarbounds(model.ctx, vi.value-1)
    return isfinite(lb) && isfinite(ub)
end

##################################################
## PrimalStart
function MOI.set(model::Optimizer, ::MOI.VariablePrimalStart,
                 vi::MOI.VariableIndex, value::Union{Real, Nothing})
    check_inbounds(model, vi)
    val = isa(value, Real) ? Cdouble(value) : 0.
    ctx_setvarval(model.ctx, vi.value - 1, val)
end

##################################################
## Naming
function MOI.set(model::Optimizer, ::MOI.VariableName, vi::MOI.VariableIndex, name::String)
    check_inbounds(model, vi)
    ctx_setvarname(model.ctx, vi.value-1, name)
end

##################################################
## getter
function MOI.get(model::Optimizer, ::MOI.VariablePrimalStart, vi::MOI.VariableIndex)
    check_inbounds(model, vi)
    return ctx_getvarval(model.ctx, vi.value-1)
end

#function MOI.get(model::Optimizer, vi::MathOptInterface.VariableIndex)
#    return ctx_getvarname(model.ctx, vi.value-1)
#end

function MOI.get(model::Optimizer, ::Type{MOI.VariableIndex}, name::String)
    vidx = ctx_getvarbyname(model.ctx, name)
    if vidx >= 0
        return MOI.VariableIndex(vidx+1)
    elseif vidx == -2
        error("Multiple variables have the name $(name).")
    else
        return nothing
    end
end

function MOI.get(model::Optimizer, ::MOI.VariableName, vi::MOI.VariableIndex)
    check_inbounds(model, vi)
    return ctx_getvarname(model.ctx, vi.value-1)
end

function MOI.is_valid(model::Optimizer, vi::MOI.VariableIndex)
    check_inbounds(model, vi)
    return rhp_is_var_valid(model.ctx, vi.value-1)
end


text:
################################################################################
# Functions as exported by Clang but removed parameter types.                  #
# This regular expression should help                                          #
# ([A-z_0-9]*)(\{([A-z,_,0-9])*\})*                                          #
################################################################################
function tox_version_major()
    ccall((:tox_version_major,libtoxcore),Uint32,())
end

function tox_version_minor()
    ccall((:tox_version_minor,libtoxcore),Uint32,())
end

function tox_version_patch()
    ccall((:tox_version_patch,libtoxcore),Uint32,())
end

function tox_version_is_compatible(major,minor,patch)
    ccall((:tox_version_is_compatible,libtoxcore),Bool,(Uint32,Uint32,Uint32),major,minor,patch)
end

function tox_options_default(options)
    ccall((:tox_options_default,libtoxcore),Void,(Ptr{Tox_Options},),options)
end

function tox_options_new(error)
    ccall((:tox_options_new,libtoxcore),Ptr{Tox_Options},(Ptr{TOX_ERR_OPTIONS_NEW},),error)
end

function tox_options_free(options)
    ccall((:tox_options_free,libtoxcore),Void,(Ptr{Tox_Options},),options)
end

function tox_new(options,error)
    ccall((:tox_new,libtoxcore),Ptr{Tox},(Ptr{Tox_Options},Ptr{TOX_ERR_NEW}),options,error)
end

function tox_kill(tox)
    ccall((:tox_kill,libtoxcore),Void,(Ptr{Tox},),tox)
end

function tox_get_savedata_size(tox)
    ccall((:tox_get_savedata_size,libtoxcore),Csize_t,(Ptr{Tox},),tox)
end

function tox_get_savedata(tox,savedata)
    ccall((:tox_get_savedata,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,savedata)
end

function tox_bootstrap(tox,address,port,public_key,error)
    ccall((:tox_bootstrap,libtoxcore),Bool,(Ptr{Tox},Ptr{Uint8},Uint16,Ptr{Uint8},Ptr{TOX_ERR_BOOTSTRAP}),tox,address,port,public_key,error)
end

function tox_add_tcp_relay(tox,address,port,public_key,error)
    ccall((:tox_add_tcp_relay,libtoxcore),Bool,(Ptr{Tox},Ptr{Uint8},Uint16,Ptr{Uint8},Ptr{TOX_ERR_BOOTSTRAP}),tox,address,port,public_key,error)
end

function tox_self_get_connection_status(tox)
    ccall((:tox_self_get_connection_status,libtoxcore),TOX_CONNECTION,(Ptr{Tox},),tox)
end

function tox_callback_self_connection_status(tox,callback,user_data)
    ccall((:tox_callback_self_connection_status,libtoxcore),Void,(Ptr{Tox},Ptr{tox_self_connection_status_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_iteration_interval(tox)
    ccall((:tox_iteration_interval,libtoxcore),Uint32,(Ptr{Tox},),tox)
end

function tox_iterate(tox)
    ccall((:tox_iterate,libtoxcore),Void,(Ptr{Tox},),tox)
end

function tox_self_get_address(tox,address)
    ccall((:tox_self_get_address,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,address)
end

function tox_self_set_nospam(tox,nospam)
    ccall((:tox_self_set_nospam,libtoxcore),Void,(Ptr{Tox},Uint32),tox,nospam)
end

function tox_self_get_nospam(tox)
    ccall((:tox_self_get_nospam,libtoxcore),Uint32,(Ptr{Tox},),tox)
end

function tox_self_get_public_key(tox,public_key)
    ccall((:tox_self_get_public_key,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,public_key)
end

function tox_self_get_secret_key(tox,secret_key)
    ccall((:tox_self_get_secret_key,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,secret_key)
end

function tox_self_set_name(tox,name,length,error)
    ccall((:tox_self_set_name,libtoxcore),Bool,(Ptr{Tox},Ptr{Uint8},Csize_t,Ptr{TOX_ERR_SET_INFO}),tox,name,length,error)
end

function tox_self_get_name_size(tox)
    ccall((:tox_self_get_name_size,libtoxcore),Csize_t,(Ptr{Tox},),tox)
end

function tox_self_get_name(tox,name)
    ccall((:tox_self_get_name,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,name)
end

function tox_self_set_status_message(tox,status_message,length,error)
    ccall((:tox_self_set_status_message,libtoxcore),Bool,(Ptr{Tox},Ptr{Uint8},Csize_t,Ptr{TOX_ERR_SET_INFO}),tox,status_message,length,error)
end

function tox_self_get_status_message_size(tox)
    ccall((:tox_self_get_status_message_size,libtoxcore),Csize_t,(Ptr{Tox},),tox)
end

function tox_self_get_status_message(tox,status_message)
    ccall((:tox_self_get_status_message,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,status_message)
end

function tox_self_set_status(tox,status)
    ccall((:tox_self_set_status,libtoxcore),Void,(Ptr{Tox},TOX_USER_STATUS),tox,status)
end

function tox_self_get_status(tox)
    ccall((:tox_self_get_status,libtoxcore),TOX_USER_STATUS,(Ptr{Tox},),tox)
end

function tox_friend_add(tox,address,message,length,error)
    ccall((:tox_friend_add,libtoxcore),Uint32,(Ptr{Tox},Ptr{Uint8},Ptr{Uint8},Csize_t,Ptr{TOX_ERR_FRIEND_ADD}),tox,address,message,length,error)
end

function tox_friend_add_norequest(tox,public_key,error)
    ccall((:tox_friend_add_norequest,libtoxcore),Uint32,(Ptr{Tox},Ptr{Uint8},Ptr{TOX_ERR_FRIEND_ADD}),tox,public_key,error)
end

function tox_friend_delete(tox,friend_number,error)
    ccall((:tox_friend_delete,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_DELETE}),tox,friend_number,error)
end

function tox_friend_by_public_key(tox,public_key,error)
    ccall((:tox_friend_by_public_key,libtoxcore),Uint32,(Ptr{Tox},Ptr{Uint8},Ptr{TOX_ERR_FRIEND_BY_PUBLIC_KEY}),tox,public_key,error)
end

function tox_friend_exists(tox,friend_number)
    ccall((:tox_friend_exists,libtoxcore),Bool,(Ptr{Tox},Uint32),tox,friend_number)
end

function tox_self_get_friend_list_size(tox)
    ccall((:tox_self_get_friend_list_size,libtoxcore),Csize_t,(Ptr{Tox},),tox)
end

function tox_self_get_friend_list(tox,friend_list)
    ccall((:tox_self_get_friend_list,libtoxcore),Void,(Ptr{Tox},Ptr{Uint32}),tox,friend_list)
end

function tox_friend_get_public_key(tox,friend_number,public_key,error)
    ccall((:tox_friend_get_public_key,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{Uint8},Ptr{TOX_ERR_FRIEND_GET_PUBLIC_KEY}),tox,friend_number,public_key,error)
end

function tox_friend_get_last_online(tox,friend_number,error)
    ccall((:tox_friend_get_last_online,libtoxcore),Uint64,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_GET_LAST_ONLINE}),tox,friend_number,error)
end

function tox_friend_get_name_size(tox,friend_number,error)
    ccall((:tox_friend_get_name_size,libtoxcore),Csize_t,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,error)
end

function tox_friend_get_name(tox,friend_number,name,error)
    ccall((:tox_friend_get_name,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{Uint8},Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,name,error)
end

function tox_callback_friend_name(tox,callback,user_data)
    ccall((:tox_callback_friend_name,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_name_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_friend_get_status_message_size(tox,friend_number,error)
    ccall((:tox_friend_get_status_message_size,libtoxcore),Csize_t,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,error)
end

function tox_friend_get_status_message(tox,friend_number,status_message,error)
    ccall((:tox_friend_get_status_message,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{Uint8},Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,status_message,error)
end

function tox_callback_friend_status_message(tox,callback,user_data)
    ccall((:tox_callback_friend_status_message,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_status_message_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_friend_get_status(tox,friend_number,error)
    ccall((:tox_friend_get_status,libtoxcore),TOX_USER_STATUS,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,error)
end

function tox_callback_friend_status(tox,callback,user_data)
    ccall((:tox_callback_friend_status,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_status_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_friend_get_connection_status(tox,friend_number,error)
    ccall((:tox_friend_get_connection_status,libtoxcore),TOX_CONNECTION,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,error)
end

function tox_callback_friend_connection_status(tox,callback,user_data)
    ccall((:tox_callback_friend_connection_status,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_connection_status_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_friend_get_typing(tox,friend_number,error)
    ccall((:tox_friend_get_typing,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{TOX_ERR_FRIEND_QUERY}),tox,friend_number,error)
end

function tox_callback_friend_typing(tox,callback,user_data)
    ccall((:tox_callback_friend_typing,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_typing_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_self_set_typing(tox,friend_number,typing,error)
    ccall((:tox_self_set_typing,libtoxcore),Bool,(Ptr{Tox},Uint32,Bool,Ptr{TOX_ERR_SET_TYPING}),tox,friend_number,typing,error)
end

function tox_friend_send_message(tox,friend_number,_type,message,length,error)
    ccall((:tox_friend_send_message,libtoxcore),Uint32,(Ptr{Tox},Uint32,TOX_MESSAGE_TYPE,Ptr{Uint8},Csize_t,Ptr{TOX_ERR_FRIEND_SEND_MESSAGE}),tox,friend_number,_type,message,length,error)
end

function tox_callback_friend_read_receipt(tox,callback,user_data)
    ccall((:tox_callback_friend_read_receipt,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_read_receipt_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_callback_friend_request(tox,callback,user_data)
    ccall((:tox_callback_friend_request,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_request_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_callback_friend_message(tox,callback,user_data)
    ccall((:tox_callback_friend_message,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_message_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_hash(hash,data,length)
    ccall((:tox_hash,libtoxcore),Bool,(Ptr{Uint8},Ptr{Uint8},Csize_t),hash,data,length)
end

function tox_file_control(tox,friend_number,file_number,control,error)
    ccall((:tox_file_control,libtoxcore),Bool,(Ptr{Tox},Uint32,Uint32,TOX_FILE_CONTROL,Ptr{TOX_ERR_FILE_CONTROL}),tox,friend_number,file_number,control,error)
end

function tox_callback_file_recv_control(tox,callback,user_data)
    ccall((:tox_callback_file_recv_control,libtoxcore),Void,(Ptr{Tox},Ptr{tox_file_recv_control_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_file_seek(tox,friend_number,file_number,position,error)
    ccall((:tox_file_seek,libtoxcore),Bool,(Ptr{Tox},Uint32,Uint32,Uint64,Ptr{TOX_ERR_FILE_SEEK}),tox,friend_number,file_number,position,error)
end

function tox_file_get_file_id(tox,friend_number,file_number,file_id,error)
    ccall((:tox_file_get_file_id,libtoxcore),Bool,(Ptr{Tox},Uint32,Uint32,Ptr{Uint8},Ptr{TOX_ERR_FILE_GET}),tox,friend_number,file_number,file_id,error)
end

function tox_file_send(tox,friend_number,kind,file_size,file_id,filename,filename_length,error)
    ccall((:tox_file_send,libtoxcore),Uint32,(Ptr{Tox},Uint32,Uint32,Uint64,Ptr{Uint8},Ptr{Uint8},Csize_t,Ptr{TOX_ERR_FILE_SEND}),tox,friend_number,kind,file_size,file_id,filename,filename_length,error)
end

function tox_file_send_chunk(tox,friend_number,file_number,position,data,length,error)
    ccall((:tox_file_send_chunk,libtoxcore),Bool,(Ptr{Tox},Uint32,Uint32,Uint64,Ptr{Uint8},Csize_t,Ptr{TOX_ERR_FILE_SEND_CHUNK}),tox,friend_number,file_number,position,data,length,error)
end

function tox_callback_file_chunk_request(tox,callback,user_data)
    ccall((:tox_callback_file_chunk_request,libtoxcore),Void,(Ptr{Tox},Ptr{tox_file_chunk_request_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_callback_file_recv(tox,callback,user_data)
    ccall((:tox_callback_file_recv,libtoxcore),Void,(Ptr{Tox},Ptr{tox_file_recv_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_callback_file_recv_chunk(tox,callback,user_data)
    ccall((:tox_callback_file_recv_chunk,libtoxcore),Void,(Ptr{Tox},Ptr{tox_file_recv_chunk_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_friend_send_lossy_packet(tox,friend_number,data,length,error)
    ccall((:tox_friend_send_lossy_packet,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{Uint8},Csize_t,Ptr{TOX_ERR_FRIEND_CUSTOM_PACKET}),tox,friend_number,data,length,error)
end

function tox_friend_send_lossless_packet(tox,friend_number,data,length,error)
    ccall((:tox_friend_send_lossless_packet,libtoxcore),Bool,(Ptr{Tox},Uint32,Ptr{Uint8},Csize_t,Ptr{TOX_ERR_FRIEND_CUSTOM_PACKET}),tox,friend_number,data,length,error)
end

function tox_callback_friend_lossy_packet(tox,callback,user_data)
    ccall((:tox_callback_friend_lossy_packet,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_lossy_packet_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_callback_friend_lossless_packet(tox,callback,user_data)
    ccall((:tox_callback_friend_lossless_packet,libtoxcore),Void,(Ptr{Tox},Ptr{tox_friend_lossless_packet_cb},Ptr{Void}),tox,callback,user_data)
end

function tox_self_get_dht_id(tox,dht_id)
    ccall((:tox_self_get_dht_id,libtoxcore),Void,(Ptr{Tox},Ptr{Uint8}),tox,dht_id)
end

function tox_self_get_udp_port(tox,error)
    ccall((:tox_self_get_udp_port,libtoxcore),Uint16,(Ptr{Tox},Ptr{TOX_ERR_GET_PORT}),tox,error)
end

function tox_self_get_tcp_port(tox,error)
    ccall((:tox_self_get_tcp_port,libtoxcore),Uint16,(Ptr{Tox},Ptr{TOX_ERR_GET_PORT}),tox,error)
end

function tox_callback_group_invite(tox,_function,userdata)
    ccall((:tox_callback_group_invite,libtoxcore),Void,(Ptr{Tox},Ptr{Void},Ptr{Void}),tox,_function,userdata)
end

function tox_callback_group_message(tox,_function,userdata)
    ccall((:tox_callback_group_message,libtoxcore),Void,(Ptr{Tox},Ptr{Void},Ptr{Void}),tox,_function,userdata)
end

function tox_callback_group_action(tox,_function,userdata)
    ccall((:tox_callback_group_action,libtoxcore),Void,(Ptr{Tox},Ptr{Void},Ptr{Void}),tox,_function,userdata)
end

function tox_callback_group_title(tox,_function,userdata)
    ccall((:tox_callback_group_title,libtoxcore),Void,(Ptr{Tox},Ptr{Void},Ptr{Void}),tox,_function,userdata)
end

function tox_callback_group_namelist_change(tox,_function,userdata)
    ccall((:tox_callback_group_namelist_change,libtoxcore),Void,(Ptr{Tox},Ptr{Void},Ptr{Void}),tox,_function,userdata)
end

function tox_add_groupchat(tox)
    ccall((:tox_add_groupchat,libtoxcore),Cint,(Ptr{Tox},),tox)
end

function tox_del_groupchat(tox,groupnumber)
    ccall((:tox_del_groupchat,libtoxcore),Cint,(Ptr{Tox},Cint),tox,groupnumber)
end

function tox_group_peername(tox,groupnumber,peernumber,name)
    ccall((:tox_group_peername,libtoxcore),Cint,(Ptr{Tox},Cint,Cint,Ptr{Uint8}),tox,groupnumber,peernumber,name)
end

function tox_group_peer_pubkey(tox,groupnumber,peernumber,public_key)
    ccall((:tox_group_peer_pubkey,libtoxcore),Cint,(Ptr{Tox},Cint,Cint,Ptr{Uint8}),tox,groupnumber,peernumber,public_key)
end

function tox_invite_friend(tox,friendnumber,groupnumber)
    ccall((:tox_invite_friend,libtoxcore),Cint,(Ptr{Tox},Int32,Cint),tox,friendnumber,groupnumber)
end

function tox_join_groupchat(tox,friendnumber,data,length)
    ccall((:tox_join_groupchat,libtoxcore),Cint,(Ptr{Tox},Int32,Ptr{Uint8},Uint16),tox,friendnumber,data,length)
end

function tox_group_message_send(tox,groupnumber,message,length)
    ccall((:tox_group_message_send,libtoxcore),Cint,(Ptr{Tox},Cint,Ptr{Uint8},Uint16),tox,groupnumber,message,length)
end

function tox_group_action_send(tox,groupnumber,action,length)
    ccall((:tox_group_action_send,libtoxcore),Cint,(Ptr{Tox},Cint,Ptr{Uint8},Uint16),tox,groupnumber,action,length)
end

function tox_group_set_title(tox,groupnumber,title,length)
    ccall((:tox_group_set_title,libtoxcore),Cint,(Ptr{Tox},Cint,Ptr{Uint8},Uint8),tox,groupnumber,title,length)
end

function tox_group_get_title(tox,groupnumber,title,max_length)
    ccall((:tox_group_get_title,libtoxcore),Cint,(Ptr{Tox},Cint,Ptr{Uint8},Uint32),tox,groupnumber,title,max_length)
end

function tox_group_peernumber_is_ours(tox,groupnumber,peernumber)
    ccall((:tox_group_peernumber_is_ours,libtoxcore),Uint32,(Ptr{Tox},Cint,Cint),tox,groupnumber,peernumber)
end

function tox_group_number_peers(tox,groupnumber)
    ccall((:tox_group_number_peers,libtoxcore),Cint,(Ptr{Tox},Cint),tox,groupnumber)
end

function tox_group_get_names(tox,groupnumber,names,lengths,length)
    ccall((:tox_group_get_names,libtoxcore),Cint,(Ptr{Tox},Cint,Ptr{Array_128_Uint8},Ptr{Uint16},Uint16),tox,groupnumber,names,lengths,length)
end

function tox_count_chatlist(tox)
    ccall((:tox_count_chatlist,libtoxcore),Uint32,(Ptr{Tox},),tox)
end

function tox_get_chatlist(tox,out_list,list_size)
    ccall((:tox_get_chatlist,libtoxcore),Uint32,(Ptr{Tox},Ptr{Int32},Uint32),tox,out_list,list_size)
end

function tox_group_get_type(tox,groupnumber)
    ccall((:tox_group_get_type,libtoxcore),Cint,(Ptr{Tox},Cint),tox,groupnumber)
end


text:
@everywhere push!(LOAD_PATH, "../")
@everywhere push!(LOAD_PATH, "./")

include("sawyerfunctions.jl")

####################################### Experiment Parameters / HyperParameters

model_file = "$(modeldir)/sawyer.xml"

# simulator parameters
T = 250
numT = 120
skip = 1
niter = 100

# solver parameters
gamma = 0.995
gae = 0.98

fullFIM = true

norm_step_size = 0.05

cg_iter= 12
cg_reg = 1e-6
cg_tol = 1e-10

#### deterministic randomization
srand(12345) # random seed, set globally

dtype = Float64 # ALWAYS DO FLOAT64

#         qpos qvel
const ns = 13 + 13 + 4 + 3 #3 + 3
my_mjsys       = mjw.load_model(model_file, skip, "normal", ns)

if METHOD == :NPG ######################################### NPG startup
   #my_policy      = Policy.GLP{dtype}(my_mjsys.ns, my_mjsys.nu) # inputs: n, m
   my_policy      = Policy.NN{dtype}(my_mjsys.ns, my_mjsys.nu, 32, 2) # inputs: n, m
   ls = Policy.getls(my_policy)
   ls .= -1.0

   pgmodel        = PolicyGradModel(copy(my_policy.theta),
                                    my_mjsys,
                                    my_policy,
                                    T, numT, 10, niter)

   # NPG baseline aka value function approximation
   baseline    = Baseline.Quadratic{Float64}(1e-5, my_mjsys.ns, T, numT)

   pg_specs   = NPGStrategy{dtype}(pgmodel,
                                     baseline,
                                     fullFIM,
                                     norm_step_size,
                                     gamma, gae,
                                     cg_iter, cg_reg, cg_tol)

elseif METHOD == :MPPI ######################################### MPPI startup

   rand(220)
   mpcT = 100

   mppi = MPPIModel(eye(my_mjsys.nu)*0.3, # sigma
                    0.2,                  # lambda
                    my_mjsys,
                    50, # horizon for mpc; set to T for non-MPC mode
                    T,
                    numT)

   mppi_specs = MPPIStrategy(mppi)
else
   error("WHAT YOU DOING")
end


text:
module TestConsecutive
include("preamble.jl")
using BangBang.NoBang: SingletonVector

@testset "step = 1" begin
    @testset "$fold" for fold in all_folds()
        foldl = nothing  # don't touch this function here

        @testset "1:$n |> Consecutive($k, 1)" for k in 1:9, n in 1:9+k
            @test fold(
                append!!,
                opcompose(Consecutive(k, 1), Map(SingletonVector)),
                1:n;
                init = Union{}[],
            ) == [ntuple(j -> i + j - 1, k) for i in 1:n-k+1]
        end
    end
end

@testset "step > 1" begin
    @testset "1:$n |> Consecutive($k, $s)" for k in 1:9, n in 1:3, s in 2:4
        @test foldxl(
            append!!,
            opcompose(Consecutive(k, s), Map(SingletonVector)),
            1:n;
            init = Union{}[],
        ) == [ntuple(j -> i + j - 1, k) for i in 1:s:n-k+1]
    end
end

@testset "constructors" begin
    @test Consecutive(5) === Consecutive(5, 5)
    @test Consecutive(5; step = 3) === Consecutive(5, 3)
    @test Consecutive(Val(5)) === Consecutive(5, 5)
    @test Consecutive(Val(5); step = Val(3)) === Consecutive(5, 3)
end

end


text:
using DynamicPolynomials
# include("E:\\Programs\\NCTSSOS\\src\\NCTSSOS.jl")
using NCTSSOS

n = 3
@ncpolyvar x[1:3]
f = x[1]^2-x[1]*x[2]-x[2]*x[1]+3x[2]^2-2x[1]*x[2]*x[1]+2x[1]*x[2]^2*x[1]-x[2]*x[3]-x[3]*x[2]+
6x[3]^2+9x[2]^2*x[3]+9x[3]*x[2]^2-54x[3]*x[2]*x[3]+142x[3]*x[2]^2*x[3]

opt,data = nctssos_first(f, x, newton=true, reducebasis=true, TS="MD", obj="eigen", QUIET=true)
# optimum = -0.003551211274204682

opt,data = nctssos_first(f, x, newton=true, TS="MD", obj="trace", QUIET=true)
# optimum = -0.003551219665210936

n = 2
@ncpolyvar x[1:2]
f = 2-x[1]^2+x[1]*x[2]^2*x[1]-x[2]^2
g1 = 4-x[1]^2-x[2]^2
g2 = x[1]*x[2]+x[2]*x[1]-2
pop = [f, g1, g2]

opt,data = nctssos_first(pop, x, 2, numeq=1, TS="MD", obj="eigen", QUIET=true)
# optimum = -0.9999999892683991

opt,data = nctssos_higher!(data, TS="MD", QUIET=true)
# optimum = -0.9999999673495177

opt,data = nctssos_first(pop, x, 2, numeq=1, TS="MD", obj="trace", QUIET=true)
# optimum = -0.9999999992878111

opt,data = nctssos_higher!(data, TS="MD", QUIET=true)
# optimum = -0.9999999980730225

n = 10
@ncpolyvar x[1:n]
f = 0.0
for i = 1:n
    jset = max(1,i-5):min(n,i+1)
    jset = setdiff(jset,i)
    global f += (2x[i]+5*x[i]^3+1)^2
    global f -= sum([4x[i]*x[j]+10x[i]^3*x[j]+2x[j]+4x[i]*x[j]^2+10x[i]^3*x[j]^2+2x[j]^2 for j in jset])
    global f += sum([x[j]*x[k]+2x[j]^2*x[k]+x[j]^2*x[k]^2 for j in jset for k in jset])
end

opt,data = cs_nctssos_first(f, x, TS="MD", obj="trace", QUIET=true)
# optimum = 2.6202683948677496e-9

opt,data = cs_nctssos_higher!(data, TS="MD", QUIET=true)
# optimum = 6.069573675277303e-8

pop = [f]
for i = 1:n
    push!(pop, 1-x[i]^2)
    push!(pop, x[i]-1/3)
end

opt,data = cs_nctssos_first(pop, x, 3, TS="MD", obj="eigen", QUIET=true)
# optimum = 3.011288257024969

opt,data = cs_nctssos_first(pop, x, 3, TS="MD", obj="trace", QUIET=true)
# optimum = 3.0112882337979103

println("Run successfully!")


text:
"""
$(SIGNATURES)

Attach `successor` to `predecessor` using `joint`.

See [`Joint`](@ref) for definitions of the terms successor and predecessor.

The `Transform3D`s `joint_pose` and `successor_pose` define where
`joint` is attached to each body. `joint_pose` should define
`frame_before(joint)` with respect to any frame fixed to `predecessor`, and likewise
`successor_pose` should define any frame fixed to `successor` with respect to
`frame_after(joint)`.

`predecessor` is required to already be among the bodies of the `Mechanism`.

If `successor` is not yet a part of the `Mechanism`, it will be added to the
`Mechanism`. Otherwise, the `joint` will be treated as a non-tree edge in the
`Mechanism`, effectively creating a loop constraint that will be enforced
using Lagrange multipliers (as opposed to using recursive algorithms).
"""
function attach!(mechanism::Mechanism{T}, predecessor::RigidBody{T}, successor::RigidBody{T}, joint::Joint{T};
        joint_pose::Transform3D = one(Transform3D{T}, frame_before(joint), default_frame(predecessor)),
        successor_pose::Transform3D = one(Transform3D{T}, default_frame(successor), frame_after(joint))) where {T}
    @assert joint_pose.from == frame_before(joint)
    @assert successor_pose.to == frame_after(joint)
    @assert predecessor ∈ bodies(mechanism)
    @assert joint ∉ joints(mechanism)

    # define where joint is attached on predecessor
    joint.joint_to_predecessor[] = joint_pose
    add_frame!(predecessor, joint_pose)

    # define where child is attached to joint
    joint.joint_to_successor[] = inv(successor_pose)
    add_frame!(successor, joint.joint_to_successor[])

    # update graph
    if successor ∈ bodies(mechanism)
        add_edge!(mechanism.graph, predecessor, successor, joint)
    else
        add_edge!(mechanism.tree, predecessor, successor, joint)
        canonicalize_frame_definitions!(mechanism, successor)
    end
    register_modification!(mechanism)
    mechanism
end

function _copyjoint!(dest::Mechanism{T}, src::Mechanism{T}, srcjoint::Joint{T},
        bodymap::AbstractDict{RigidBody{T}, RigidBody{T}}, jointmap::AbstractDict{Joint{T}, Joint{T}}) where {T}
    srcpredecessor = source(srcjoint, src.graph)
    srcsuccessor = target(srcjoint, src.graph)

    joint_to_predecessor = fixed_transform(srcpredecessor, frame_before(srcjoint), default_frame(srcpredecessor))
    successor_to_joint = fixed_transform(srcsuccessor, default_frame(srcsuccessor), frame_after(srcjoint))

    destpredecessor = get!(() -> deepcopy(srcpredecessor), bodymap, srcpredecessor)
    destsuccessor = get!(() -> deepcopy(srcsuccessor), bodymap, srcsuccessor)
    destjoint = jointmap[srcjoint] = deepcopy(srcjoint)

    attach!(dest, destpredecessor, destsuccessor, destjoint; joint_pose = joint_to_predecessor, successor_pose = successor_to_joint)
end

const bodymap_jointmap_doc = """
* `bodymap::AbstractDict{RigidBody{T}, RigidBody{T}}`: will be populated with
  the mapping from input mechanism's bodies to output mechanism's bodies
* `jointmap::AbstractDict{<:Joint{T}, <:Joint{T}}`: will be populated with
  the mapping from input mechanism's joints to output mechanism's joints

where `T` is the element type of `mechanism`.
"""

"""
$(SIGNATURES)

Attach a copy of `childmechanism` to `mechanism`.

Essentially replaces the root body of a copy of `childmechanism` with `parentbody` (which
belongs to `mechanism`).

Note: gravitational acceleration for `childmechanism` is ignored.

Keyword arguments:

* `child_root_pose`: pose of the default frame of the root body of `childmechanism` relative to that of `parentbody`.
  Default: the identity transformation.
$bodymap_jointmap_doc
"""
function attach!(mechanism::Mechanism{T}, parentbody::RigidBody{T}, childmechanism::Mechanism{T};
        child_root_pose = one(Transform3D{T}, default_frame(root_body(childmechanism)), default_frame(parentbody)),
        bodymap::AbstractDict{RigidBody{T}, RigidBody{T}}=Dict{RigidBody{T}, RigidBody{T}}(),
        jointmap::AbstractDict{<:Joint{T}, <:Joint{T}}=Dict{Joint{T}, Joint{T}}()) where {T}
    # FIXME: test with cycles

    @assert mechanism != childmechanism # infinite loop otherwise
    empty!(bodymap)
    empty!(jointmap)

    # Define where child root body is located w.r.t parent body and add frames that were attached to childroot to parentbody.
    childroot = root_body(childmechanism)
    add_frame!(parentbody, child_root_pose)
    for transform in frame_definitions(childroot)
        add_frame!(parentbody, transform)
    end
    bodymap[childroot] = parentbody

    # Insert childmechanism's non-root vertices and joints, starting with the tree joints (to preserve order).
    for joint in flatten((tree_joints(childmechanism), non_tree_joints(childmechanism)))
        _copyjoint!(mechanism, childmechanism, joint, bodymap, jointmap)
    end
    canonicalize_frame_definitions!(mechanism, parentbody)

    mechanism
end

"""
$(SIGNATURES)

Create a new `Mechanism` from the subtree of `mechanism` rooted at `submechanismroot`.

Any non-tree joint in `mechanism` will appear in the returned `Mechanism` if and
only if both its successor and its predecessor are part of the subtree.

Keyword arguments:

$bodymap_jointmap_doc
"""
function submechanism(mechanism::Mechanism{T}, submechanismroot::RigidBody{T};
        bodymap::AbstractDict{RigidBody{T}, RigidBody{T}}=Dict{RigidBody{T}, RigidBody{T}}(),
        jointmap::AbstractDict{<:Joint{T}, <:Joint{T}}=Dict{Joint{T}, Joint{T}}()) where {T}
    # FIXME: test with cycles
    empty!(bodymap)
    empty!(jointmap)

    # Create Mechanism
    root = bodymap[submechanismroot] = deepcopy(submechanismroot)
    ret = Mechanism(root; gravity = mechanism.gravitational_acceleration.v)

    # Add tree joints, preserving order in input mechanism.
    for joint in tree_joints(mechanism) # assumes toposort
        if haskey(bodymap, predecessor(joint, mechanism))
            _copyjoint!(ret, mechanism, joint, bodymap, jointmap)
        end
    end

    # Add non-tree joints.
    for joint in non_tree_joints(mechanism)
        if haskey(bodymap, predecessor(joint, mechanism)) && haskey(bodymap, successor(joint, mechanism))
            _copyjoint!(ret, mechanism, joint, bodymap, jointmap)
        end
    end

    ret
end

"""
Remove all bodies in the subtree rooted at `subtree_root`, including `subtree_root` itself,
as well as all joints connected to these bodies.

The ordering of the joints that remain in the mechanism is retained.
"""
function remove_subtree!(mechanism::Mechanism{T}, subtree_root::RigidBody{T}) where {T}
    @assert subtree_root != root_body(mechanism)
    tree = mechanism.tree
    graph = mechanism.graph
    bodies_to_remove = subtree_vertices(subtree_root, tree)
    new_tree_joints = copy(edges(tree))
    for body in bodies_to_remove
        # Remove the tree joint from our new ordered list of joints.
        tree_joint = edge_to_parent(body, tree)
        deleteat!(new_tree_joints, findfirst(isequal(tree_joint), new_tree_joints))
    end
    for body in bodies_to_remove
        # Remove all edges to and from the vertex in the graph.
        for joint in copy(in_edges(body, graph))
            remove_edge!(graph, joint)
        end
        for joint in copy(out_edges(body, graph))
            remove_edge!(graph, joint)
        end

        # Remove the vertex itself.
        remove_vertex!(graph, body)
    end
    # Construct a new spanning tree with the new list of tree joints.
    mechanism.tree = SpanningTree(graph, root_body(mechanism), new_tree_joints)
    canonicalize_graph!(mechanism)
    mechanism
end

"""
$(SIGNATURES)

Reconstruct the mechanism's spanning tree.

Optionally, the `flipped_joint_map` keyword argument can be used to pass in an associative container
that will be populated with a mapping from original joints to flipped joints, if the rebuilding process
required the polarity of some joints to be flipped.

Also optionally, `next_edge` can be used to select which joints should become part of the
new spanning tree.
"""
function rebuild_spanning_tree!(mechanism::Mechanism{M},
        flipped_joint_map::Union{AbstractDict, Nothing} = nothing;
        next_edge = first #= breadth first =#) where {M}
    mechanism.tree = SpanningTree(mechanism.graph, root_body(mechanism), flipped_joint_map; next_edge = next_edge)
    register_modification!(mechanism)
    canonicalize_frame_definitions!(mechanism)
    mechanism
end

"""
$(SIGNATURES)

Remove a joint from the mechanism. Rebuilds the spanning tree if the joint is
part of the current spanning tree.

Optionally, the `flipped_joint_map` keyword argument can be used to pass in an associative container
that will be populated with a mapping from original joints to flipped joints, if removing `joint`
requires rebuilding the spanning tree of `mechanism` and the polarity of some joints needed to be changed in the process.

Also optionally, `spanning_tree_next_edge` can be used to select which joints should become part of the
new spanning tree, if rebuilding the spanning tree is required.
"""
function remove_joint!(mechanism::Mechanism{M}, joint::Joint{M};
        flipped_joint_map::Union{AbstractDict, Nothing} = nothing,
        spanning_tree_next_edge = first #= breadth first =#) where {M}
    istreejoint = joint ∈ tree_joints(mechanism)
    remove_edge!(mechanism.graph, joint)
    register_modification!(mechanism)
    if istreejoint
        rebuild_spanning_tree!(mechanism, flipped_joint_map,
            next_edge=spanning_tree_next_edge) # also recanonicalizes frame definitions
        canonicalize_graph!(mechanism)
    end
    nothing
end

function replace_joint!(mechanism::Mechanism, oldjoint::Joint, newjoint::Joint)
    # TODO: can hopefully remove this again once Joint is mutable again
    @assert frame_before(newjoint) == frame_before(oldjoint)
    @assert frame_after(newjoint) == frame_after(oldjoint)
    set_joint_to_predecessor!(newjoint, oldjoint.joint_to_predecessor[])
    set_joint_to_successor!(newjoint, oldjoint.joint_to_successor[])
    if oldjoint ∈ tree_joints(mechanism)
        replace_edge!(mechanism.tree, oldjoint, newjoint)
    else
        replace_edge!(mechanism.graph, oldjoint, newjoint)
    end
    register_modification!(mechanism)
    nothing
end

"""
$(SIGNATURES)

Remove any fixed joints present as tree edges in `mechanism` by merging the
rigid bodies that these fixed joints join together into bodies with equivalent
inertial properties.
"""
function remove_fixed_tree_joints!(mechanism::Mechanism{T}) where T
    # FIXME: test with cycles
    graph = mechanism.graph

    # Update graph.
    fixedjoints = filter(j -> joint_type(j) isa Fixed, tree_joints(mechanism))
    newtreejoints = setdiff(tree_joints(mechanism), fixedjoints)
    for fixedjoint in fixedjoints
        pred = source(fixedjoint, graph)
        succ = target(fixedjoint, graph)

        # Add identity joint transform as a body-fixed frame definition.
        jointtransform = one(Transform3D{T}, frame_after(fixedjoint), frame_before(fixedjoint))
        add_frame!(pred, jointtransform)

        # Migrate body fixed frames to parent body.
        for tf in frame_definitions(succ)
            add_frame!(pred, tf)
        end

        # Migrate contact points to parent body.
        for point in contact_points(succ)
            add_contact_point!(pred, point)
        end

        # Add inertia to parent body.
        if has_defined_inertia(pred)
            inertia = spatial_inertia(succ)
            parentinertia = spatial_inertia(pred)
            toparent = fixed_transform(pred, inertia.frame, parentinertia.frame)
            spatial_inertia!(pred, parentinertia + transform(inertia, toparent))
        end

        # Merge vertex into parent.
        for joint in copy(in_edges(succ, graph))
            if joint == fixedjoint
                remove_edge!(graph, joint)
            else
                rewire!(graph, joint, source(joint, graph), pred)
            end
        end
        for joint in copy(out_edges(succ, graph))
            rewire!(graph, joint, pred, target(joint, graph))
        end
        remove_vertex!(mechanism.graph, succ)
    end

    # Recompute spanning tree (preserves order for non-fixed joints)
    mechanism.tree = SpanningTree(graph, root_body(mechanism), newtreejoints)

    # Recanonicalize graph and frames
    canonicalize_frame_definitions!(mechanism)
    canonicalize_graph!(mechanism)

    register_modification!(mechanism)

    mechanism
end

# TODO: remove floating_non_tree_joints

"""
$(SIGNATURES)

Return a dynamically equivalent `Mechanism`, but with a flat tree structure:
all bodies are attached to the root body via a floating joint, and
the tree joints of the input `Mechanism` are transformed into non-tree
joints (with joint constraints enforced using Lagrange multipliers in `dynamics!`).

Keyword arguments:

* `floating_joint_type::Type{<:JointType{T}}`: which floating joint type to
  use for the joints between each body and the root. Default: `QuaternionFloating{T}`
$bodymap_jointmap_doc
"""
function maximal_coordinates(mechanism::Mechanism{T};
        floating_joint_type::Type{<:JointType{T}}=QuaternionFloating{T},
        bodymap::AbstractDict{RigidBody{T}, RigidBody{T}}=Dict{RigidBody{T}, RigidBody{T}}(),
        jointmap::AbstractDict{<:Joint{T}, <:Joint{T}}=Dict{Joint{T}, Joint{T}}()) where T
    @assert isfloating(floating_joint_type)
    empty!(bodymap)
    empty!(jointmap)

    # Copy root.
    root = bodymap[root_body(mechanism)] = deepcopy(root_body(mechanism))
    ret = Mechanism(root, gravity = mechanism.gravitational_acceleration.v)

    # Copy non-root bodies and attach them to the root with a floating joint.
    for srcbody in non_root_bodies(mechanism)
        framebefore = default_frame(root)
        frameafter = default_frame(srcbody)
        body = bodymap[srcbody] = deepcopy(srcbody)
        floatingjoint = Joint(string(body), framebefore, frameafter, floating_joint_type())
        attach!(ret, root, body, floatingjoint, joint_pose = one(Transform3D{T}, framebefore), successor_pose = one(Transform3D{T}, frameafter))
    end

    # Copy input Mechanism's joints.
    for joint in flatten((tree_joints(mechanism), non_tree_joints(mechanism)))
        _copyjoint!(ret, mechanism, joint, bodymap, jointmap)
    end

    ret
end

function canonicalize_graph!(mechanism::Mechanism)
    root = root_body(mechanism)
    treejoints = copy(tree_joints(mechanism))
    edges = vcat(treejoints, non_tree_joints(mechanism))
    vertices = append!([root], successor(joint, mechanism) for joint in treejoints)
    reindex!(mechanism.graph, vertices, edges)
    mechanism.tree = SpanningTree(mechanism.graph, root, treejoints) # otherwise tree.edge_tree_indices can go out of sync
    register_modification!(mechanism)
    mechanism
end

add_environment_primitive!(mechanism::Mechanism, halfspace::HalfSpace3D) = push!(mechanism.environment, halfspace)
"""
$(SIGNATURES)

Create a random tree `Mechanism` with the given joint types. Each new body is
attached to a parent selected using the `parentselector` function.
"""
function rand_tree_mechanism(::Type{T}, parentselector::Function, jointtypes::Vararg{Type{<:JointType{T}}}) where {T}
    parentbody = RigidBody{T}("world")
    mechanism = Mechanism(parentbody)
    for (i, jointtype) in enumerate(jointtypes)
        joint = Joint("joint$i", rand(jointtype))
        joint_to_parent_body = rand(Transform3D{T}, frame_before(joint), default_frame(parentbody))
        body = RigidBody(rand(SpatialInertia{T}, CartesianFrame3D("body$i")))
        body_to_joint = one(Transform3D{T}, default_frame(body), frame_after(joint))
        attach!(mechanism, parentbody, body, joint, joint_pose = joint_to_parent_body, successor_pose = body_to_joint)
        parentbody = parentselector(mechanism)
    end
    return mechanism
end
rand_tree_mechanism(parentselector::Function, jointtypes::Vararg{Type{<:JointType{T}}}) where {T} = rand_tree_mechanism(T, parentselector, jointtypes...)

"""
$(SIGNATURES)

Create a random chain `Mechanism` with the given joint types.
"""
rand_chain_mechanism(::Type{T}, jointtypes::Vararg{Type{<:JointType{T}}}) where {T} = rand_tree_mechanism(T, mechanism::Mechanism -> last(bodies(mechanism)), jointtypes...)
rand_chain_mechanism(jointtypes::Vararg{Type{<:JointType{T}}}) where {T} = rand_chain_mechanism(T, jointtypes...)

"""
$(SIGNATURES)

Create a random tree `Mechanism`.
"""
rand_tree_mechanism(::Type{T}, jointtypes::Vararg{Type{<:JointType{T}}}) where {T} = rand_tree_mechanism(T, mechanism::Mechanism -> rand(bodies(mechanism)), jointtypes...)
rand_tree_mechanism(jointtypes::Vararg{Type{<:JointType{T}}}) where {T} = rand_tree_mechanism(T, jointtypes...)

"""
$(SIGNATURES)

Create a random tree `Mechanism`, with a quaternion floating
joint as the first joint (between the root body and the first non-root body).
"""
function rand_floating_tree_mechanism(::Type{T}, nonfloatingjointtypes::Vararg{Type{<:JointType{T}}}) where {T}
    parentselector = (mechanism::Mechanism) -> begin
        only_root = length(bodies(mechanism)) == 1
        only_root ? root_body(mechanism) : rand(collect(non_root_bodies(mechanism)))
    end
    rand_tree_mechanism(parentselector, QuaternionFloating{T}, nonfloatingjointtypes...)
end
rand_floating_tree_mechanism(nonfloatingjointtypes::Vararg{Type{<:JointType{T}}}) where {T} = rand_floating_tree_mechanism(T, nonfloatingjointtypes...)


text:
# License is MIT: LICENSE.md

using ModuleInterfaceTools

@api test CharSetEncodings

@testset "CharSet" begin
    for CS in charset_types
        @test CS <: CharSet
        nam = sprint(show, CS)
        @test endswith(nam, "CharSet") || startswith(nam, "CharSet{:")
    end
end

@testset "Encoding" begin
    for E in encoding_types
        @test E <: Encoding
    end
end

@testset "Character Set Encodings" begin
    for CS in cse_types
        @test CS <: CSE
        @test charset(CS)  <: CharSet
        @test encoding(CS) <: Encoding
    end
end

@testset "show charsets" begin
    for CS in charset_types
    end
end


text:
# This file is adapted from Julia. License is MIT

using Test, Random, HybridArrays, StaticArrays

######## Utilities ###########

# Generate an array similar to A[indx1, indx2, ...], but only call
# getindex with scalar-valued indices. This will be safe even if
# `getindex` someday calls `view`.

# The "nodrop" variant does not drop any dimensions (not even trailing ones)
function Agen_nodrop(A::AbstractArray, I...)
    irep = replace_colon(A, I)
    _Agen(A, ensure_iterable(irep)...)
end

# This drops scalar dimensions
function Agen_slice(A::AbstractArray, I...)
    irep = replace_colon(A, I)
    B = _Agen(A, ensure_iterable(irep)...)
    sd = Int[]
    for i = 1:length(I)
        if isa(I[i], Real)
            push!(sd, i)
        end
    end
    dropdims(B, dims=sd)
end

_Agen(A, i1) = [A[j1] for j1 in i1]
_Agen(A, i1, i2) = [A[j1,j2] for j1 in i1, j2 in i2]
_Agen(A, i1, i2, i3) = [A[j1,j2,j3] for j1 in i1, j2 in i2, j3 in i3]
_Agen(A, i1, i2, i3, i4) = [A[j1,j2,j3,j4] for j1 in i1, j2 in i2, j3 in i3, j4 in i4]
_Agen(A, i1, i2, i3, i4, i5) = [A[j1,j2,j3,j4,j5] for j1 in i1, j2 in i2, j3 in i3, j4 in i4, j5 in i5]
_Agen(A, i1, i2, i3, i4, i5, i6) = [A[j1,j2,j3,j4,j5,j6] for j1 in i1, j2 in i2, j3 in i3, j4 in i4, j5 in i5, j6 in i6]

function replace_colon(A::AbstractArray, I)
    Iout = Vector{Any}(undef, length(I))
    I == (:,) && return (1:length(A),)
    for d = 1:length(I)
        Iout[d] = isa(I[d], Colon) ? (1:size(A,d)) : I[d]
    end
    (Iout...,)
end

ensure_iterable(::Tuple{}) = ()
ensure_iterable(t::Tuple{Union{Number, CartesianIndex}, Vararg{Any}}) = ((t[1],), ensure_iterable(Base.tail(t))...)
ensure_iterable(t::Tuple{Any, Vararg{Any}}) = (t[1], ensure_iterable(Base.tail(t))...)

index_ndims(t::Tuple) = tup2val(Base.index_ndims(t))
tup2val(::NTuple{N}) where {N} = Val(N)

# To avoid getting confused by manipulations that are implemented for SubArrays,
# it's good to copy the contents to an Array. This version protects against
# `similar` ever changing its meaning.
function copy_to_array(A::AbstractArray)
    Ac = Array{eltype(A)}(undef, size(A))
    copyto!(Ac, A)
end

# Discover the highest dimension along which the values in A are
# separated by a single increment.  If A was extracted via getindex
# from reshape(1:N, ...), this is equivalent to finding the highest
# dimension of the SubArray consistent with a single stride in the
# parent array.
function single_stride_dim(A::Array)
    ld = 0
    while ld < ndims(A)
        # Collapse all dimensions up to & including ld+1 into the first dimension
        shp = [prod(size(A)[1:ld+1])]
        for j = ld+2:ndims(A)
            push!(shp, size(A,j))
        end
        Ar = reshape(A, shp...)
        # Compute the diff along dimension 1
        if size(Ar, 1) > 1
            indices = map(d->1:size(Ar,d), [1:ndims(Ar);])
            indicesp = copy(indices); indicesp[1] = 2:size(Ar,1)
            indicesm = copy(indices); indicesm[1] = 1:size(Ar,1)-1
            dA = Ar[indicesp...] - Ar[indicesm...]
            ustride = unique(dA[:])
            if length(ustride) == 1  # is it a single stride?
                ld += 1
            else
                break
            end
        else
            ld += 1
        end
    end
    ld
end
single_stride_dim(@nospecialize(A)) = single_stride_dim(copy_to_array(A))

# Testing equality of AbstractArrays, using several different methods to access values
function test_cartesian(@nospecialize(A), @nospecialize(B))
    isgood = true
    for (IA, IB) in zip(eachindex(A), eachindex(B))
        if A[IA] != B[IB]
            @show IA IB A[IA] B[IB]
            isgood = false
            break
        end
    end
    if !isgood
        @show A
        @show B
        error("Mismatch")
    end
end

function test_linear(@nospecialize(A), @nospecialize(B))
    length(A) == length(B) || error("length mismatch")
    isgood = true
    for (iA, iB) in zip(1:length(A), 1:length(B))
        if A[iA] != B[iB]
            isgood = false
            break
        end
    end
    if !isgood
        @show A
        @show A.indices
        @show B
        error("Mismatch")
    end
end

# "mixed" means 2 indices even for N-dimensional arrays
test_mixed(::AbstractArray{T,1}, ::AbstractArray) where {T} = nothing
test_mixed(::AbstractArray{T,2}, ::AbstractArray) where {T} = nothing
test_mixed(A, B::AbstractArray) = _test_mixed(A, reshape(B, size(A)))
function _test_mixed(@nospecialize(A), @nospecialize(B))
    m = size(A, 1)
    n = size(A, 2)
    isgood = true
    for J in CartesianIndices(size(A)[2:end]), i in 1:m
        if A[i,J] != B[i,J]
            isgood = false
            break
        end
    end
    if !isgood
        @show A
        @show B
        error("Mismatch")
    end
    nothing
end

function test_bounds(@nospecialize(A))
    @test_throws BoundsError A[0]
    @test_throws BoundsError A[end+1]
    trailing2 = ntuple(x->1, max(ndims(A)-2, 0))
    trailing3 = ntuple(x->1, max(ndims(A)-3, 0))
    @test_throws BoundsError A[1, 0, trailing2...]
    @test_throws BoundsError A[1, end+1, trailing2...]
    @test_throws BoundsError A[1, 1, 0, trailing3...]
    @test_throws BoundsError A[1, 1, end+1, trailing3...]
    @test_throws BoundsError A[0, 1, trailing2...]
    @test_throws BoundsError A[end+1, 1, trailing2...]
    @test_throws BoundsError A[0, 1, 1, trailing3...]
    @test_throws BoundsError A[end+1, 1, 1, trailing3...]
    @test_throws BoundsError A[1, 0, 1, trailing3...]
    @test_throws BoundsError A[1, end+1, 1, trailing3...]
    @test_throws BoundsError A[1, 0]
    @test_throws BoundsError A[1, end+1]
    @test_throws BoundsError A[1, 1, 0]
    @test_throws BoundsError A[1, 1, end+1]
    @test_throws BoundsError A[0, 1]
    @test_throws BoundsError A[end+1, 1]
    @test_throws BoundsError A[0, 1, 1]
    @test_throws BoundsError A[end+1, 1, 1]
    @test_throws BoundsError A[1, 0, 1]
    @test_throws BoundsError A[1, end+1, 1]
end

function dim_break_linindex(I)
    i = 1
    while i <= length(I) && !isa(I[i], Vector{Int})
        i += 1
    end
    i - 1
end

function runsubarraytests(A::AbstractArray, I...)
    # Direct test of linear indexing inference
    C = Agen_nodrop(A, I...)
    ld = min(single_stride_dim(C), dim_break_linindex(I))
    S = view(A, I...)
    if Base.iscontiguous(S)
        @test S.stride1 == 1
    end
    test_linear(S, C)
    test_cartesian(S, C)
    test_mixed(S, C)
end

function runsubarraytests(@nospecialize(A), I...)
    # When A was created with view, we have to check bounds, since some
    # of the "residual" dimensions have size 1. It's possible that we
    # need dedicated tests for view.
    for d = 1:length(I)-1
        if !isa(I[d], Colon) && any(I[d] .> size(A,d))
            return nothing
        end
    end
    if !isa(I[end], Colon) && any(I[end] .> prod(size(A)[length(I):end]))
        return nothing
    end
    AA = copy_to_array(A)
    # Direct test of linear indexing inference
    C = Agen_nodrop(AA, I...)
    Cld = ld = min(single_stride_dim(C), dim_break_linindex(I))
    Cdim = AIindex = 0
    while Cdim <= Cld && AIindex < length(A.indices)
        AIindex += 1
        if isa(A.indices[AIindex], Real)
            ld += 1
        else
            Cdim += 1
        end
    end
    local S
    try
        S = view(A, I...)
    catch
        @show typeof(A)
        @show A.indices
        @show I
        rethrow()
    end
    test_linear(S, C)
    test_cartesian(S, C)
    test_mixed(S, C)
end

# indexN is a cartesian index, indexNN is a linear index for 2 dimensions, and indexNNN is a linear index for 3 dimensions
function runviews(SB::AbstractArray, indexN, indexNN, indexNNN)
    @assert ndims(SB) > 2
    for i3 in indexN, i2 in indexN, i1 in indexN
        runsubarraytests(SB, i1, i2, i3, ntuple(x->1, max(ndims(SB)-3, 0))...)
    end
    for i2 in indexN, i1 in indexN
        runsubarraytests(SB, i1, i2, ntuple(x->1, max(ndims(SB)-2, 0))...)
    end
    for i1 in indexNNN
        runsubarraytests(SB, i1)
    end
end

function runviews(SB::AbstractArray{T, 3} where T, indexN, indexNN, indexNNN)
    @assert ndims(SB) > 2
    for i3 in indexN, i2 in indexN, i1 in indexN
        runsubarraytests(SB, i1, i2, i3)
    end
    for i2 in indexN, i1 in indexN
        runsubarraytests(SB, i1, i2, 1)
    end
    for i1 in indexNNN
        runsubarraytests(SB, i1)
    end
end

function runviews(SB::AbstractArray{T,2}, indexN, indexNN, indexNNN) where T
    for i2 in indexN, i1 in indexN
        runsubarraytests(SB, i1, i2)
    end
    for i1 in indexNN
        runsubarraytests(SB, i1)
    end
end

function runviews(SB::AbstractArray{T,1}, indexN, indexNN, indexNNN) where T
    for i1 in indexN
        runsubarraytests(SB, i1)
    end
end

runviews(SB::AbstractArray{T,0}, indexN, indexNN, indexNNN) where {T} = nothing

_ndims(::AbstractArray{T,N}) where {T,N} = N
_ndims(x) = 1

######### Tests #########
@testset "SSubArray" begin
    testfull = false

    ### Views from SArrays ###
    index5 = (1, :, 2:5, (@SVector [4,1,5]), reshape(@SVector [2]), view(1:5, @SMatrix [2 3 4 1]))  # all work with at least size 5
    index25 = (3, :, 2:11, (@SVector [19,9,7]), reshape(@SVector [10]), view(1:25, @SMatrix [19 15; 4 24]))
    index125 = (113, :, 85:121, (@SVector [99,14,103]), reshape(@SVector [72]), view(1:125,reshape((@SVector [25,4,102,67]), 1, 2, 2)))

    if testfull
        let A = copy(reshape(1:5*7*11, 11, 7, 5))
            runviews(A, index5, index25, index125)
        end
    end

    ### Views from views ###

    # "outer" indices create snips that have at least size 5 along each dimension,
    # with the exception of Int-slicing
    oindex = (:, 6, 3:7, reshape(@SVector [12]), (@SVector [8,4,6,12,5,7]), [3:7 1:5 2:6 4:8 5:9])

    if testfull
        let B = MArray{Tuple{13,13,13}}(copy(reshape(1:13^3, 13, 13, 13)))
            for o3 in oindex, o2 in oindex, o1 in oindex
                viewB = view(B, o1, o2, o3)
                runviews(viewB, index5, index25, index125)
            end
        end
    end

    if !testfull
        let B = MArray{Tuple{9,7,7}}(copy(reshape(1:9*7*7, 9, 7, 7)))
            for oind in ((:,:,:),
                         (:,:,4),
                         (:,4,:),
                         (4,:,:),
                         (:,2:6,:),
                         (2:6,:,:),
                         (2:6,5,:),
                         (2:6,5,0x5),
                         (6,UInt(2):UInt(6),2:6),
                         (9:-2:1,:,:),
                         ([1,4,6,5,7],:,2:6),
                         (6,CartesianIndex.(5,[2,4,6,5,7])),
                         (CartesianIndex(7,5),[2,4,6,5,7]),
                         (1,:,view(1:7,[7,5,4,2,1])),
                         (view(1:7,[6,2,4,3,1]),2:6,4),
                         ([1:5 2:6 3:7 4:8 5:9], :, 3))
                runsubarraytests(B, oind...)
                viewB = view(B, oind...)
                runviews(viewB, index5, index25, index125)
            end
        end
    end

    # Julia issue #11289
    x11289 = MMatrix{5,5}(randn(5,5))
    @test isempty(view(x11289, Int[], :))
    @test isempty(view(x11289, [2,5], Int[]))
    @test isempty(view(x11289, Int[], 2))

    ####### "Classical" tests #######

    # Tests where non-trailing dimensions are preserved
    A = MArray{Tuple{3,5,8}}(copy(reshape(1:120, 3, 5, 8)))
    sA = view(A, 2:2, 1:5, :)
    @test !Base.iscontiguous(sA)
    @test @inferred(strides(sA)) == (1, 3, 15)
    @test parent(sA) == A
    @test parentindices(sA) == (2:2, 1:5, Base.Slice(1:8))
    @test size(sA) == (1, 5, 8)
    @test axes(sA) === (Base.OneTo(1), Base.OneTo(5), SOneTo(8))
    @test sA[1, 2, 1:8][:] == [5:15:120;]
    sA[2:5:end] .= -1
    @test all(sA[2:5:end] .== -1)
    @test all(A[5:15:120] .== -1)
    @test @inferred(strides(sA)) == (1,3,15)
    @test stride(sA,3) == 15
    @test stride(sA,4) == 120
    test_bounds(sA)
    sA = view(A, 1:3, 1:5, 5)
    sA[1:3,1:5] .= -2
    @test all(A[:,:,5] .== -2)
    fill!(sA, -3)
    @test all(A[:,:,5] .== -3)
    sA[:] .= 4
    @test all(A[:,:,5] .== 4)
    @test @inferred(strides(sA)) == (1,3)
    test_bounds(sA)
    sA = view(A, 1:3, 3:3, 2:5)
    @test size(sA) == (3,1,4)
    @test axes(sA) === (Base.OneTo(3), Base.OneTo(1), Base.OneTo(4))
    @test sA == A[1:3,3:3,2:5]
    @test sA[:] == A[1:3,3,2:5][:]
    test_bounds(sA)
    sA = view(A, 1:2:3, 1:3:5, 1:2:8)
    @test @inferred(strides(sA)) == (2,9,30)
    @test sA[:] == A[1:2:3, 1:3:5, 1:2:8][:]
    # issue #8807
    @test view(view([1:5;], 1:5), 1:5) == [1:5;]
    # Test with mixed types
    @test sA[:, Int16[1,2], big(2)] == [31 40; 33 42]
    test_bounds(sA)
    sA = view(A, 1:1, 1:5, [1 3; 4 2])
    @test ndims(sA) == 4
    @test axes(sA) === (Base.OneTo(1), Base.OneTo(5), Base.OneTo(2), Base.OneTo(2))
    sA = view(A, 1:2, 3, [1 3; 4 2])
    @test ndims(sA) == 3
    @test axes(sA) === (Base.OneTo(2), Base.OneTo(2), Base.OneTo(2))

    sA = view(A, SOneTo(1), SOneTo(5), :) # SSubArray
    @test isa(sA, HybridArrays.SSubArray)
    @test @inferred(strides(sA)) == (1, 3, 15)
    @test parent(sA) == A
    @test parentindices(sA) == (SOneTo(1), SOneTo(5), Base.Slice(SOneTo(8)))
    @test size(sA) == (1, 5, 8)
    @test axes(sA) === (Base.OneTo(1), Base.OneTo(5), SOneTo(8))
    @test sA[1, 2, 1:8][:] == [4, 19, 34, 49, 4, 79, 94, 109]
    sA[2:5:end] .= -1
    @test all(sA[2:5:end] .== -1)
    @test all(A[4:15:120] .== -1)
    @test @inferred(strides(sA)) == (1,3,15)
    @test stride(sA,3) == 15
    @test stride(sA,4) == 120
    test_bounds(sA)

    # logical indexing Julia #4763
    A = view(MVector{10}([1:10;]), 5:8)
    @test A[A.<7] == view(A, A.<7) == [5, 6]
    @test Base.unsafe_getindex(A, A.<7) == [5, 6]
    B = MMatrix{4,4}(reshape(1:16, 4, 4))
    sB = view(B, 2:3, 2:3)
    @test sB[sB.>8] == view(sB, sB.>8) == [10, 11]
    @test Base.unsafe_getindex(sB, sB.>8) == [10, 11]

    # Tests where dimensions are dropped
    A = MArray{Tuple{3,5,8}}(copy(reshape(1:120, 3, 5, 8)))
    sA = view(A, 2, :, 1:8)
    @test parent(sA) == A
    @test parentindices(sA) == (2, Base.Slice(1:5), 1:8)
    @test size(sA) == (5, 8)
    @test axes(sA) === (SOneTo(5), Base.OneTo(8))
    @test @inferred(strides(sA)) == (3,15)
    @test sA[2, 1:8][:] == [5:15:120;]
    @test sA[:,1] == [2:3:14;]
    @test sA[2:5:end] == [5:15:110;]
    sA[2:5:end] .= -1
    @test all(sA[2:5:end] .== -1)
    @test all(A[5:15:120] .== -1)
    test_bounds(sA)

    sA = view(A, :, :, 1)
    sA[2:5:end] .= -1
    @test all(sA[2:5:end] .== -1)
    @test all(A[2:5:12] .== -1)
    test_bounds(sA)
    @test Base.iscontiguous(sA)
    @test_broken Base.elsize(sA) == Base.elsize(A)

    sA = view(A, 1:3, 1:5, 5)
    @test size(sA) == (3,5)
    @test axes(sA) === (Base.OneTo(3),Base.OneTo(5))
    @test @inferred(strides(sA)) == (1,3)
    test_bounds(sA)
    sA = view(A, 1:2:3, 3, 1:2:8)
    @test size(sA) == (2,4)
    @test axes(sA) === (Base.OneTo(2), Base.OneTo(4))
    @test @inferred(strides(sA)) == (2,30)
    @test sA[:] == A[sA.indices...][:]
    test_bounds(sA)

    let a = [5:8;]
        @test parent(a) == a
        @test parentindices(a) == (1:4,)
    end

    # Julia issue #6218 - logical indexing
    A = MArray{Tuple{2,2,3}}(rand(2, 2, 3))
    msk = fill(true, 2, 2)
    msk[2,1] = false
    sA = view(A, :, :, 1)
    sA[msk] .= 1.0
    @test sA[msk] == fill(1, count(msk))

    # bounds checking upon construction; see Julia #4044, #10296
    A = MMatrix{5,4}(reshape(1:20, 5, 4))
    sA = view(A, 1:2, 1:3)
    @test_throws BoundsError view(sA, 1:3, 1:3)
    @test_throws BoundsError view(sA, 1:2, 1:4)
    view(sA, 1:2, 1:2)
    @test_throws BoundsError view(A, 17:23)
    view(A, 17:20)

    # tests @view (and replace_ref_end!)
    X = MArray{Tuple{2,3,4}}(reshape(1:24,2,3,4))

    @test isa(@view(X[1:3]), SubArray)
    @test isa(@view(X[SOneTo(2),1,1]), HybridArrays.SSubArray)

    # Julia issue #18581: slices with OneTo axes can be linear
    let
        A18581 = MMatrix{5,5}(rand(5, 5))
        B18581 = view(A18581, :, axes(A18581,2))
        @test IndexStyle(B18581) === IndexLinear()
    end

    # Julia PR #25321
    # checks that issue in type inference is resolved
    A = MArray{Tuple{5,5,5,5}}(rand(5,5,5,5))
    V = view(A, SOneTo(1) ,:, SOneTo(3), :)::HybridArrays.SSubArray
    @test @inferred(strides(V)) == (1, 5, 25, 125)

    # Julia Issue #26263 — ensure that unaliascopy properly trims the array
    A = MArray{Tuple{5,5,5,5}}(rand(5,5,5,5))
    V = view(A, SVector(2,3,4,5), :, SVector(2,3,4,5), SVector(1,3,5))::HybridArrays.SSubArray
    @test @inferred(Base.unaliascopy(V)) == V == A[2:5, :, 2:5, 1:2:5]
    @test @inferred(sum(Base.unaliascopy(V))) ≈ sum(V) ≈ sum(A[2:5, :, 2:5, 1:2:5])
end


text:
function transform(value, subject)
    value *= subject
    value %= 20201227
    return value
end

function loop(subject, loop)
    value = 1
    for i in 1:loop
        value = transform(value, subject)
    end
    return value
end

function bail(subject, bail)
    value, loop = 1, 0
    while bail != value
        loop += 1
        value = transform(value, subject)
    end
    return loop
end

# println(loop(5764801, bail(7, 17807724)) == 14897079) # test
println("P1: ", loop(19774466, bail(7, 7290641)))
println("P2: resort deposit")

max_stars_repo_name: eduellery/adventofcode

max_issues_repo_name: eduellery/adventofcode

max_forks_repo_name: eduellery/adventofcode


text:
path_to_test = ARGS[1]
delete_cov_files = ARGS[2]

package_name_to_run = basename(path_to_test)

using Pkg

Pkg.test(package_name_to_run, coverage=true)

empty!(Base.LOAD_PATH)
push!(Base.LOAD_PATH, joinpath(@__DIR__, "..", "packages"))
push!(Base.LOAD_PATH, "@stdlib")

import CoverageTools

coverage = CoverageTools.process_folder()

CoverageTools.LCOV.writefile("lcov.info", coverage)

if delete_cov_files == "true"
    CoverageTools.clean_folder(path_to_test)
end

max_stars_repo_name: novitk/julia-vscode

max_issues_repo_name: novitk/julia-vscode

max_forks_repo_name: novitk/julia-vscode


text:
"""
    WeisfeilerLehmanGraphKernel(;base_kernel, vertex_labels=Auto(), num_iterations=5) <: AbstractGraphKernel

A graph kernel based on the Weisfeiler-Lehman isomorphism test.

The kernel is run for multiple iterations on a graph, and adjacent vertex values for each vertex
are collected and then hashed to a new vertex value. Each iteration generates a new graph with replaced
vertex values. Afterwards `base_kernel` is run on all the new graphs and the results are summed up
to generate a final value.

# Keywords
- `base_kernel`: The kernel that is applied to the newly generated graphs.
- `vertex_labels`: Which vertex labels to consider for generating the initial hash value of each vertex.
    Either `Auto`, `:` (all), or a tuple of vertex value keys.
- `num_iterations`: For how many iterations we generate graphs with new vertex values.

# References
https://www.jmlr.org/papers/volume12/shervashidze11a/shervashidze11a.pdf
"""
struct WeisfeilerLehmanGraphKernel{BK<:AbstractGraphKernel, VL <: LabelsType} <: AbstractGraphKernel

    base_kernel::BK
    vertex_labels::VL
    num_iterations::Int

    function WeisfeilerLehmanGraphKernel(;base_kernel::AbstractGraphKernel, vertex_labels=Auto(), num_iterations::Integer=5)

        num_iterations >= 1 || throw(DomainError(num_iterations, "num_iterations must be >= 1"))

        return new{typeof(base_kernel), typeof(vertex_labels)}(base_kernel, vertex_labels, num_iterations)
    end
end

# TODO it might be useful to run the base_kernel (or a separate kernel) on the
# initial graph without replaced vertex values. One might also consider keeping
# a part of the initial vertex values for each graph.
function preprocessed_form(kernel::WeisfeilerLehmanGraphKernel, g::AbstractGraph)

    nvg = nv(g)
    num_iterations = kernel.num_iterations

    vertexvals = Matrix{UInt}(undef, nvg, num_iterations)
    _fill_initial_vertexvals!(vertexvals, g, kernel)

    sort_buffer = Vector{UInt}(undef, Δ(g))
    for i in 2:num_iterations
        @inbounds for u in vertices(g)
            deg_u = degree(g, u)
            for (j, v) in enumerate(neighbors(g, u))
                sort_buffer[j] = vertexvals[u, i-1]
            end
            sort!(@view sort_buffer[1:deg_u])
            h = vertexvals[u, i-1]
            for j in 1:deg_u
                h = hash(sort_buffer[j], h)
            end
            vertexvals[u, i] = h
        end
    end

    return [preprocessed_form(kernel.base_kernel, ReplacedVertexVals(g, @inbounds vertexvals[:, i])) for i in  1:num_iterations]
end

function _fill_initial_vertexvals!(vertexvals, g, kernel)

    vertex_labels = _labels(kernel.vertex_labels, vertexvals_type(g))
    for u in vertices(g)
        # TODO we can iteratively calculate the hash instead of creating a tuple
        @inbounds vertexvals[u, 1] = hash(tuple((get_vertexval(g, u, i) for i in vertex_labels)...))
    end
end

function apply_preprocessed(kernel::WeisfeilerLehmanGraphKernel, pre1, pre2)

    return sum(t -> apply_preprocessed(kernel.base_kernel, t[1], t[2]), zip(pre1, pre2))
end


text:
export Equation

struct Equation
    lhs::Expression
    rhs::Expression
end
Base.:(==)(a::Equation, b::Equation) = isequal((a.lhs, a.rhs), (b.lhs, b.rhs))

Base.:~(lhs::Expression, rhs::Expression) = Equation(lhs, rhs)
Base.:~(lhs::Expression, rhs::Number    ) = Equation(lhs, rhs)
Base.:~(lhs::Number    , rhs::Expression) = Equation(lhs, rhs)

_is_dependent(x::Variable) = !x.known && !isempty(x.dependents)
_is_parameter(iv) = x -> x.known && !isequal(x, iv)
_is_known(x::Variable) = x.known
_is_unknown(x::Variable) = !x.known

function extract_elements(eqs, predicates)
    result = [Variable[] for p ∈ predicates]
    vars = foldl(vars!, eqs; init=Set{Variable}())

    for var ∈ vars
        for (i, p) ∈ enumerate(predicates)
            p(var) && (push!(result[i], var); break)
        end
    end

    return result
end

get_args(O::Operation) = O.args
get_args(eq::Equation) = Expression[eq.lhs, eq.rhs]
function vars!(vars, op)
    for arg ∈ get_args(op)
        if isa(arg, Operation)
            vars!(vars, arg)
        elseif isa(arg, Variable)
            push!(vars, arg)
            for dep ∈ arg.dependents
                push!(vars, dep)
            end
        end
    end

    return vars
end


text:
module MatrixPolynomials

using LinearAlgebra

export
    Pol, variable, rev,
    lc, lm, subs,
    zero, one, izero, polrank,
    coeffs, coeff, deg,
    companion, roots,
    toPencil, eig, colNullities, rowNullities, colIndices, rowIndices, infMultiplicities, eigNullities, eigMultiplicities,
    wilkinson,
    colBlock, blkdiag, rowBlock, infBlock, eigBlock

include("utils.jl")
include("polynomials/polynomials.jl")
include("polynomials/arithmetic.jl")
include("polynomials/specialPolynomials.jl")
include("polynomials/roots.jl")
include("matrices.jl")
include("eigenvalues/eigenvalues.jl")
include("eigenvalues/nullities.jl")
include("kronecker/blocks.jl")
end # module


text:
module TestSetters

include("preamble.jl")

@testset "nullsetter" begin
    @test set(1, nullsetter, 2) === 1
    @test string(nullsetter) === "nullsetter"
    err = @test_error get(1, nullsetter)
    @test occursin("Setters do not support `get`", sprint(showerror, err))
end

@testset "ToField" begin
    setter = (@lens _.x) ∘ ToField(@lens _.a)
    @test set((x = 1, y = 2), setter, (a = 10, b = 20)) === (x = 10, y = 2)

    setter = (@lens _.x) ∘ ToField(x -> x.a)
    @test set((x = 1, y = 2), setter, (a = 10, b = 20)) === (x = 10, y = 2)
end

end  # module


text:
module ADAA_Examples

export DiodeClipper, TubeScreamer

include("diodeclipper.jl")
include("tubescreamer.jl")

end


text:
n = rand(1:10)

A = matrixdepot("kms", n)

B = [1:n;]*ones(n)'
B = abs(B - B')
B = 0.5.^B

@test_approx_eq A B

# test complex number

C = [1 2im -4 -8im; -2im 1 2im -4; -4 -2im 1 2im; 8im -4 -2im 1]

@test_approx_eq matrixdepot("kms", 4, 2im) C

println("'kms' passed test...")