text:
import Adapt
import .CUDA

struct OneHotArray{T<:Integer, L, N, var"N+1", I<:Union{T, AbstractArray{T, N}}} <: AbstractArray{Bool, var"N+1"}
  indices::I
end
OneHotArray{T, L, N, I}(indices) where {T, L, N, I} = OneHotArray{T, L, N, N+1, I}(indices)
OneHotArray(indices::T, L::Integer) where {T<:Integer} = OneHotArray{T, L, 0, 1, T}(indices)
OneHotArray(indices::I, L::Integer) where {T, N, I<:AbstractArray{T, N}} = OneHotArray{T, L, N, N+1, I}(indices)

_indices(x::OneHotArray) = x.indices
_indices(x::Base.ReshapedArray{<: Any, <: Any, <: OneHotArray}) =
  reshape(parent(x).indices, x.dims[2:end])

const OneHotVector{T, L} = OneHotArray{T, L, 0, 1, T}
const OneHotMatrix{T, L, I} = OneHotArray{T, L, 1, 2, I}

OneHotVector(idx, L) = OneHotArray(idx, L)
OneHotMatrix(indices, L) = OneHotArray(indices, L)

function _show_elements(x::OneHotArray)
  xbool = convert(Array{Bool}, cpu(x))
  xrepr = join(split(repr(MIME("text/plain"), xbool; context= :limit => true), "\n")[2:end], "\n")

  return xrepr
end

function Base.show(io::IO, ::MIME"text/plain", x::OneHotArray{<:Any, L, <:Any, N, I}) where {L, N, I}
  join(io, string.(size(x)), "×")
  print(io, " Flux.OneHotArray{")
  join(io, string.([L, N, I]), ",")
  println(io, "}:")
  print(io, _show_elements(x))
end
function Base.show(io::IO, ::MIME"text/plain", x::OneHotVector{T, L}) where {T, L}
  print(io, string.(length(x)))
  print(io, "-element Flux.OneHotVector{")
  join(io, string.([L, T]), ",")
  println(io, "}:")
  print(io, _show_elements(x))
end

# use this type so reshaped arrays hit fast paths
# e.g. argmax
const OneHotLike{T, L, N, var"N+1", I} =
  Union{OneHotArray{T, L, N, var"N+1", I},
        Base.ReshapedArray{Bool, var"N+1", <:OneHotArray{T, L, <:Any, <:Any, I}}}

_isonehot(x::OneHotArray) = true
_isonehot(x::Base.ReshapedArray{<:Any, <:Any, <:OneHotArray{<:Any, L}}) where L = (size(x, 1) == L)

Base.size(x::OneHotArray{<:Any, L}) where L = (Int(L), size(x.indices)...)

_onehotindex(x, i) = (x == i)

Base.getindex(x::OneHotVector, i::Integer) = _onehotindex(x.indices, i)
Base.getindex(x::OneHotVector{T, L}, ::Colon) where {T, L} = x

Base.getindex(x::OneHotArray, i::Integer, I...) = _onehotindex.(x.indices[I...], i)
Base.getindex(x::OneHotArray{<:Any, L}, ::Colon, I...) where L = OneHotArray(x.indices[I...], L)
Base.getindex(x::OneHotArray{<:Any, <:Any, <:Any, N}, ::Vararg{Colon, N}) where N = x
Base.getindex(x::OneHotArray, I::CartesianIndex{N}) where N = x[I[1], Tuple(I)[2:N]...]

_onehot_bool_type(x::OneHotLike{<:Any, <:Any, <:Any, N, <:Union{Integer, AbstractArray}}) where N = Array{Bool, N}
_onehot_bool_type(x::OneHotLike{<:Any, <:Any, <:Any, N, <:CuArray}) where N = CuArray{Bool, N}

function Base.cat(x::OneHotLike{<:Any, L}, xs::OneHotLike{<:Any, L}...; dims::Int) where L
  if isone(dims) || any(x -> !_isonehot(x), (x, xs...))
    return cat(map(x -> convert(_onehot_bool_type(x), x), (x, xs...))...; dims = dims)
  else
    return OneHotArray(cat(_indices(x), _indices.(xs)...; dims = dims - 1), L)
  end
end

Base.hcat(x::OneHotLike, xs::OneHotLike...) = cat(x, xs...; dims = 2)
Base.vcat(x::OneHotLike, xs::OneHotLike...) = cat(x, xs...; dims = 1)

# optimized concatenation for matrices and vectors of same parameters
Base.hcat(x::T, xs::T...) where {L, T <: OneHotLike{<:Any, L, <:Any, 2}} =
  OneHotMatrix(reduce(vcat, _indices.(xs); init = _indices(x)), L)
Base.hcat(x::T, xs::T...) where {L, T <: OneHotLike{<:Any, L, <:Any, 1}} =
  OneHotMatrix(reduce(vcat, _indices.(xs); init = _indices(x)), L)

batch(xs::AbstractArray{<:OneHotVector{<:Any, L}}) where L = OneHotArray(_indices.(xs), L)

Adapt.adapt_structure(T, x::OneHotArray{<:Any, L}) where L = OneHotArray(adapt(T, _indices(x)), L)

Base.BroadcastStyle(::Type{<:OneHotArray{<: Any, <: Any, <: Any, N, <: CuArray}}) where N = CUDA.CuArrayStyle{N}()

Base.map(f, x::OneHotLike) = Base.broadcast(f, x)

Base.argmax(x::OneHotLike; dims = Colon()) =
  (_isonehot(x) && dims == 1) ?
    reshape(CartesianIndex.(_indices(x), CartesianIndices(_indices(x))), 1, size(_indices(x))...) :
    invoke(argmax, Tuple{AbstractArray}, x; dims = dims)

"""
    onehot(l, labels[, unk])

Return a `OneHotVector` where only first occourence of `l` in `labels` is `1` and
all other elements are `0`.

If `l` is not found in labels and  `unk` is present, the function returns
`onehot(unk, labels)`; otherwise the function raises an error.

# Examples
```jldoctest
julia> Flux.onehot(:b, [:a, :b, :c])
3-element Flux.OneHotVector{3,UInt32}:
 0
 1
 0

julia> Flux.onehot(:c, [:a, :b, :c])
3-element Flux.OneHotVector{3,UInt32}:
 0
 0
 1
```
"""
function onehot(l, labels)
  i = something(findfirst(isequal(l), labels), 0)
  i > 0 || error("Value $l is not in labels")
  OneHotVector{UInt32, length(labels)}(i)
end

function onehot(l, labels, unk)
  i = something(findfirst(isequal(l), labels), 0)
  i > 0 || return onehot(unk, labels)
  OneHotVector{UInt32, length(labels)}(i)
end

"""
    onehotbatch(ls, labels[, unk...])

Return a `OneHotMatrix` where `k`th column of the matrix is `onehot(ls[k], labels)`.

If one of the input labels `ls` is not found in `labels` and `unk` is given,
return [`onehot(unk, labels)`](@ref) ; otherwise the function will raise an error.

# Examples
```jldoctest
julia> Flux.onehotbatch([:b, :a, :b], [:a, :b, :c])
3×3 Flux.OneHotArray{3,2,Vector{UInt32}}:
 0  1  0
 1  0  1
 0  0  0
```
"""
onehotbatch(ls, labels, unk...) = batch([onehot(l, labels, unk...) for l in ls])

"""
    onecold(y[, labels = 1:length(y)])

Inverse operations of [`onehot`](@ref).

# Examples
```jldoctest
julia> Flux.onecold([true, false, false], [:a, :b, :c])
:a

julia> Flux.onecold([0.3, 0.2, 0.5], [:a, :b, :c])
:c
```
"""
onecold(y::AbstractVector, labels = 1:length(y)) = labels[argmax(y)]
function onecold(y::AbstractArray, labels = 1:size(y, 1))
  indices = _fast_argmax(y)
  xs = isbits(labels) ? indices : collect(indices) # non-bit type cannot be handled by CUDA

  return map(xi -> labels[xi[1]], xs)
end

_fast_argmax(x::AbstractArray) = dropdims(argmax(x; dims = 1); dims = 1)
function _fast_argmax(x::OneHotLike)
  if _isonehot(x)
    return _indices(x)
  else
    return _fast_argmax(convert(_onehot_bool_type(x), x))
  end
end

@nograd OneHotArray, onecold, onehot, onehotbatch

function Base.:(*)(A::AbstractMatrix, B::OneHotLike{<:Any, L}) where L
  _isonehot(B) || return invoke(*, Tuple{AbstractMatrix, AbstractMatrix}, A, B)
  size(A, 2) == L || throw(DimensionMismatch("Matrix column must correspond with OneHot size: $(size(A, 2)) != $L"))
  return A[:, onecold(B)]
end
for wrapper in [:Adjoint, :Transpose]
  @eval begin
    function Base.:*(A::$wrapper{<:Any, <:AbstractMatrix{T}}, b::OneHotVector{<:Any, L}) where {L, T}
      size(A, 2) == L ||
        throw(DimensionMismatch("Matrix column must correspond with OneHot size: $(size(A, 2)) != $L"))

      return A[:, onecold(b)]
    end

    function Base.:*(A::$wrapper{<:Number, <:AbstractVector{T}}, b::OneHotVector{<:Any, L}) where {L, T}
      size(A, 2) == L ||
        throw(DimensionMismatch("Matrix column must correspond with OneHot size: $(size(A, 2)) != $L"))

      return A[onecold(b)]
    end
  end
end


text:
BUILD_SHARED_LIBS = false
include("build.jl")

ext: jl

max_stars_repo_name: chemfiles/chemfiles-prebuilt

max_issues_repo_name: chemfiles/chemfiles-prebuilt

max_forks_repo_name: chemfiles/chemfiles-prebuilt


text:
bucket_name = "ocaws.jl.test." * lowercase(Dates.format(now(Dates.UTC), "yyyymmddTHHMMSSZ"))
s3_create_bucket(bucket_name)
root = Path("s3://$bucket_name/pathset-root/")

ps = PathSet(
    root,
    root / "foo/",
    root / "foo" / "baz.txt",
    root / "bar/",
    root / "bar" / "qux/",
    root / "bar" / "qux" / "quux.tar.gz",
    root / "fred/",
    root / "fred" / "plugh",
    false
)

function test_s3_constructors(ps::PathSet)
    @test S3Path(bucket_name, "pathset-root/foo/baz.txt") == ps.baz
    @test S3Path(bucket_name, p"pathset-root/foo/baz.txt") == ps.baz
    @test S3Path(bucket_name, p"/pathset-root/foo/baz.txt") == ps.baz
    @test S3Path("s3://$bucket_name", p"/pathset-root/foo/baz.txt") == ps.baz
    @test S3Path(bucket_name, "pathset-root/bar/qux"; isdirectory=true) == ps.qux
    @test S3Path(bucket_name, "pathset-root/bar/qux/"; isdirectory=true) == ps.qux
    @test S3Path(bucket_name, p"pathset-root/bar/qux"; isdirectory=true) == ps.qux
    @test S3Path(bucket_name, p"/pathset-root/bar/qux"; isdirectory=true) == ps.qux
end

function test_s3_parents(ps::PathSet)
    @testset "parents" begin
        @test parent(ps.foo) == ps.root
        @test parent(ps.qux) == ps.bar
        @test dirname(ps.foo) == ps.root

        @test hasparent(ps.qux)
        _parents = parents(ps.qux)
        @test _parents[end] == ps.bar
        @test _parents[end - 1] == ps.root
        @test _parents[1] == Path(ps.root; segments=())
    end
end

function test_s3_join(ps::PathSet)
    @testset "join" begin
        @test join(ps.root, "bar/") == ps.bar
        @test ps.root / "foo" / "baz.txt" == ps.baz
        @test ps.root / "foobaz.txt" == ps.root / "foo" * "baz.txt"
    end
end

function test_s3_normalize(ps::PathSet)
    @testset "norm" begin
        @test normalize(ps.bar / ".." / "foo/") == ps.foo
        @test normalize(ps.bar / ".." / "foo") != ps.foo
        @test normalize(ps.bar / "./") == ps.bar
        @test normalize(ps.bar / "../") == ps.root
    end
end

function test_s3_mkdir(p::PathSet)
    @testset "mkdir" begin
        garply = p.root / "corge" / "grault" / "garply/"
        mkdir(garply; recursive=true)
        @test exists(garply)
        rm(p.root / "corge/"; recursive=true)
        @test !exists(garply)
    end
end

function test_s3_readpath(p::PathSet)
    @testset "readpath" begin
        @test readdir(p.root) == ["bar/", "foo/", "fred/"]
        @test readdir(p.qux) == ["quux.tar.gz"]
        @test readpath(p.root) == [p.bar, p.foo, p.fred]
        @test readpath(p.qux) == [p.quux]
    end
end

function test_s3_cp(p::PathSet)
    @testset "cp" begin
        # In case the folder objects were deleted in a previous test
        mkdir.([p.foo, p.qux, p.fred]; recursive=true, exist_ok=true)
        @test exists(p.foo)
        cp(p.foo, p.qux / "foo/"; force=true)
        @test exists(p.qux / "foo" / "baz.txt")
        rm(p.qux / "foo/"; recursive=true)
    end
end

function test_s3_mv(p::PathSet)
    @testset "mv" begin
        # In case the folder objects were deleted in a previous test
        mkdir.([p.foo, p.qux, p.fred]; recursive=true, exist_ok=true)
        garply = p.root / "corge" / "grault" / "garply/"
        mkdir(garply; recursive=true, exist_ok=true)
        @test exists(garply)
        mv(p.root / "corge/", p.foo / "corge/"; force=true)
        @test exists(p.foo / "corge" / "grault" / "garply/")
        rm(p.foo / "corge/"; recursive=true)
    end
end

function test_s3_sync(p::PathSet)
    @testset "sync" begin
        # In case the folder objects were deleted in a previous test
        mkdir.([p.foo, p.qux, p.fred]; recursive=true, exist_ok=true)
        # Base cp case
        sync(p.foo, ps.qux / "foo/")
        @test exists(p.qux / "foo" / "baz.txt")

        # Test that the copied baz file has a newer modified time
        baz_t = modified(p.qux / "foo" / "baz.txt")
        @test modified(p.baz) < baz_t

        # Don't cp unchanged files when a new file is added
        # NOTE: sleep before we make a new file, so it's clear tha the
        # modified time has changed.
        sleep(1)
        write(p.foo / "test.txt", "New File")
        sync(p.foo, ps.qux / "foo/")
        @test exists(p.qux / "foo" / "test.txt")
        @test read(p.qux / "foo" / "test.txt") == b"New File"
        @test read(p.qux / "foo" / "test.txt", String) == "New File"
        @test modified(p.qux / "foo" / "baz.txt") == baz_t
        @test modified(p.qux / "foo" / "test.txt") > baz_t

        # Test not deleting a file on sync
        rm(p.foo / "test.txt")
        sync(p.foo, ps.qux / "foo/")
        @test exists(p.qux / "foo" / "test.txt")

        # Test passing delete flag
        sync(p.foo, p.qux / "foo/"; delete=true)
        @test !exists(p.qux / "foo" / "test.txt")
        rm(p.qux / "foo/"; recursive=true)
    end
end

function test_s3_properties(ps::PathSet)
    @testset "s3_properties" begin
        fp1 = p"s3://mybucket/path/to/some/object"
        fp2 = p"s3://mybucket/path/to/some/prefix/"
        @test fp1.bucket == "mybucket"
        @test fp1.key == "path/to/some/object"
        @test fp2.bucket == "mybucket"
        @test fp2.key == "path/to/some/prefix/"
    end
end

function test_s3_folders_and_files(ps::PathSet)
    @testset "s3_folders_and_files" begin
        # In case the ps.root doesn't exist
        mkdir(ps.root; recursive=true, exist_ok=true)

        # Test that the trailing slash matters
        @test p"s3://mybucket/path/to/some/prefix/" != p"s3://mybucket/path/to/some/prefix"

        # Test that we can have empty directory names
        # I'm not sure if we want to support this in the future, but it may require more
        # overloading of AbstractPath methods to support properly.
        @test_broken p"s3://mybucket/path/to/some/prefix" != p"s3://mybucket/path//to/some/prefix"

        write(ps.root / "foobar", "I'm an object")
        mkdir(ps.root / "foobar/")
        write(ps.root / "foobar" / "car.txt", "I'm a different object")

        @test read(ps.root / "foobar") == b"I'm an object"
        @test read(ps.root / "foobar", String) == "I'm an object"
        @test_throws ArgumentError readpath(ps.root / "foobar")
        @test readpath(ps.root / "foobar/") == [ps.root / "foobar" / "car.txt"]
        @test read(ps.root / "foobar" / "car.txt", String) == "I'm a different object"
    end
end

@testset "$(typeof(ps.root))" begin
    testsets = [
        test_s3_constructors,
        test_registration,
        test_show,
        test_parse,
        test_convert,
        test_components,
        test_indexing,
        test_iteration,
        test_s3_parents,
        test_descendants_and_ascendants,
        test_s3_join,
        test_splitext,
        test_basename,
        test_filename,
        test_extensions,
        test_isempty,
        test_s3_normalize,
        # test_canonicalize, # real doesn't make sense for S3Paths
        test_relative,
        test_absolute,
        test_isdir,
        test_isfile,
        test_stat,
        test_filesize,
        test_modified,
        test_created,
        test_cd,
        test_s3_readpath,
        test_walkpath,
        test_read,
        test_write,
        test_s3_mkdir,
        # These tests seem to fail due to an eventual consistency issue?
        test_s3_cp,
        test_s3_mv,
        test_s3_sync,
        test_symlink,
        test_touch,
        test_tmpname,
        test_tmpdir,
        test_mktmp,
        test_mktmpdir,
        test_download,
        test_issocket,
        # These will also all work for our custom path type,
        # but many implementations won't support them.
        test_isfifo,
        test_ischardev,
        test_isblockdev,
        test_ismount,
        test_isexecutable,
        test_isreadable,
        test_iswritable,
        # test_chown,   # chmod & chown don't make sense for S3Paths
        # test_chmod,
        test_s3_properties,
        test_s3_folders_and_files,
    ]

    # Run all of the automated tests
    test(ps, testsets)
end

@testset "readdir" begin
    function initialize()
        """
        Hierarchy:

        bucket-name
        |-- test_01.txt
        |-- emptydir/
        |-- subdir1/
        |   |-- test_02.txt
        |   |-- test_03.txt
        |   |-- subdir2/
        |       |-- test_04.txt
        |       |-- subdir3/
        """
        s3_put(bucket_name, "test_01.txt", "test01")
        s3_put(bucket_name, "emptydir/", "")
        s3_put(bucket_name, "subdir1/", "")
        s3_put(bucket_name, "subdir1/test_02.txt", "test02")
        s3_put(bucket_name, "subdir1/test_03.txt", "test03")
        s3_put(bucket_name, "subdir1/subdir2/", "")
        s3_put(bucket_name, "subdir1/subdir2/test_04.txt", "test04")
        s3_put(bucket_name, "subdir1/subdir2/subdir3/", "")
    end

    function verify_files(path::S3Path)
        @test readdir(path) == ["emptydir/", "subdir1/", "test_01.txt"]
        @test readdir(path / "emptydir/") == []
        @test readdir(path / "subdir1/") == ["subdir2/", "test_02.txt", "test_03.txt"]
        @test readdir(path / "subdir1/subdir2/") == ["subdir3/", "test_04.txt"]
        @test readdir(path / "subdir1/subdir2/subdir3/") == []
    end

    function verify_files(path::AbstractPath)
        @test readdir(path) == ["emptydir", "subdir1", "test_01.txt"]
        @test readdir(path / "emptydir/") == []
        @test readdir(path / "subdir1/") == ["subdir2", "test_02.txt", "test_03.txt"]
        @test readdir(path / "subdir1/subdir2/") == ["subdir3", "test_04.txt"]
        @test readdir(path / "subdir1/subdir2/subdir3/") == []
    end

    initialize()

    @testset "S3" begin
        verify_files(S3Path("s3://$bucket_name/"))
        @test_throws ArgumentError("Invalid s3 path string: $bucket_name") S3Path(bucket_name)
    end

    @test_skip @testset "Local" begin
        temp_path = Path(tempdir() * string(uuid4()))
        mkdir(temp_path)

        sync(S3Path("s3://$bucket_name/"), temp_path)
        verify_files(temp_path)

        rm(temp_path, force=true, recursive=true)
    end

    @testset "join" begin
        @test (  # test trailing slash on prefix does not matter for join
            p"s3://foo/bar" / "baz" ==
            p"s3://foo/bar/" / "baz" ==
            p"s3://foo/bar/baz"
        )
        @test (  # test trailing slash on root-only prefix in particular does not matter
            p"s3://foo" / "bar" / "baz" ==
            p"s3://foo/" / "bar" / "baz" ==
            p"s3://foo/bar/baz"
        )
        # test extra leading and trailing slashes do not matter
        @test p"s3://foo/" / "bar/" / "/baz" == p"s3://foo/bar/baz"
        # test joining `/` and string concatentation `*` play nice as expected
        @test p"s3://foo" * "/" / "bar" == p"s3://foo" / "/" * "bar" == p"s3://foo" / "bar"
        @test p"s3://foo" / "bar" * "baz" == p"s3://foo/bar" * "baz"  == p"s3://foo" / "barbaz"
        # test trailing slash on final piece is included
        @test p"s3://foo/bar" / "baz/" == p"s3://foo/bar/baz/"
    end
end


text:
module Memorial

using ..Ahorn, Maple

const placements = Ahorn.PlacementDict(
    "Memorial" => Ahorn.EntityPlacement(
        Maple.Memorial
    ),
    "Custom Memorial (Everest)" => Ahorn.EntityPlacement(
        Maple.EverestMemorial
    )
)

sprite = "scenery/memorial/memorial"

function Ahorn.selection(entity::Maple.Memorial)
    x, y = Ahorn.position(entity)

    return Ahorn.getSpriteRectangle(sprite, x, y, jx=0.5, jy=1.0)
end

function Ahorn.selection(entity::Maple.EverestMemorial)
    x, y = Ahorn.position(entity)

    spriteName = get(entity.data, "sprite", sprite)
    customSprite = Ahorn.getSprite(spriteName, "Gameplay")

    if customSprite.width == 0 || customSprite.height == 0
        return Ahorn.Rectangle(x - 4, y - 4, 8, 8)

    else
        return Ahorn.getSpriteRectangle(spriteName, x, y, jx=0.5, jy=1.0)
    end
end

function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::Maple.EverestMemorial, room::Maple.Room)
    spriteName = get(entity.data, "sprite", sprite)

    Ahorn.drawSprite(ctx, spriteName, 0, 0, jx=0.5, jy=1.0)
end

Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::Maple.Memorial, room::Maple.Room) = Ahorn.drawSprite(ctx, sprite, 0, 0, jx=0.5, jy=1.0)

end


text:
# syntax: proto3
using ProtoBuf
import ProtoBuf.meta
import ._ProtoBuf_Top_.opentelemetry

const AggregationTemporality = (;
    [
        Symbol("AGGREGATION_TEMPORALITY_UNSPECIFIED") => Int32(0),
        Symbol("AGGREGATION_TEMPORALITY_DELTA") => Int32(1),
        Symbol("AGGREGATION_TEMPORALITY_CUMULATIVE") => Int32(2),
    ]...,
)

const DataPointFlags =
    (; [Symbol("FLAG_NONE") => Int32(0), Symbol("FLAG_NO_RECORDED_VALUE") => Int32(1)]...)

mutable struct SummaryDataPoint_ValueAtQuantile <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function SummaryDataPoint_ValueAtQuantile(; kwargs...)
        obj = new(meta(SummaryDataPoint_ValueAtQuantile), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct SummaryDataPoint_ValueAtQuantile
const __meta_SummaryDataPoint_ValueAtQuantile = Ref{ProtoMeta}()
function meta(::Type{SummaryDataPoint_ValueAtQuantile})
    ProtoBuf.metalock() do
        if !isassigned(__meta_SummaryDataPoint_ValueAtQuantile)
            __meta_SummaryDataPoint_ValueAtQuantile[] =
                target = ProtoMeta(SummaryDataPoint_ValueAtQuantile)
            allflds = Pair{Symbol,Union{Type,String}}[:quantile=>Float64, :value=>Float64]
            meta(
                target,
                SummaryDataPoint_ValueAtQuantile,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_SummaryDataPoint_ValueAtQuantile[]
    end
end
function Base.getproperty(obj::SummaryDataPoint_ValueAtQuantile, name::Symbol)
    if name === :quantile
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :value
        return (obj.__protobuf_jl_internal_values[name])::Float64
    else
        getfield(obj, name)
    end
end

mutable struct SummaryDataPoint <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function SummaryDataPoint(; kwargs...)
        obj = new(meta(SummaryDataPoint), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct SummaryDataPoint
const __meta_SummaryDataPoint = Ref{ProtoMeta}()
function meta(::Type{SummaryDataPoint})
    ProtoBuf.metalock() do
        if !isassigned(__meta_SummaryDataPoint)
            __meta_SummaryDataPoint[] = target = ProtoMeta(SummaryDataPoint)
            fnum = Int[7, 2, 3, 4, 5, 6, 8]
            wtype = Dict(
                :start_time_unix_nano => :fixed64,
                :time_unix_nano => :fixed64,
                :count => :fixed64,
            )
            allflds = Pair{Symbol,Union{Type,String}}[
                :attributes=>Base.Vector{opentelemetry.proto.common.v1.KeyValue},
                :start_time_unix_nano=>UInt64,
                :time_unix_nano=>UInt64,
                :count=>UInt64,
                :sum=>Float64,
                :quantile_values=>Base.Vector{SummaryDataPoint_ValueAtQuantile},
                :flags=>UInt32,
            ]
            meta(
                target,
                SummaryDataPoint,
                allflds,
                ProtoBuf.DEF_REQ,
                fnum,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                wtype,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_SummaryDataPoint[]
    end
end
function Base.getproperty(obj::SummaryDataPoint, name::Symbol)
    if name === :attributes
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            opentelemetry.proto.common.v1.KeyValue,
        }
    elseif name === :start_time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :count
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :sum
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :quantile_values
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            SummaryDataPoint_ValueAtQuantile,
        }
    elseif name === :flags
        return (obj.__protobuf_jl_internal_values[name])::UInt32
    else
        getfield(obj, name)
    end
end

mutable struct Summary <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Summary(; kwargs...)
        obj = new(meta(Summary), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct Summary
const __meta_Summary = Ref{ProtoMeta}()
function meta(::Type{Summary})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Summary)
            __meta_Summary[] = target = ProtoMeta(Summary)
            allflds =
                Pair{Symbol,Union{Type,String}}[:data_points=>Base.Vector{SummaryDataPoint}]
            meta(
                target,
                Summary,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_Summary[]
    end
end
function Base.getproperty(obj::Summary, name::Symbol)
    if name === :data_points
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{SummaryDataPoint}
    else
        getfield(obj, name)
    end
end

mutable struct Exemplar <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Exemplar(; kwargs...)
        obj = new(meta(Exemplar), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct Exemplar
const __meta_Exemplar = Ref{ProtoMeta}()
function meta(::Type{Exemplar})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Exemplar)
            __meta_Exemplar[] = target = ProtoMeta(Exemplar)
            fnum = Int[7, 2, 3, 6, 4, 5]
            wtype = Dict(:time_unix_nano => :fixed64, :as_int => :sfixed64)
            allflds = Pair{Symbol,Union{Type,String}}[
                :filtered_attributes=>Base.Vector{opentelemetry.proto.common.v1.KeyValue},
                :time_unix_nano=>UInt64,
                :as_double=>Float64,
                :as_int=>Int64,
                :span_id=>Vector{UInt8},
                :trace_id=>Vector{UInt8},
            ]
            oneofs = Int[0, 0, 1, 1, 0, 0]
            oneof_names = Symbol[Symbol("value")]
            meta(
                target,
                Exemplar,
                allflds,
                ProtoBuf.DEF_REQ,
                fnum,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                wtype,
                oneofs,
                oneof_names,
            )
        end
        __meta_Exemplar[]
    end
end
function Base.getproperty(obj::Exemplar, name::Symbol)
    if name === :filtered_attributes
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            opentelemetry.proto.common.v1.KeyValue,
        }
    elseif name === :time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :as_double
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :as_int
        return (obj.__protobuf_jl_internal_values[name])::Int64
    elseif name === :span_id
        return (obj.__protobuf_jl_internal_values[name])::Vector{UInt8}
    elseif name === :trace_id
        return (obj.__protobuf_jl_internal_values[name])::Vector{UInt8}
    else
        getfield(obj, name)
    end
end

mutable struct NumberDataPoint <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function NumberDataPoint(; kwargs...)
        obj = new(meta(NumberDataPoint), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct NumberDataPoint
const __meta_NumberDataPoint = Ref{ProtoMeta}()
function meta(::Type{NumberDataPoint})
    ProtoBuf.metalock() do
        if !isassigned(__meta_NumberDataPoint)
            __meta_NumberDataPoint[] = target = ProtoMeta(NumberDataPoint)
            fnum = Int[7, 2, 3, 4, 6, 5, 8]
            wtype = Dict(
                :start_time_unix_nano => :fixed64,
                :time_unix_nano => :fixed64,
                :as_int => :sfixed64,
            )
            allflds = Pair{Symbol,Union{Type,String}}[
                :attributes=>Base.Vector{opentelemetry.proto.common.v1.KeyValue},
                :start_time_unix_nano=>UInt64,
                :time_unix_nano=>UInt64,
                :as_double=>Float64,
                :as_int=>Int64,
                :exemplars=>Base.Vector{Exemplar},
                :flags=>UInt32,
            ]
            oneofs = Int[0, 0, 0, 1, 1, 0, 0]
            oneof_names = Symbol[Symbol("value")]
            meta(
                target,
                NumberDataPoint,
                allflds,
                ProtoBuf.DEF_REQ,
                fnum,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                wtype,
                oneofs,
                oneof_names,
            )
        end
        __meta_NumberDataPoint[]
    end
end
function Base.getproperty(obj::NumberDataPoint, name::Symbol)
    if name === :attributes
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            opentelemetry.proto.common.v1.KeyValue,
        }
    elseif name === :start_time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :as_double
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :as_int
        return (obj.__protobuf_jl_internal_values[name])::Int64
    elseif name === :exemplars
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Exemplar}
    elseif name === :flags
        return (obj.__protobuf_jl_internal_values[name])::UInt32
    else
        getfield(obj, name)
    end
end

mutable struct ExponentialHistogramDataPoint_Buckets <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function ExponentialHistogramDataPoint_Buckets(; kwargs...)
        obj = new(
            meta(ExponentialHistogramDataPoint_Buckets),
            Dict{Symbol,Any}(),
            Set{Symbol}(),
        )
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct ExponentialHistogramDataPoint_Buckets
const __meta_ExponentialHistogramDataPoint_Buckets = Ref{ProtoMeta}()
function meta(::Type{ExponentialHistogramDataPoint_Buckets})
    ProtoBuf.metalock() do
        if !isassigned(__meta_ExponentialHistogramDataPoint_Buckets)
            __meta_ExponentialHistogramDataPoint_Buckets[] =
                target = ProtoMeta(ExponentialHistogramDataPoint_Buckets)
            pack = Symbol[:bucket_counts]
            wtype = Dict(:offset => :sint32)
            allflds = Pair{Symbol,Union{Type,String}}[
                :offset=>Int32,
                :bucket_counts=>Base.Vector{UInt64},
            ]
            meta(
                target,
                ExponentialHistogramDataPoint_Buckets,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                pack,
                wtype,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_ExponentialHistogramDataPoint_Buckets[]
    end
end
function Base.getproperty(obj::ExponentialHistogramDataPoint_Buckets, name::Symbol)
    if name === :offset
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :bucket_counts
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{UInt64}
    else
        getfield(obj, name)
    end
end

mutable struct ExponentialHistogramDataPoint <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function ExponentialHistogramDataPoint(; kwargs...)
        obj = new(meta(ExponentialHistogramDataPoint), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct ExponentialHistogramDataPoint
const __meta_ExponentialHistogramDataPoint = Ref{ProtoMeta}()
function meta(::Type{ExponentialHistogramDataPoint})
    ProtoBuf.metalock() do
        if !isassigned(__meta_ExponentialHistogramDataPoint)
            __meta_ExponentialHistogramDataPoint[] =
                target = ProtoMeta(ExponentialHistogramDataPoint)
            wtype = Dict(
                :start_time_unix_nano => :fixed64,
                :time_unix_nano => :fixed64,
                :count => :fixed64,
                :scale => :sint32,
                :zero_count => :fixed64,
            )
            allflds = Pair{Symbol,Union{Type,String}}[
                :attributes=>Base.Vector{opentelemetry.proto.common.v1.KeyValue},
                :start_time_unix_nano=>UInt64,
                :time_unix_nano=>UInt64,
                :count=>UInt64,
                :sum=>Float64,
                :scale=>Int32,
                :zero_count=>UInt64,
                :positive=>ExponentialHistogramDataPoint_Buckets,
                :negative=>ExponentialHistogramDataPoint_Buckets,
                :flags=>UInt32,
                :exemplars=>Base.Vector{Exemplar},
            ]
            meta(
                target,
                ExponentialHistogramDataPoint,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                wtype,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_ExponentialHistogramDataPoint[]
    end
end
function Base.getproperty(obj::ExponentialHistogramDataPoint, name::Symbol)
    if name === :attributes
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            opentelemetry.proto.common.v1.KeyValue,
        }
    elseif name === :start_time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :count
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :sum
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :scale
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :zero_count
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :positive
        return (obj.__protobuf_jl_internal_values[name])::ExponentialHistogramDataPoint_Buckets
    elseif name === :negative
        return (obj.__protobuf_jl_internal_values[name])::ExponentialHistogramDataPoint_Buckets
    elseif name === :flags
        return (obj.__protobuf_jl_internal_values[name])::UInt32
    elseif name === :exemplars
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Exemplar}
    else
        getfield(obj, name)
    end
end

mutable struct HistogramDataPoint <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function HistogramDataPoint(; kwargs...)
        obj = new(meta(HistogramDataPoint), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct HistogramDataPoint
const __meta_HistogramDataPoint = Ref{ProtoMeta}()
function meta(::Type{HistogramDataPoint})
    ProtoBuf.metalock() do
        if !isassigned(__meta_HistogramDataPoint)
            __meta_HistogramDataPoint[] = target = ProtoMeta(HistogramDataPoint)
            fnum = Int[9, 2, 3, 4, 5, 6, 7, 8, 10]
            pack = Symbol[:bucket_counts, :explicit_bounds]
            wtype = Dict(
                :start_time_unix_nano => :fixed64,
                :time_unix_nano => :fixed64,
                :count => :fixed64,
                :bucket_counts => :fixed64,
            )
            allflds = Pair{Symbol,Union{Type,String}}[
                :attributes=>Base.Vector{opentelemetry.proto.common.v1.KeyValue},
                :start_time_unix_nano=>UInt64,
                :time_unix_nano=>UInt64,
                :count=>UInt64,
                :sum=>Float64,
                :bucket_counts=>Base.Vector{UInt64},
                :explicit_bounds=>Base.Vector{Float64},
                :exemplars=>Base.Vector{Exemplar},
                :flags=>UInt32,
            ]
            meta(
                target,
                HistogramDataPoint,
                allflds,
                ProtoBuf.DEF_REQ,
                fnum,
                ProtoBuf.DEF_VAL,
                pack,
                wtype,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_HistogramDataPoint[]
    end
end
function Base.getproperty(obj::HistogramDataPoint, name::Symbol)
    if name === :attributes
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            opentelemetry.proto.common.v1.KeyValue,
        }
    elseif name === :start_time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :time_unix_nano
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :count
        return (obj.__protobuf_jl_internal_values[name])::UInt64
    elseif name === :sum
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :bucket_counts
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{UInt64}
    elseif name === :explicit_bounds
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Float64}
    elseif name === :exemplars
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Exemplar}
    elseif name === :flags
        return (obj.__protobuf_jl_internal_values[name])::UInt32
    else
        getfield(obj, name)
    end
end

mutable struct Sum <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Sum(; kwargs...)
        obj = new(meta(Sum), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct Sum
const __meta_Sum = Ref{ProtoMeta}()
function meta(::Type{Sum})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Sum)
            __meta_Sum[] = target = ProtoMeta(Sum)
            allflds = Pair{Symbol,Union{Type,String}}[
                :data_points=>Base.Vector{NumberDataPoint},
                :aggregation_temporality=>Int32,
                :is_monotonic=>Bool,
            ]
            meta(
                target,
                Sum,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_Sum[]
    end
end
function Base.getproperty(obj::Sum, name::Symbol)
    if name === :data_points
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{NumberDataPoint}
    elseif name === :aggregation_temporality
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :is_monotonic
        return (obj.__protobuf_jl_internal_values[name])::Bool
    else
        getfield(obj, name)
    end
end

mutable struct Gauge <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Gauge(; kwargs...)
        obj = new(meta(Gauge), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct Gauge
const __meta_Gauge = Ref{ProtoMeta}()
function meta(::Type{Gauge})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Gauge)
            __meta_Gauge[] = target = ProtoMeta(Gauge)
            allflds =
                Pair{Symbol,Union{Type,String}}[:data_points=>Base.Vector{NumberDataPoint}]
            meta(
                target,
                Gauge,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_Gauge[]
    end
end
function Base.getproperty(obj::Gauge, name::Symbol)
    if name === :data_points
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{NumberDataPoint}
    else
        getfield(obj, name)
    end
end

mutable struct ExponentialHistogram <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function ExponentialHistogram(; kwargs...)
        obj = new(meta(ExponentialHistogram), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct ExponentialHistogram
const __meta_ExponentialHistogram = Ref{ProtoMeta}()
function meta(::Type{ExponentialHistogram})
    ProtoBuf.metalock() do
        if !isassigned(__meta_ExponentialHistogram)
            __meta_ExponentialHistogram[] = target = ProtoMeta(ExponentialHistogram)
            allflds = Pair{Symbol,Union{Type,String}}[
                :data_points=>Base.Vector{ExponentialHistogramDataPoint},
                :aggregation_temporality=>Int32,
            ]
            meta(
                target,
                ExponentialHistogram,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_ExponentialHistogram[]
    end
end
function Base.getproperty(obj::ExponentialHistogram, name::Symbol)
    if name === :data_points
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            ExponentialHistogramDataPoint,
        }
    elseif name === :aggregation_temporality
        return (obj.__protobuf_jl_internal_values[name])::Int32
    else
        getfield(obj, name)
    end
end

mutable struct Histogram <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Histogram(; kwargs...)
        obj = new(meta(Histogram), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct Histogram
const __meta_Histogram = Ref{ProtoMeta}()
function meta(::Type{Histogram})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Histogram)
            __meta_Histogram[] = target = ProtoMeta(Histogram)
            allflds = Pair{Symbol,Union{Type,String}}[
                :data_points=>Base.Vector{HistogramDataPoint},
                :aggregation_temporality=>Int32,
            ]
            meta(
                target,
                Histogram,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_Histogram[]
    end
end
function Base.getproperty(obj::Histogram, name::Symbol)
    if name === :data_points
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{HistogramDataPoint}
    elseif name === :aggregation_temporality
        return (obj.__protobuf_jl_internal_values[name])::Int32
    else
        getfield(obj, name)
    end
end

mutable struct Metric <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Metric(; kwargs...)
        obj = new(meta(Metric), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct Metric
const __meta_Metric = Ref{ProtoMeta}()
function meta(::Type{Metric})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Metric)
            __meta_Metric[] = target = ProtoMeta(Metric)
            fnum = Int[1, 2, 3, 5, 7, 9, 10, 11]
            allflds = Pair{Symbol,Union{Type,String}}[
                :name=>AbstractString,
                :description=>AbstractString,
                :unit=>AbstractString,
                :gauge=>Gauge,
                :sum=>Sum,
                :histogram=>Histogram,
                :exponential_histogram=>ExponentialHistogram,
                :summary=>Summary,
            ]
            oneofs = Int[0, 0, 0, 1, 1, 1, 1, 1]
            oneof_names = Symbol[Symbol("data")]
            meta(
                target,
                Metric,
                allflds,
                ProtoBuf.DEF_REQ,
                fnum,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                oneofs,
                oneof_names,
            )
        end
        __meta_Metric[]
    end
end
function Base.getproperty(obj::Metric, name::Symbol)
    if name === :name
        return (obj.__protobuf_jl_internal_values[name])::AbstractString
    elseif name === :description
        return (obj.__protobuf_jl_internal_values[name])::AbstractString
    elseif name === :unit
        return (obj.__protobuf_jl_internal_values[name])::AbstractString
    elseif name === :gauge
        return (obj.__protobuf_jl_internal_values[name])::Gauge
    elseif name === :sum
        return (obj.__protobuf_jl_internal_values[name])::Sum
    elseif name === :histogram
        return (obj.__protobuf_jl_internal_values[name])::Histogram
    elseif name === :exponential_histogram
        return (obj.__protobuf_jl_internal_values[name])::ExponentialHistogram
    elseif name === :summary
        return (obj.__protobuf_jl_internal_values[name])::Summary
    else
        getfield(obj, name)
    end
end

mutable struct InstrumentationLibraryMetrics <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function InstrumentationLibraryMetrics(; kwargs...)
        obj = new(meta(InstrumentationLibraryMetrics), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct InstrumentationLibraryMetrics
const __meta_InstrumentationLibraryMetrics = Ref{ProtoMeta}()
function meta(::Type{InstrumentationLibraryMetrics})
    ProtoBuf.metalock() do
        if !isassigned(__meta_InstrumentationLibraryMetrics)
            __meta_InstrumentationLibraryMetrics[] =
                target = ProtoMeta(InstrumentationLibraryMetrics)
            allflds = Pair{Symbol,Union{Type,String}}[
                :instrumentation_library=>opentelemetry.proto.common.v1.InstrumentationLibrary,
                :metrics=>Base.Vector{Metric},
                :schema_url=>AbstractString,
            ]
            meta(
                target,
                InstrumentationLibraryMetrics,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_InstrumentationLibraryMetrics[]
    end
end
function Base.getproperty(obj::InstrumentationLibraryMetrics, name::Symbol)
    if name === :instrumentation_library
        return (obj.__protobuf_jl_internal_values[name])::opentelemetry.proto.common.v1.InstrumentationLibrary
    elseif name === :metrics
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Metric}
    elseif name === :schema_url
        return (obj.__protobuf_jl_internal_values[name])::AbstractString
    else
        getfield(obj, name)
    end
end

mutable struct ResourceMetrics <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function ResourceMetrics(; kwargs...)
        obj = new(meta(ResourceMetrics), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct ResourceMetrics
const __meta_ResourceMetrics = Ref{ProtoMeta}()
function meta(::Type{ResourceMetrics})
    ProtoBuf.metalock() do
        if !isassigned(__meta_ResourceMetrics)
            __meta_ResourceMetrics[] = target = ProtoMeta(ResourceMetrics)
            allflds = Pair{Symbol,Union{Type,String}}[
                :resource=>opentelemetry.proto.resource.v1.Resource,
                :instrumentation_library_metrics=>Base.Vector{
                    InstrumentationLibraryMetrics,
                },
                :schema_url=>AbstractString,
            ]
            meta(
                target,
                ResourceMetrics,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_ResourceMetrics[]
    end
end
function Base.getproperty(obj::ResourceMetrics, name::Symbol)
    if name === :resource
        return (obj.__protobuf_jl_internal_values[name])::opentelemetry.proto.resource.v1.Resource
    elseif name === :instrumentation_library_metrics
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{
            InstrumentationLibraryMetrics,
        }
    elseif name === :schema_url
        return (obj.__protobuf_jl_internal_values[name])::AbstractString
    else
        getfield(obj, name)
    end
end

mutable struct MetricsData <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function MetricsData(; kwargs...)
        obj = new(meta(MetricsData), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) ||
                error(string(typeof(obj), " has no field with name ", fldname))
            if fldval !== nothing
                values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
            end
        end
        obj
    end
end # mutable struct MetricsData
const __meta_MetricsData = Ref{ProtoMeta}()
function meta(::Type{MetricsData})
    ProtoBuf.metalock() do
        if !isassigned(__meta_MetricsData)
            __meta_MetricsData[] = target = ProtoMeta(MetricsData)
            allflds = Pair{Symbol,Union{Type,String}}[:resource_metrics=>Base.Vector{
                ResourceMetrics,
            }]
            meta(
                target,
                MetricsData,
                allflds,
                ProtoBuf.DEF_REQ,
                ProtoBuf.DEF_FNUM,
                ProtoBuf.DEF_VAL,
                ProtoBuf.DEF_PACK,
                ProtoBuf.DEF_WTYPES,
                ProtoBuf.DEF_ONEOFS,
                ProtoBuf.DEF_ONEOF_NAMES,
            )
        end
        __meta_MetricsData[]
    end
end
function Base.getproperty(obj::MetricsData, name::Symbol)
    if name === :resource_metrics
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{ResourceMetrics}
    else
        getfield(obj, name)
    end
end

export AggregationTemporality,
    DataPointFlags,
    MetricsData,
    ResourceMetrics,
    InstrumentationLibraryMetrics,
    Metric,
    Gauge,
    Sum,
    Histogram,
    ExponentialHistogram,
    Summary,
    NumberDataPoint,
    HistogramDataPoint,
    ExponentialHistogramDataPoint_Buckets,
    ExponentialHistogramDataPoint,
    SummaryDataPoint_ValueAtQuantile,
    SummaryDataPoint,
    Exemplar


text:
using SatelliteToolbox
using Dates
using LinearAlgebra

"""
external_model(current_time,r_ecef, r_geod, cal_year=2020)

衛星外環境モデルに関わる全ての計算

# Arguments
- `current_time`: 現在時刻
- `r_ecef`: 衛星位置@ECEF
- `r_geod`: 衛星位置@Geodetic
- `cal_year`: 2020

# Returns
- `mag_vec_ecef`: 地磁場方向ベクトル@ECEF
- `sun_vecs`: 太陽方向ベクトル@SEOF
- `atoms_dens`: 大気密度スカラー

"""
function external_model(current_time,r_ecef, r_geod,r_eci_1st, eop_IAU2000A, sunvector_index, cal_year=2020)
    # 筑波大 総合研究棟B r_ecef = [3.957729931663941e6,3.3091914769971482e6,3.737926200042794e6]

    # ユリウス通日への変換
    jd = DatetoJD(current_time)

    # 地磁場ベクトル計算 @Geodetic to Geocentric
    # X軸：右手形をなすように設定
    # Y軸：東
    # Z軸：地球中心
    geoc_lat, geoc_h = GeodetictoGeocentric(r_geod[1], r_geod[3])
    mag_vec_geoc = igrf12(cal_year,geoc_h,geoc_lat,r_geod[2],Val{:geocentric})

    # mag_vec_geocのECEFへの変換
    # DCMの取得
    ez = - r_ecef/ norm(r_ecef,2) # 地球中心方向をz軸の単位ベクトルに
    ey = cross(ez,[0,0,1]) # ECEFのz軸との外積をy軸の単位ベクトルに
    ex = cross(ey,ez)
    C = DCM([ex;ey;ez])
    mag_vec_ecef = C * mag_vec_geoc

    # 太陽方向ベクトルの計算
     # 基準ベクトル(シミュレーション初期衛星位置@ECI)とのなす角を求める
    r_eci = rECEFtoECI(ITRF(), GCRF(), jd, eop_IAU2000A)*r_ecef
    cθ = dot(r_eci_1st,r_eci) / (norm(r_eci_1st)*norm(r_eci))
    rcross = cross(r_eci_1st, r_eci)
    if cθ > 1
        θ = π/2
    else
        θ = acos(cθ)
    end
    if rcross[3] < 0
        θ = 2π - θ
    end
     # indexからどの要素を抜き出すか
    index_num = round(Int64, 10*rad2deg(θ)) +1
    sun_vecs = sunvector_index[index_num, 2:4]

    # 大気密度計算
    atoms_dens = expatmosphere(ECEFtoGeodetic(r_ecef)[3])

    return mag_vec_ecef, sun_vecs, atoms_dens
end

"""
sun_vec = sunvector_model(JD_log, tles)

太陽方向ベクトルの計算

# Arguments
- `JD_1st`: シミュレート開始時刻＠ユリウス日
- `tles`: シミュレートに用いるTLE情報 SatelliteToolbox.read_tle(Name)の出力形式

# Returns
- `sun_vec`: 衛星位置 - 太陽方向ベクトル@SEOF座標系 対応の行列
             1列目が衛星位置　（時刻JD_1stにおける衛星位置ベクトルとのなす角
             2-4列目がx,y,z方向成分

"""
function sunvector_model(JD_1st, tles)
    μ = 3.98600441* (10^14)  # 重力定数
    a = (μ / ((tles[1].n * 2π / 86400)^2))^(1/3)  # 軌道長半径

     # x方向成分
    sun_angle_xp = satellite_sun_angle_earth_pointing(JD_1st, a, tles[1].e, tles[1].i, tles[1].M, tles[1].Ω, 1, [1, 0, 0])
    sun_angle_xm = satellite_sun_angle_earth_pointing(JD_1st, a, tles[1].e, tles[1].i, tles[1].M, tles[1].Ω, 1, [-1, 0, 0])
    sun_vec = zeros(length(sun_angle_xp), 4)

    #位置情報
    for i = 2:length(sun_angle_xp)
        sun_vec[i, 1] = sun_vec[i-1, 1] + 0.1
    end

    # x方向成分
    for i = 1:length(sun_angle_xp)
        if isnan(sun_angle_xp[i]) && isnan(sun_angle_xm[i])
            sun_vec[i, 2] = 0.
        elseif isnan(sun_angle_xp[i])
            sun_vec[i, 2] = -1*cos(sun_angle_xm[i])
        else
            sun_vec[i, 2] = cos(sun_angle_xp[i])
        end
    end

    # y方向成分
    sun_angle_yp = satellite_sun_angle_earth_pointing(JD_1st, a, tles[1].e, tles[1].i, tles[1].M, tles[1].Ω, 1, [0, 1, 0])
    sun_angle_ym = satellite_sun_angle_earth_pointing(JD_1st, a, tles[1].e, tles[1].i, tles[1].M, tles[1].Ω, 1, [0, -1, 0])
    for i = 1:length(sun_angle_yp)
        if isnan(sun_angle_yp[i]) && isnan(sun_angle_ym[i])
            sun_vec[i, 3] = 0.
        elseif isnan(sun_angle_yp[i])
            sun_vec[i, 3] = -1*cos(sun_angle_ym[i])
        else
            sun_vec[i, 3] = cos(sun_angle_yp[i])
        end
    end

    # z方向成分
    sun_angle_zp = satellite_sun_angle_earth_pointing(JD_1st, a, tles[1].e, tles[1].i, tles[1].M, tles[1].Ω, 1, [0, 0, 1])
    sun_angle_zm = satellite_sun_angle_earth_pointing(JD_1st, a, tles[1].e, tles[1].i, tles[1].M, tles[1].Ω, 1, [0, 0, -1])
    for i = 1:length(sun_angle_zp)
        if isnan(sun_angle_zp[i]) && isnan(sun_angle_zm[i])
            sun_vec[i, 4] = 0.
        elseif isnan(sun_angle_zp[i])
            sun_vec[i, 4] = -1*cos(sun_angle_zm[i])
        else
            sun_vec[i, 4] = cos(sun_angle_zp[i])
        end
    end

    return sun_vec

end

max_stars_repo_name: yui-project/ACSim

max_issues_repo_name: yui-project/ACSim

max_forks_repo_name: yui-project/ACSim


text:
mutable struct GPLA{BD, AD, X<:AbstractMatrix, Y<:AbstractVector, M<:GaussianProcesses.Mean, K<:GaussianProcesses.Kernel, NOI<:GaussianProcesses.Param} <: GaussianProcesses.GPBase
    x::X
    y::Y
    k::Int64 #Local Neighborhood Size

    #=
    action_dims::Int64
    belief_dims::Int64
    dim::Int64
    =#

    mean::M
    kernel::K
    logNoise::NOI

    kdtree::KDTree

    "Auxiliary variables used to optimize GP hyperparameters"
    data::GaussianProcesses.KernelData
    mll::Float64
    dmll::Vector{Float64}
    target::Float64
    dtarget::Vector{Float64}
    function GPLA{BD, AD, X, Y, M, K, NOI}(x::X, y::Y, k::Int64, mean::M, kernel::K, logNoise::NOI) where {BD, AD, X, Y, N, M, K, NOI}
        data = GaussianProcesses.KernelData(kernel, x, x)
        tree = KDTree(zeros(Float64, AD + BD, 0), Euclidean())
        gp = new{BD, AD, X, Y, M, K, NOI}(ElasticArray(x), ElasticArray(y), k, mean, kernel, logNoise, tree, data)
        initialize!(gp)
    end
end

function GPLA(x::AbstractMatrix, y::AbstractVector, k::Integer, action_dims::Integer, belief_dims::Integer, mean::GaussianProcesses.Mean, kernel::GaussianProcesses.Kernel, logNoise::Real)
    lns = GaussianProcesses.wrap_param(logNoise)
    size_x = size(x, 2)
    GPLA{belief_dims, action_dims, typeof(x),typeof(y),typeof(mean),typeof(kernel), typeof(lns)}(x, y, k, mean, kernel, lns)
end

beliefdim(::GPLA{BD}) where BD = BD
actiondim(::GPLA{BD, AD}) where {BD, AD} = AD

function initialize!(gp::GPLA)
    n_obs = size(gp.y, 1)
    if n_obs != 0
        gp.kdtree = KDTree(gp.x)
        update_mll!(gp)
    end
    return gp
end

function GaussianProcesses.predict_f(gp::GPLA, x::AbstractArray{T,2} where T)
    nx = size(gp.x, 2)
    if nx <= gp.k
        mx = GaussianProcesses.mean(gp.mean, gp.x)
        mf = GaussianProcesses.mean(gp.mean, x)
        Kxf = GaussianProcesses.cov(gp.kernel, x, gp.x) #size(size(x,2) x nx)
        Kff = GaussianProcesses.cov(gp.kernel, x, x) .+ exp(2*gp.logNoise.value) .+ eps()
        y = gp.y - mx
        data = GaussianProcesses.KernelData(gp.kernel, gp.x, gp.x)
        Σ = GaussianProcesses.cov(gp.kernel, gp.x, gp.x, data) + Matrix(I, nx, nx).*(exp(2*gp.logNoise.value)+eps())
        cK = PDMat(GaussianProcesses.make_posdef!(Σ)...)
        α = reshape(cK \ y, nx, 1)
        β = cK \ transpose(Kxf)
        μ = mf + Kxf*α
        σ² = diag(Kff - Kxf*β)
    else
        sx = NearestNeighbors.copy_svec(Float64, extract_value(x), Val(beliefdim(gp) + actiondim(gp)))
        neighbors, _ = knn(gp.kdtree, sx, gp.k, true)
        μ = zeros(eltype(x), size(x, 2), 1)
        σ² = zeros(eltype(x), size(x, 2), 1)
        for i = 1:size(x,2)
            x_obs = gp.x[:, neighbors[i]]
            y_obs = gp.y[neighbors[i]]
            m, s = predict_local(x[:,i:i], x_obs, y_obs, gp.mean, gp.kernel, gp.logNoise)
            μ[i, 1] = m
            σ²[i, 1] = s
        end
    end
    return μ, σ²
end

function predict_local(x, x_obs, y_obs, mean, kernel, logNoise)
    k = size(x_obs, 2)
    sample_mean = Statistics.mean(y_obs)
    mx = zero(y_obs) .+ Statistics.mean(y_obs)
    mf = sample_mean
    Kxf = GaussianProcesses.cov(kernel, x, x_obs)
    Kff = GaussianProcesses.cov(kernel, x, x) .+ exp(2*logNoise.value) .+ eps()

    y_obs = reshape(y_obs - mx, size(y_obs, 1), 1)
    data = GaussianProcesses.KernelData(kernel, x_obs, x_obs)
    Σ = GaussianProcesses.cov(kernel, x_obs, x_obs, data) + Matrix(I, k, k).*(exp(2*logNoise.value)+eps())
    Kxx = PDMat(GaussianProcesses.make_posdef!(Σ)...)
    μ = mf + GaussianProcesses.dot(Kxf, Kxx \ y_obs)
    Σ = Kff - Kxf*(Kxx \ transpose(Kxf))
    σ² = max(Σ[1], 0.0)
    return μ, σ²
end

function mll_local(idx, gp, mx, neighbors)
    if idx in neighbors
        neighbors = neighbors[neighbors .!= idx]
    else
        neighbors = neighbors[1:end-1]
    end
    k = length(neighbors)

    x = gp.x[:,idx:idx]
    x_obs = gp.x[:, neighbors]
    y_obs = gp.y[neighbors] - mx[neighbors]
    y_obs = reshape(y_obs, size(y_obs, 1), 1)

    mf = mx[idx]
    Kxf = GaussianProcesses.cov(gp.kernel, x, x_obs)
    Kff = GaussianProcesses.cov(gp.kernel, x, x) .+ exp(2*gp.logNoise.value) .+ eps()

    data = GaussianProcesses.KernelData(gp.kernel, x_obs, x_obs)
    Σ = GaussianProcesses.cov(gp.kernel, x_obs, x_obs, data) + Matrix(I, gp.k, gp.k).*(exp(2*gp.logNoise.value)+eps())
    Kxx = PDMat(GaussianProcesses.make_posdef!(Σ)...)
    μ = mf + GaussianProcesses.dot(Kxf, Kxx \ y_obs)
    Σ = Kff - Kxf*(Kxx \ transpose(Kxf))
    σ² = max(Σ[1], 0.0)
    σ = sqrt(σ²)
    log_p = -0.5*((gp.y[idx] - μ)/σ)^2 - 0.5*log(2*pi) - log(σ)
    param_tuple = (μ = μ, σ²  = σ², Kxx = Kxx, Kxf = Kxf, Kff = Kff, mf = mf, y = y_obs, neighbors = neighbors)
    return log_p, param_tuple
end

function update_mll!(gp::GPLA)
    nx = size(gp.x, 2)
    μ = GaussianProcesses.mean(gp.mean, gp.x)
    if nx <= gp.k
        y = gp.y - μ
        data = GaussianProcesses.KernelData(gp.kernel, gp.x, gp.x)
        Σ = GaussianProcesses.cov(gp.kernel, gp.x, gp.x, data) + Matrix(I, nx, nx).*(exp(2*gp.logNoise.value)+eps())
        cK = PDMat(GaussianProcesses.make_posdef!(Σ)...)
        α = cK \ y
        gp.mll = - (GaussianProcesses.dot(y, α) + GaussianProcesses.logdet(cK) + log(2*pi) * nx) / 2
    else
        mx = GaussianProcesses.mean(gp.mean, gp.x)
        neighbors, _ = knn(gp.kdtree, extract_value(gp.x), gp.k + 1)
        gp.mll = 0.0
        for i = 1:nx
            log_p, _ = mll_local(i, gp, mx, neighbors[i])
            gp.mll += log_p
        end
    end
end

"""
     update_dmll!(gp::GPE, ...)
Update the gradient of the marginal log-likelihood of Gaussian process `gp`.
"""
function update_dmll!(gp::GPLA;
                    noise::Bool=true, # include gradient component for the logNoise term
                    domean::Bool=true, # include gradient components for the mean parameters
                    kern::Bool=true, # include gradient components for the spatial kernel parameters
                    )
    n_mean_params = GaussianProcesses.num_params(gp.mean)
    n_kern_params = GaussianProcesses.num_params(gp.kernel)
    gp.dmll = zeros(Float64, noise + domean * n_mean_params + kern * n_kern_params)
    nobs = size(gp.y, 1)
    μ = GaussianProcesses.mean(gp.mean, gp.x)
    neighbors, _ = knn(gp.kdtree, gp.x, gp.k + 1)
    for i = 1:nobs
        _, params = mll_local(i, gp, μ, neighbors[i])
        d_dmll = zeros(Float64, noise + domean * n_mean_params + kern * n_kern_params)
        dmll_local!(d_dmll, gp, i, n_mean_params, n_kern_params, params; noise = noise, domean = domean, kern = kern)
        gp.dmll += d_dmll
    end
end

function dmll_local!(dmll::AbstractVector, gp::GPLA, idx::Int64, n_mean_params, n_kern_params, params;
                noise::Bool=true, domean::Bool=true, kern::Bool=true)
    i=1
    if noise
        @assert GaussianProcesses.num_params(gp.logNoise) == 1
        dmll[i] = dmll_noise(gp, idx, params)
        i += 1
    end
    if domean && n_mean_params>0
        dmll_m = @view(dmll[i:i+n_mean_params-1])
        dmll_mean!(dmll_m, gp, idx, params)
        i += n_mean_params
    end
    if kern
        dmll_k = @view(dmll[i:end])
        dmll_kern!(dmll_k, gp, idx, params)
    end
    return dmll
end

function dmll_noise(gp::GPLA, idx::Int64, params::NamedTuple)
    y = gp.y[idx]
    Knoise = diagm(repeat([2*exp(2*gp.logNoise.value)], gp.k))
    σ = sqrt(params.σ²) + eps()
    dμ = -dot(params.Kxf, params.Kxx \ Knoise * (params.Kxx \ params.y))
    dσ = dot(params.Kxf[1,:], params.Kxx \ Knoise * (params.Kxx \ params.Kxf[1,:])) + 2*exp(2*gp.logNoise.value)
    dσ /= σ*2.0
    dlog_p = -(y - params.μ)/σ*(-dμ/σ - (y - params.μ)/params.σ²*dσ)
    dlog_p -= dσ/σ
    return dlog_p
end

function dmll_mean!(dmll::AbstractVector, gp::GPLA, idx::Int64, params::NamedTuple)
    y = gp.y[idx]
    x = gp.x[:,idx:idx]
    d_mean = -ones(Float64, gp.k)
    σ = sqrt(params.σ²) + eps()
    dμ = GaussianProcesses.grad_stack(gp.mean, x)*(1.0 + GaussianProcesses.dot(params.Kxf, params.Kxx \ d_mean))
    dσ = [0.0]
    dlog_p = -(y - params.μ)/σ*(-dμ/σ - (y - params.μ)/params.σ²*dσ)
    dlog_p -= dσ/σ

    for i in 1:length(dlog_p)
        dmll[i] = dlog_p[i]
    end
    return dmll
end

function dmll_kern!(dmll::AbstractVector, gp::GPLA, idx::Int64, params::NamedTuple)
    y = gp.y[idx]
    x = gp.x[:,idx:idx]
    dKxx = grad_stack(gp.kernel, gp.x[:,params.neighbors], gp.x[:,params.neighbors])
    dKff = grad_stack(gp.kernel, x, x)[1, 1, :]
    dKxf = grad_stack(gp.kernel, x, gp.x[:,params.neighbors])[1,:,:]
    σ = sqrt(params.σ²) + eps()
    for i in 1:size(dKxf,2)
        dμ = GaussianProcesses.dot(dKxf[:,i], params.Kxx \ params.y)
        dμ -= GaussianProcesses.dot(params.Kxf, (params.Kxx \ dKxx[:,:,i]) * (params.Kxx \ params.y))
        dσ = dKff[i] - GaussianProcesses.dot(dKxf[:,i], params.Kxx \ params.Kxf[1,:])
        dσ += GaussianProcesses.dot(params.Kxf[1,:], (params.Kxx \ dKxx[:,:,i]) * (params.Kxx \ params.Kxf[1,:]))
        dσ -= GaussianProcesses.dot(params.Kxf[1,:], params.Kxx \ dKxf[:,i])
        dσ /= σ*2.0
        dlog_p = -(y - params.μ)/σ*(-dμ/σ - (y - params.μ)/params.σ²*dσ)
        dlog_p -= dσ/σ
        dmll[i] = dlog_p
    end
    return dmll
end

function update_mll_and_dmll!(gp::GPLA, precomp; kwargs...)
    update_mll!(gp)
    update_dmll!(gp; kwargs...)
end

function GaussianProcesses.update_target_and_dtarget!(gp::GPLA, precomp; params_kwargs...)
    update_mll_and_dmll!(gp, precomp; params_kwargs...)
    gp.target = gp.mll
    gp.dtarget = gp.dmll
end

function grad_stack(k::GaussianProcesses.Kernel, X1::AbstractMatrix, X2::AbstractMatrix)
    data = GaussianProcesses.KernelData(k, X1, X2)
    nobs1 = size(X1, 2)
    nobs2 = size(X2, 2)
    stack = Array{eltype(X1)}(undef, nobs1, nobs2, GaussianProcesses.num_params(k))
    GaussianProcesses.grad_stack!(stack, k, X1, X2, data)
end

function extract_value(x::Array)
    x_out = zeros(Float64, size(x, 1), size(x, 2))
    for j = 1:size(x,2)
        for i = 1:size(x,1)
            if x[i, j] isa AbstractFloat
                x_out[i, j] = convert(Float64, x[i, j])
            else
                x_out[i, j] = convert(Float64, x[i, j].value)
            end
        end
    end
    return x_out
end

GaussianProcesses.get_params_kwargs(::GPLA; kwargs...) = delete!(Dict(kwargs), :lik)

function GaussianProcesses.get_params(gp::GPLA; noise::Bool=true, domean::Bool=true, kern::Bool=true)
    params = Float64[]
    if noise; append!(params, GaussianProcesses.get_params(gp.logNoise)); end
    if domean
        append!(params, GaussianProcesses.get_params(gp.mean))
    end
    if kern
        append!(params, GaussianProcesses.get_params(gp.kernel))
    end
    return params
end

function GaussianProcesses.optimize!(gp::GPLA; method = GaussianProcesses.LBFGS(), domean::Bool = true, kern::Bool = true,
                   noise::Bool = true, lik::Bool = true,
                   meanbounds = nothing, kernbounds = nothing,
                   noisebounds = nothing, likbounds = nothing, kwargs...)
    params_kwargs = GaussianProcesses.get_params_kwargs(gp; domean=domean, kern=kern, noise=noise, lik=lik)
    func = GaussianProcesses.get_optim_target(gp; params_kwargs...)
    init = GaussianProcesses.get_params(gp; params_kwargs...)  # Initial hyperparameter values
    # try
        if meanbounds == kernbounds == noisebounds == likbounds == nothing
            results = Optim.optimize(func, init; method=method, kwargs...)
        else
            lb, ub = GaussianProcesses.bounds(gp, noisebounds, meanbounds, kernbounds, likbounds;
                            domean = domean, kern = kern, noise = noise, lik = lik)
            results = GaussianProcesses.optimize(func.f, func.df, lb, ub, init, Fminbox(method))
        end
        GaussianProcesses.set_params!(gp, Optim.minimizer(results); params_kwargs...)
        return results
end

function GaussianProcesses.set_params!(gp::GPLA, hyp::AbstractVector;
                     noise::Bool=true, domean::Bool=true, kern::Bool=true)
    n_noise_params = GaussianProcesses.num_params(gp.logNoise)
    n_mean_params = GaussianProcesses.num_params(gp.mean)
    n_kern_params = GaussianProcesses.num_params(gp.kernel)

    i = 1
    if noise
        GaussianProcesses.set_params!(gp.logNoise, hyp[1:n_noise_params])
        i += n_noise_params
    end

    if domean && n_mean_params>0
        GaussianProcesses.set_params!(gp.mean, hyp[i:i+n_mean_params-1])
        i += n_mean_params
    end

    if kern
        GaussianProcesses.set_params!(gp.kernel, hyp[i:i+n_kern_params-1])
        i += n_kern_params
    end
end

function GaussianProcesses.get_optim_target(gp::GPLA; params_kwargs...)
    function ltarget(hyp::AbstractVector)
        prev = GaussianProcesses.get_params(gp; params_kwargs...)
        try
            GaussianProcesses.set_params!(gp, hyp; params_kwargs...)
            update_mll!(gp)
            return -gp.mll
        catch err
            # reset parameters to remove any NaNs
            GaussianProcesses.set_params!(gp, prev; params_kwargs...)

            if !all(isfinite.(hyp))
                println(err)
                return Inf
            elseif isa(err, ArgumentError)
                println(err)
                return Inf
            elseif isa(err, LinearAlgebra.PosDefException)
                println(err)
                return Inf
            else
                throw(err)
            end
        end
    end
    function ltarget_and_dltarget!(grad::AbstractVector, hyp::AbstractVector)
        prev = GaussianProcesses.get_params(gp; params_kwargs...)
        try
            GaussianProcesses.set_params!(gp, hyp; params_kwargs...)
            update_mll!(gp)
            update_dmll!(gp; params_kwargs...)
            grad[:] = -gp.dmll
            return -gp.mll
        catch err
            # reset parameters to remove any NaNs
            GaussianProcesses.set_params!(gp, prev; params_kwargs...)
            if !all(isfinite.(hyp))
                println(err)
                return Inf
            elseif isa(err, ArgumentError)
                println(err)
                return Inf
            elseif isa(err, LinearAlgebra.PosDefException)
                println(err)
                return Inf
            else
                throw(err)
            end
        end
    end

    function dltarget!(grad::AbstractVector, hyp::AbstractVector)
        ltarget_and_dltarget!(grad::AbstractVector, hyp::AbstractVector)
    end
    xinit = GaussianProcesses.get_params(gp; params_kwargs...)
    func = GaussianProcesses.OnceDifferentiable(ltarget, dltarget!, ltarget_and_dltarget!, xinit)
    return func
end

function GaussianProcesses.init_precompute(gp::GPLA) nothing end


text:
using MixedSubdivisions
const MS = MixedSubdivisions
import MultivariatePolynomials
const MP = MultivariatePolynomials
import PolynomialTestSystems: equations, cyclic, ipp2, cyclooctane
using Test

@testset "MixedSubdivisions" begin
    @testset "Basic" begin
        A₁ = [0 0 1 1; 0 2 0 1]
        A₂ = [0 0 1 2; 0 1 1 0]

        A = MS.cayley(A₁, A₂)

        @test A == [
            0 0 1 1 0 0 1 2
            0 2 0 1 0 1 1 0
            1 1 1 1 0 0 0 0
            0 0 0 0 1 1 1 1
        ]

        @test_throws ErrorException MS.cayley([1 0; 0 1], [1 0; 0 0; 0 2])

        w₁ = [0, 0, 0, -2]
        w₂ = [0, -3, -4, -8]
        w = [w₁; w₂]

        v₁ = [0, 0, 0, -1]
        v₂ = copy(w₂)
        v = [v₁; v₂]

        mixed_cell_indices = [(2, 3), (1, 3)]
        indexing = MS.CayleyIndexing(size.((A₁, A₂), 2))
        ord = MS.DotOrdering(Int32.(w))
        cell = MS.MixedCellTable(mixed_cell_indices, A, indexing)
        @test cell.volume == 3
        @test cell.circuit_table == [1 2; 3 0; 0 0; 1 -1; 0 3; 1 2; 0 0; -2 -1]
        ineq = MS.first_violated_inequality(cell, v, ord, typemax(Int32))
        @test ineq.config_index == 1
        @test ineq.col_index == 4

        @test MS.exchange_column(cell, MS.exchange_first, ineq, 8) == MS.MixedCellTable(
            [(4, 3), (1, 3)],
            A,
            indexing
        )
        @test MS.exchange_column(cell, MS.exchange_second, ineq, 8) == MS.MixedCellTable(
            [(2, 4), (1, 3)],
            A,
            indexing,
        )

        ind_back = MS.reverse_index(ineq, cell, MS.exchange_second)
        cell2 = MS.exchange_column(cell, MS.exchange_second, ineq, 8)
        @test cell2.volume == 2
        @test cell == MS.exchange_column(cell2, MS.exchange_second, ind_back, 8)

        ind_back = MS.reverse_index(ineq, cell, MS.exchange_first)
        cell2 = MS.exchange_column(cell, MS.exchange_first, ineq, 8)
        @test cell2.volume == 1
        @test cell == MS.exchange_column(cell2, MS.exchange_first, ind_back, 8)
    end

    @testset "Mixed Volume" begin
        @test mixed_volume(equations(cyclic(5))) == 70
        @test mixed_volume(equations(cyclic(7))) == 924
        @test mixed_volume(equations(cyclic(10))) == 35940
        @test mixed_volume(equations(cyclic(11))) == 184756
        @test mixed_volume(equations(ipp2())) == 288

        @test mixed_volume(equations(cyclic(5)), algorithm = :total_degree) == 70
        @test mixed_volume(equations(ipp2()), algorithm = :total_degree) == 288
    end

    @testset "Mixed Cells" begin
        A₁ = [0 0 1 1; 0 2 0 1]
        A₂ = [0 0 1 2; 0 1 1 0]

        A = [A₁, A₂]

        w₁ = [0, 0, 0, 2]
        w₂ = [0, 3, 4, 8]
        w = [w₁, w₂]

        v₁ = [0, 0, 0, 1]
        v₂ = copy(w₂)
        v = [v₁, v₂]

        cells_v = mixed_cells(A, v)
        @test length(cells_v) == 3
        @test sum(volume, cells_v) == 4
        @test sort(volume.(cells_v)) == [1, 1, 2]
        @test all(cells_v) do c
            all(sort.(map(A_i -> A_i' * normal(c), A) .+ v)) do r
                isapprox(r[1], r[2], atol = 1e-12)
            end
        end

        cells_w = mixed_cells(A, w)
        @test length(cells_w) == 2
        @test sum(volume, cells_w) == 4
        @test sort(volume.(cells_w)) == [1, 3]
        @test all(cells_w) do c
            all(sort.(map(A_i -> A_i' * normal(c), A) .+ w)) do r
                isapprox(r[1], r[2], atol = 1e-12)
            end
        end
    end

    @testset "Fine mixed cells" begin
        f = equations(cyclic(7))
        cells, lift = fine_mixed_cells(f)
        @test sum(c -> c.volume, cells) == 924
        @test lift isa Vector{Vector{Int32}}

        @test isnothing(fine_mixed_cells(f, max_tries = 0))
    end

    @testset "Overflow error messages" begin
        f = equations(cyclooctane())
        @test_throws ArgumentError MS.mixed_volume(f)
        F = [f; randn(2, 18) * [MP.variables(f); 1]]
        A = support(F)
        lifting = map(Ai -> rand(-Int32(2^20):Int32(2^20), size(Ai, 2)), A)
        cells = mixed_cells(A, lifting)
        @test_deprecated is_fully_mixed_cell(first(cells), A, lifting)
        @test all(is_fine, cells)
        @test sum(volume, cells) == 32768
        @test sum(volume, first(fine_mixed_cells(F))) == 32768
    end

    @testset "Bugfix#1" begin
        lift = Array{Int32,1}[
            [-312, 347, 823, 901],
            [-1021, -296, -421, -491, -9, 168, -905, -79, -610, -898],
            [489, 385, -540, 612, 792, -986, 697, 695, 842, -731],
            [-126, 677, -699, 96, -270, 186, 263, 75, -765, 68],
            [-230, 173, 142, 531, 218, 668, -305, 177, -710, -94],
            [283, -967, 530, 226, -452, -557, 501, -828],
            [-656, -75, -709, -588],
            [407, 920, 330, 265],
            [157, 2, 524, 417, -449, -897, -19, -603, -209, 257],
            [-683, 763, 1023, 983, -863, -727, 211, -466, 998, -644],
            [-916, 661, 401, 808, 979, -793, -815, 155, -1018, -409],
            [1015, -274, -71, 955, 100, 433, 249, -552],
            [-523, -225, 997, -784, -884],
            [457, -579, 749],
            [624, -74, -563, 861, 86],
            [
             -428,
             75,
             274,
             283,
             691,
             -782,
             513,
             -915,
             -189,
             279,
             793,
             624,
             -741,
             -698,
             -94,
             945,
             -58,
             -164,
            ],
            [
             533,
             -156,
             -488,
             539,
             718,
             724,
             -32,
             -845,
             441,
             -273,
             137,
             511,
             -1005,
             -856,
             -788,
             824,
             279,
             -12,
            ],
        ]
        f = equations(cyclooctane())
        F = [f; randn(2, 18) * [MP.variables(f); 1]]
        A = support(F)
        cells = mixed_cells(A, lift)
        @test !isempty(cells)
        sum(volume, cells) == 32768
    end
end


text:
import Base.round, Base.eltype

# TODO affinehull and sparse

export Representation, HRepresentation, VRepresentation, fulldim
export HRepIterator, EqIterator, IneqIterator, VRepIterator, RayIterator, PointIterator
export Rep
export changeeltype, changefulldim, changeboth, decomposedhfast, decomposedvfast, decomposedfast

abstract Representation{N, T <: Real}
abstract HRepresentation{N,T} <: Representation{N,T}
abstract VRepresentation{N,T} <: Representation{N,T}

typealias  Rep{N,T} Union{ Representation{N,T}, Polyhedron{N,T}}
typealias HRep{N,T} Union{HRepresentation{N,T}, Polyhedron{N,T}}
typealias VRep{N,T} Union{VRepresentation{N,T}, Polyhedron{N,T}}

Base.copy(rep::Rep)            = error("copy not implemented for $(typeof(rep))")

decomposedhfast(p::Polyhedron)          = error("decomposedhfast not implemented for $(typeof(p))")
decomposedvfast(p::Polyhedron)          = error("decomposedvfast not implemented for $(typeof(p))")
decomposedfast(rep::HRepresentation)      = error("decomposedfast not implemented for $(typeof(rep))")
decomposedfast(rep::VRepresentation)      = error("decomposedfast not implemented for $(typeof(rep))")
decomposedhfast(rep::HRepresentation)     = decomposedfast(rep)
decomposedvfast(rep::VRepresentation)     = decomposedfast(rep)

removevredundancy!(p::VRep)               = error("removevredundancy! not implemented for $(typeof(p))")
isvredundant(p::VRep, i::Integer; strongly=false, cert=false, solver = defaultLPsolverfor(p))         = error("not implemented for $(typeof(p))")
detectvlinearies!(p::VRep)                = error("detectvlinearities! not implemented for $(typeof(p))")

removehredundancy!(p::HRep)               = error("removehredundancy! not implemented for $(typeof(p))")
ishredundant(p::HRep, i::Integer; strongly=false, cert=false, solver = defaultLPsolverfor(p))         = error("ishredundant not implemented for $(typeof(p))")
detecthlinearities!(p::HRep)              = error("detecthlinearities! not implemented for $(typeof(p))")

Base.eltype{N,T}(rep::Rep{N,T}) = T
fulldim{N}(rep::Rep{N}) = N
Base.eltype{RepT<:Rep}(::Type{RepT}) = RepT.parameters[2]
fulldim{RepT<:Rep}(::Type{RepT}) = RepT.parameters[1]

# type EmptyIterator{N,T}
# end
# length(it::VRepIterator) = 0
# isempty(it::VRepIterator) = true
# eltype{N,T}(it::VRepIterator{N,T}) = T
# start(it::VRepIterator) = 0
# done(it::VRepIterator, state) = true
# next(it::VRepIterator, state) = error("This iterator is empty")

function checknext(it, i, state, donep, startp)
  while i <= length(it.ps) && (i == 0 || donep(it.ps[i], state))
    i += 1
    if i <= length(it.ps)
      state = startp(it.ps[i])
    end
  end
  i > length(it.ps) ? i : (i, state)
end

# convention: ax <= β
for (rep, HorVRep, low) in [(true, :VRep, "vrep"), (false, :VRep, "point"), (false, :VRep, "ray"), (true, :HRep, "hrep"), (false, :HRep, "ineq"), (false, :HRep, "eq")]
  if rep
    up = uppercase(low[1:2]) * low[3:end]
    shortcut = Symbol(low)
    isemp = Symbol("has" * low)
  else
    up = uppercase(low[1:1]) * low[2:end]
    shortcut = Symbol(low * "s")
    isemp = Symbol("has" * low * "s")
  end
  typename = Symbol(up * "Iterator")
  donep = Symbol("done" * low)
  startp = Symbol("start" * low)
  nextp = Symbol("next" * low)
  lenp = Symbol("n" * low * "s")

  @eval begin
    if !$rep
      $lenp(p::$HorVRep)   = error("$lenp not implemented")
      $startp(p::$HorVRep) = error("$startp not implemented")
      $donep(p::$HorVRep)  = error("$donep not implemented")
      $nextp(p::$HorVRep)  = error("$nextp not implemented")
    end

    type $typename{Nout, Tout, Nin, Tin}
      ps::Vector{$HorVRep{Nin, Tin}}
      f::Nullable{Function}
    end
    $typename{RepT<:$HorVRep}(ps::Vector{RepT}, f::Function=nothing) = $typename{fulldim(RepT),eltype(RepT),fulldim(RepT),eltype(RepT)}(ps, f)
    $shortcut{N,T}(p::$HorVRep{N,T}, f::Function=nothing) = $typename([p], f)

    Base.length(it::$typename) = sum([$lenp(p) for p in it.ps])
    Base.isempty(it::$typename) = reduce(&, true, [$isemp(p) for p in it.ps])
    fulldim{N}(it::$typename{N}) = N
    Base.eltype{N,T}(it::$typename{N,T}) = T

    Base.start(it::$typename) = checknext(it, 0, nothing, $donep, $startp)
    Base.done(it::$typename, state) = state[1] > length(it.ps)
    function Base.next(it::$typename, state)
      item, newsubstate = $nextp(it.ps[state[1]], state[2])
      newstate = checknext(it, state[1], newsubstate, $donep, $startp)
      (isnull(it.f) ? item : get(it.f)(state[1], item), newstate)
    end

  end
end

# Default implementation for hrep and vrep
function checknext(rep::Rep, i, state, donep, startp)
  while i <= 2 && (i == 0 || donep[i](rep, state))
    i += 1
    if i <= 2
      state = startp[i](rep)
    end
  end
  i > 2 ? i : (i, state)
end

#HRep
Base.length(hrep::HRepresentation)  = nhreps(hrep)
Base.isempty(hrep::HRepresentation) = hashreps(hrep)

nhreps(hrep::HRep) = neqs(hrep) + nineqs(hrep)

haseqs(hrep::HRep)   = neqs(hrep) > 0
hasineqs(hrep::HRep) = nhrep(hrep) > 0
hashreps(hrep::HRep) = nhrep(hrep) > 0

starthrep(hrep::HRep) = checknext(hrep, 0, nothing, [doneeq, doneineq], [starteq, startineq])
donehrep(hrep::HRep, state) = state[1] > 2
function nexthrep(hrep::HRep, state)
  nextp = [nexteq, nextineq]
  item, newsubstate = nextp[state[1]](hrep, state[2])
  newstate = checknext(hrep, state[1], newsubstate, [doneeq, doneineq], [starteq, startineq])
  (item, newstate)
end

#VRep
Base.length(vrep::VRepresentation)  = nvreps(vrep)
Base.isempty(vrep::VRepresentation) = hasvreps(vrep)

nvreps(vrep::VRep) = nrays(vrep) + npoints(vrep)

hasrays(vrep::VRep)   = nrays(vrep) > 0
haspoints(vrep::VRep) = npoints(vrep) > 0
hasvreps(vrep::VRep)  = nvreps(vrep) > 0

startvrep(vrep::VRep) = checknext(vrep, 0, nothing, [doneray, donepoint], [startray, startpoint])
donevrep(vrep::VRep, state) = state[1] > 2
function nextvrep(vrep::VRep, state)
  nextp = [nextray, nextpoint]
  item, newsubstate = nextp[state[1]](vrep, state[2])
  newstate = checknext(vrep, state[1], newsubstate, [doneray, donepoint], [startray, startpoint])
  (item, newstate)
end

# Linearity Set
function linset(rep::HRepresentation)
  s = IntSet()
  for (i,h) in enumerate(hrep(rep))
    if islin(h)
      push!(s, i)
    end
  end
  s
end
function linset(rep::VRepresentation)
  s = IntSet()
  for (i,v) in enumerate(vrep(rep))
    if islin(v)
      push!(s, i)
    end
  end
  s
end

# Modify type
changeeltype{RepT<:Rep,T}(::Type{RepT}, ::Type{T})  = error("changeeltype not implemented for $(RepT)")
changefulldim{RepT<:Rep}(::Type{RepT}, N)           = error("changefulldim not implemented for $(RepT)")
changeboth{RepT<:Rep,T}(::Type{RepT}, N, ::Type{T}) = error("changeboth not implemented for $(RepT)")

# Conversion
changeeltype{S,N}(::Type{S}, x::HalfSpace{N}) = HalfSpace{N,S}(changeeltype(S, x.a), S(β))
changeeltype{S,N}(::Type{S}, x::HyperPlane{N}) = HyperPlane{N,S}(changeeltype(S, x.a), S(β))

changeeltype{S,N}(::Type{S}, x::Vec{N}) = Vec{N,S}(x)
changeeltype{S,N}(::Type{S}, x::Ray{N}) = Ray{N,S}(changeeltype(S, x.r))
changeeltype{S,N}(::Type{S}, x::Line{N}) = Line{N,S}(changeeltype(S, x.r))
changeeltype{S,N}(::Type{S}, x::Point{N}) = Point{N,S}(x)
changeeltype{S,N}(::Type{S}, x::SymPoint{N}) = SymPoint{N,S}(changeeltype(S, x))
changeeltype{S}(::Type{S}, x::AbstractVector) = AbstractVector{S}(x)

# This method solves the ambiguity with the following methods and the general method
# Base.convert{T}(::Type{T}, p::T) = p
Base.convert{T<:HRepresentation}(::Type{T}, p::T) = p
Base.convert{T<:VRepresentation}(::Type{T}, p::T) = p
function Base.convert{RepTout<:HRep, RepTin<:HRepresentation}(::Type{RepTout}, p::RepTin)
  Nin  = fulldim(RepTin)
  Nout = fulldim(RepTout)
  if Nin != Nout
    error("Different dimension")
  end
  Tin  = eltype(RepTin)
  Tout = eltype(RepTout)
  if Tin == Tout
    f = nothing
  else
    f = (i,x) -> changeeltype(typeof(x), Tout)(x)
  end
  if decomposedfast(p)
    RepTout(eqs=EqIterator{Nout,Tout,Nin,Tin}([p], f), ineqs=IneqIterator{Nout,Tout,Nin,Tin}([p], f))
  else
    RepTout(HRepIterator{Nout,Tout,Nin,Tin}([p], f))
  end
end
function Base.convert{Tout<:VRep, Tin<:VRepresentation}(::Type{Tout}, p::Tin)
  if fulldim(Tout) != fulldim(Tin)
    error("Different dimension")
  end
  if eltype(Tout) == eltype(Tin)
    f = nothing
  else
    f = (i,x) -> changeeltype(typeof(x), eltype(Tout))(x)
  end
  if decomposedfast(p)
    Tout(points=points(p, f), rays=rays(p, f))
  else
    Tout(vrep(p, f))
  end
end

function Base.convert{N, T, RepT<:Representation}(::Type{Representation{N, T}}, rep::RepT)
  if fulldim(RepT) != N
    error("Cannot convert representations of the same dimension")
  end
  Base.convert(changeeltype(RepT, T), rep)
end
function Base.convert{N, T, RepT<:HRepresentation}(::Type{HRepresentation{N, T}}, rep::RepT)
  if fulldim(RepT) != N
    error("Cannot convert representations of the same dimension")
  end
  Base.convert(changeeltype(RepT, T), rep)
end
function Base.convert{N, T, RepT<:VRepresentation}(::Type{VRepresentation{N, T}}, rep::RepT)
  if fulldim(RepT) != N
    error("Cannot convert representations of the same dimension")
  end
  Base.convert(changeeltype(RepT, T), rep)
end

# Show
function Base.show{N,T}(io::IO, rep::Representation{N,T})
  if typeof(rep) <: HRepresentation
    print(io, "H")
  else
    print(io, "V")
  end
  println(io, "-representation")

  if haseqs(rep)
    print(io, "linearity $(neqs(rep))");
    for i in linset(rep)
      print(io, " $i")
    end
    println(io)
  end

  println(io, "begin")
  if T <: AbstractFloat
    typename = "real"
  elseif T <: Integer
    typename = "integer"
  else
    typename = "rational"
  end
  println(io, " $(length(rep)) $(N+1) $typename")
  if rep <: HRepresentation
    for h in hrep(rep)
      print(io, " $(h.β)")
      for j = 1:N
        print(io, " $(h.a[j])")
      end
      println(io)
    end
  else
    for v in vrep(rep)
      print(io, " $(Int(isray(v)))")
      for j = 1:N
        print(io, " $(v[j])")
      end
      println(io)
    end
  end
  print(io, "end")
end


text:
# File: require.jl
# Author: Jannis Harder
# Description: Allows types to be reloaded
# Provides: @reloadable

macro reloadable(typ)
    assert(typ.head == :type)
    name = typ.args[1]
    if isa(name, Expr)
        name = name.args[1]
    end
    hidden_name = symbol(strcat("#", name, "#", hash(string(typ))))
    already_defined = false
    try
        eval(hidden_name)
        already_defined = true
    end
    if !already_defined
        typ_hidden = expr_replace_sym(typ, name, hidden_name)
        quote
            global $hidden_name
            $typ_hidden
            global $name = $hidden_name
        end
    else
        quote
            global $name = $hidden_name
        end
    end
end

expr_replace_sym(exp::Symbol, a::Symbol, b::Symbol) = exp == a ? b : exp

function expr_replace_sym(exp::Expr, a::Symbol, b::Symbol)
    expr(exp.head, map(x -> expr_replace_sym(x, a, b), exp.args))
end
expr_replace_sym(exp::Any, a::Symbol, b::Symbol) = exp

max_stars_repo_name: MetalNinjas/julia-require

max_issues_repo_name: MetalNinjas/julia-require

max_forks_repo_name: MetalNinjas/julia-require


text:
using HigherOrderKernels
using GaussQuadrature
using Test

import HigherOrderKernels: density_kernel, density_bandwidth_constant, roughness, firstnzmoment

for s = 0:20, ν = 2:2:20
    N = s + div(ν, 2)
    x, w = legendre(N)
    @test density_kernel.(PolynomialKernel{s,ν}, x)'*w ≈ 1
end

for ν = 2:2:20
    N = div(ν, 2)
    k = x -> density_kernel(GaussianKernel{ν}, x)
    x, w = hermite(N)
    @test sum(w[i]*k(sqrt(2)*x[i])*exp(x[i]^2) for i=1:N)*sqrt(2) ≈ 1
end

# table 1
@test roughness(     UniformKernel{2}) ≈ 1/2
@test roughness(EpanechnikovKernel{2}) ≈ 3/5
@test roughness(    BiweightKernel{2}) ≈ 5/7
@test roughness(   TriweightKernel{2}) ≈ 350/429
@test roughness(    GaussianKernel{2}) ≈ 1/(2sqrt(pi))
@test firstnzmoment(     UniformKernel{2}) ≈ 1/3
@test firstnzmoment(EpanechnikovKernel{2}) ≈ 1/5
@test firstnzmoment(    BiweightKernel{2}) ≈ 1/7
@test firstnzmoment(   TriweightKernel{2}) ≈ 1/9
@test firstnzmoment(    GaussianKernel{2}) ≈ 1

# table 2
@test roughness(EpanechnikovKernel{4}) ≈ 5/4
@test roughness(    BiweightKernel{4}) ≈ 805/572
@test roughness(   TriweightKernel{4}) ≈ 3780/2431
@test roughness(    GaussianKernel{4}) ≈ 27/(32sqrt(pi))
@test firstnzmoment(EpanechnikovKernel{4}) ≈ -1/21
@test firstnzmoment(    BiweightKernel{4}) ≈ -1/33
@test firstnzmoment(   TriweightKernel{4}) ≈ -3/143
@test firstnzmoment(    GaussianKernel{4}) ≈ -3

# table 3
@test roughness(EpanechnikovKernel{6}) ≈ 1575/832
@test roughness(    BiweightKernel{6}) ≈ 29295/14144
@test roughness(   TriweightKernel{6}) ≈ 301455/134368
@test roughness(    GaussianKernel{6}) ≈ 2265/(2048sqrt(pi))
@test firstnzmoment(EpanechnikovKernel{6}) ≈ 5/429
@test firstnzmoment(    BiweightKernel{6}) ≈ 1/143
@test firstnzmoment(   TriweightKernel{6}) ≈ 1/221
@test firstnzmoment(    GaussianKernel{6}) ≈ 15

# table 4
@test round(density_bandwidth_constant(PolynomialKernel{1,2}), digits=2) == 2.34
@test round(density_bandwidth_constant(PolynomialKernel{1,4}), digits=2) == 3.03
@test round(density_bandwidth_constant(PolynomialKernel{1,6}), digits=2) == 3.53
@test round(density_bandwidth_constant(PolynomialKernel{2,2}), digits=2) == 2.78
@test round(density_bandwidth_constant(PolynomialKernel{2,4}), digits=2) == 3.39
@test round(density_bandwidth_constant(PolynomialKernel{2,6}), digits=2) == 3.84
@test round(density_bandwidth_constant(PolynomialKernel{3,2}), digits=2) == 3.15
@test round(density_bandwidth_constant(PolynomialKernel{3,4}), digits=2) == 3.72
@test round(density_bandwidth_constant(PolynomialKernel{3,6}), digits=2) == 4.13
@test round(density_bandwidth_constant(GaussianKernel{2}), digits=2) == 1.06
@test round(density_bandwidth_constant(GaussianKernel{4}), digits=2) == 1.08
@test round(density_bandwidth_constant(GaussianKernel{6}), digits=2) == 1.08