text:
"""
Bridges `CP.SortPermutation` to `CP.AllDifferent` and
`CP.ElementVariableArray`.
"""
struct SortPermutation2AllDifferentBridge{T} <: MOIBC.AbstractBridge
    con_alldiff::MOI.ConstraintIndex{MOI.VectorAffineFunction{T}, CP.AllDifferent}
    cons_value::Vector{MOI.ConstraintIndex{MOI.VectorAffineFunction{T}, CP.ElementVariableArray}}
    cons_sort::Vector{MOI.ConstraintIndex{MOI.ScalarAffineFunction{T}, MOI.GreaterThan{T}}}
end

function MOIBC.bridge_constraint(
    ::Type{SortPermutation2AllDifferentBridge{T}},
    model,
    f::MOI.VectorOfVariables,
    s::CP.SortPermutation,
) where {T}
    return MOIBC.bridge_constraint(
        SortPermutation2AllDifferentBridge{T},
        model,
        MOI.VectorAffineFunction{T}(f),
        s,
    )
end

function MOIBC.bridge_constraint(
    ::Type{SortPermutation2AllDifferentBridge{T}},
    model,
    f::MOI.VectorAffineFunction{T},
    s::CP.SortPermutation,
) where {T}
    f_scalars = MOIU.scalarize(f)
    dim = s.dimension

    sorted_array = f_scalars[1:dim]
    array = f_scalars[(dim + 1):(2 * dim)]
    indices = f_scalars[(2 * dim + 1):(3 * dim)]

    # The values must be sorted.
    # TODO: use CP.Increasing instead?
    cons_sort = MOI.ConstraintIndex{MOI.ScalarAffineFunction{T}, MOI.GreaterThan{T}}[
        MOI.add_constraint(
            model,
            sorted_array[i] - sorted_array[i + 1],
            MOI.GreaterThan(zero(T))
        )
        for i in 1:(dim - 1)
    ]

    # The indices must take different values, one per index in the array.
    con_alldiff = MOI.add_constraint(
        model,
        MOIU.vectorize(indices),
        CP.AllDifferent(dim)
    )

    # Relate the three sets of variables by indexing.
    cons_value = MOI.ConstraintIndex{MOI.VectorAffineFunction{T}, CP.ElementVariableArray}[
        MOI.add_constraint(
            model,
            MOIU.vectorize(
                [
                    sorted_array[i],
                    indices[i],
                    array...
                ]
            ),
            CP.ElementVariableArray(dim)
        )
        for i in 1:dim
    ]

    return SortPermutation2AllDifferentBridge(con_alldiff, cons_value, cons_sort)
end

function MOI.supports_constraint(
    ::Type{SortPermutation2AllDifferentBridge{T}},
    ::Union{Type{MOI.VectorOfVariables}, Type{MOI.VectorAffineFunction{T}}},
    ::Type{CP.SortPermutation},
) where {T}
    return true
end

function MOIB.added_constrained_variable_types(::Type{SortPermutation2AllDifferentBridge{T}}) where {T}
    return Tuple{Type}[]
end

function MOIB.added_constraint_types(::Type{SortPermutation2AllDifferentBridge{T}}) where {T}
    return [
        (MOI.VectorAffineFunction{T}, CP.AllDifferent),
        (MOI.ScalarAffineFunction{T}, CP.ElementVariableArray),
        (MOI.ScalarAffineFunction{T}, MOI.LessThan{T}),
    ]
end

function MOI.get(
    ::SortPermutation2AllDifferentBridge{T},
    ::MOI.NumberOfConstraints{
        MOI.VectorAffineFunction{T}, CP.AllDifferent,
    },
) where {T}
    return 1
end

function MOI.get(
    b::SortPermutation2AllDifferentBridge{T},
    ::MOI.NumberOfConstraints{
        MOI.ScalarAffineFunction{T}, CP.ElementVariableArray,
    },
) where {T}
    return length(b.cons_value)
end

function MOI.get(
    b::SortPermutation2AllDifferentBridge{T},
    ::MOI.NumberOfConstraints{
        MOI.ScalarAffineFunction{T}, MOI.LessThan{T},
    },
) where {T}
    return length(b.cons_sort)
end

function MOI.get(
    b::SortPermutation2AllDifferentBridge{T},
    ::MOI.ListOfConstraintIndices{
        MOI.VectorAffineFunction{T}, CP.AllDifferent,
    },
) where {T}
    return [b.con_alldiff]
end

function MOI.get(
    b::SortPermutation2AllDifferentBridge{T},
    ::MOI.ListOfConstraintIndices{
        MOI.ScalarAffineFunction{T}, CP.ElementVariableArray,
    },
) where {T}
    return copy(b.cons_value)
end

function MOI.get(
    b::SortPermutation2AllDifferentBridge{T},
    ::MOI.ListOfConstraintIndices{
        MOI.ScalarAffineFunction{T}, MOI.LessThan{T},
    },
) where {T}
    return copy(b.cons_sort)
end


text:
# MIT License
#
# Copyright (c) 2018 Martin Biel
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

@reexport module ProgressiveHedging

# Standard library
using LinearAlgebra
using SparseArrays
using Distributed
using Printf

# External libraries
using Parameters
using JuMP
using MathOptInterface
using StochasticPrograms
using StochasticPrograms: AcceptableTermination
using StochasticPrograms: UnspecifiedInstantiation, ScenarioDecompositionStructure, AbstractScenarioProblems, ScenarioProblems, DistributedScenarioProblems
using StochasticPrograms: AbstractExecution, ExecutionParameter, Serial, Synchronous, Asynchronous
using StochasticPrograms: AbstractStructuredOptimizer, set_master_optimizer!, set_subproblem_optimizer!
using StochasticPrograms: DecisionMap, get_decisions, all_decisions, remove_decision!, set_decision!, set_stage!, SingleDecisionSet, DecisionCoefficientChange, KnownDecision, NoSpecifiedConstraint
using StochasticPrograms: add_subscript
using StochasticPrograms: AbstractPenaltyTerm, Quadratic, InfNorm, ManhattanNorm, initialize_penaltyterm!, update_penaltyterm!, remove_penalty!
using ProgressMeter

import Base: show, put!, wait, isready, take!, fetch
import StochasticPrograms: supports_structure, num_iterations, default_structure, load_structure!, restore_structure!, optimize!, optimizer_name, master_optimizer, subproblem_optimizer, num_subproblems

const MOI = MathOptInterface
const MOIU = MOI.Utilities

export
    AbstractProgressiveHedgingAttribute,
    ProgressiveHedgingAlgorithm,
    PrimalTolerance,
    DualTolerance,
    Penalizer,
    PenalizationParameter,
    RawPenalizationParameter,
    set_penalization_attribute,
    set_penalization_attributes,
    PenaltyTerm,
    Fixed,
    Adaptive

# Include files
include("types/types.jl")
include("penalties/penalization.jl")
include("execution/execution.jl")
include("solver.jl")
include("MOI_wrapper.jl")

end # module

ext: jl


text:
using ConservationLawsParticles
using SpecialFunctions, RecursiveArrayTools, DifferentialEquations, Plots
using Random

# reference solution
boxsol(t, x; a, b) = (erf((x-a)/2sqrt(t)) - erf((x-b)/2sqrt(t))) / (2*(b-a))
refsol(t, x) = sum(boxsol(t, x; a=x0[i-1], b=x0[i]) for i in eachindex(x0)[2:end]) / (length(x0)-1)

# model
V(t, x) = 0.0 # 2 + 0.5sin(2x) + 0.3sin(2sqrt(2)*x) + 0.2cos(2sqrt(7)*x)
W(t, x) = 0.0 # x^2/2 - abs(x)
W′(t, x) = 0.0 # x - sign(x)
mob(ρ) = 0.0 # max((ρ-1)^2 * (2ρ+1), 0)
simple_model = DiffusiveSampledModel((V,), ((W′,),), (mob,), (SimpleDiffusion(1),))
mean_model = DiffusiveSampledModel((V,), ((W′,),), (mob,), (MeanDiffusion(1),))
min_model = DiffusiveSampledModel((V,), ((W′,),), (mob,), (MinDiffusion(1),))

# initial condition
Random.seed!(42)
n = 25
x0 = ArrayPartition(sort(vcat(randn(n) .- 2, .5randn(n) .+ 2)))

# time span
tspan = (0., 0.1)

# ODE system for the particles
simple_prob = ODEProblem(velocities_diff!, x0, tspan, simple_model)
mean_prob = ODEProblem(velocities_diff!, x0, tspan, mean_model)
min_prob = ODEProblem(velocities_diff!, x0, tspan, min_model)

abstol = reltol = 2e-7

@time simple_sol = solve(simple_prob, BS5(); abstol=abstol, reltol=reltol);
@time mean_sol = solve(mean_prob, BS5(); abstol=abstol, reltol=reltol);
@time min_sol = solve(min_prob, BS5(); abstol=abstol, reltol=reltol);

# plot the particle trajectories
plot(title="Trajectories", xlabel="time", ylabel="position", legend=false)
plot!(simple_sol, vars=eachindex(x0)[1:1:end], color=1)
plot!(mean_sol, vars=eachindex(x0)[1:1:end], color=2)
plot!(min_sol, vars=eachindex(x0)[1:1:end], color=3)
savefig("diffusion6.png")

# plot an animation of the density
anim = @animate for t in range(sqrt.(tspan)...; length=100).^2
    plot(title="Density", xlabel="position", ylabel="density",
        xlims=(-5,3), ylims=(0,.8), legend=:topleft)
    plot!(x -> refsol(t, x); color=:black, label="analytic")
    densityplot!(simple_sol(t); color=1, label="simple")
    densityplot!(mean_sol(t); color=2, label="mean")
    densityplot!(min_sol(t); color=3, label="min")
end
gif(anim, "diffusion6.gif")

# plot an animation of the density
let tspan = (0., .003)
anim = @animate for t in range(sqrt.(tspan)...; length=100).^2
    plot(title="Density", xlabel="position", ylabel="density",
        xlims=(-5,3), ylims=(0,.8), legend=:topleft)
    plot!(x -> refsol(t, x); color=:black, label="analytic")
    densityplot!(simple_sol(t); color=1, label="simple")
    densityplot!(mean_sol(t); color=2, label="mean")
    densityplot!(min_sol(t); color=3, label="min")
end
gif(anim, "diffusion6.1.gif")
end


text:
using StaticArrays: identity_perm
using Manifolds: decorator_transparent_dispatch
using Base: decode_overlong

include("../utils.jl")
include("group_utils.jl")

@testset "General group tests" begin
    @test length(methods(has_biinvariant_metric)) == 1
    @test length(methods(has_invariant_metric)) == 1
    @test length(methods(has_biinvariant_metric)) == 1
    @testset "Not implemented operation" begin
        G = GroupManifold(NotImplementedManifold(), NotImplementedOperation())
        @test repr(G) ==
              "GroupManifold(NotImplementedManifold(), NotImplementedOperation())"
        p = [1.0, 2.0]
        X = [2.0, 3.0]
        eg = Identity(G)
        @test repr(eg) === "Identity(NotImplementedOperation)"
        @test number_eltype(eg) == Bool
        @test is_identity(G, eg) # identity transparent
        @test_throws MethodError identity_element(G) # but for a NotImplOp there is no concrete id.
        @test isapprox(G, eg, eg)
        @test_throws MethodError is_identity(G, 1) # same rror as before i.e. dispatch isapprox works
        @test length(methods(is_group_decorator)) == 1

        @test Identity(NotImplementedOperation()) === eg
        @test Identity(NotImplementedOperation) === eg
        @test !is_point(G, Identity(AdditionOperation()))
        @test !isapprox(G, eg, Identity(AdditionOperation()))

        @test Manifolds.is_group_decorator(G)
        @test Manifolds.decorator_group_dispatch(G) === Val{true}()
        @test Manifolds.default_decorator_dispatch(G) === Val{false}()
        @test !Manifolds.is_group_decorator(NotImplementedManifold())
        @test Manifolds.decorator_group_dispatch(NotImplementedManifold()) === Val{false}()

        @test Manifolds.decorator_transparent_dispatch(compose, G, p, p, p) ===
              Val{:intransparent}()
        @test Manifolds.decorator_transparent_dispatch(compose!, G, p, p, p) ===
              Val{:intransparent}()
        @test Manifolds.decorator_transparent_dispatch(exp_lie, G, p, p) ===
              Val{:intransparent}()
        @test Manifolds.decorator_transparent_dispatch(log_lie, G, p, p) ===
              Val{:intransparent}()
        @test Manifolds.decorator_transparent_dispatch(translate_diff!, G, X, p, p, X) ===
              Val{:intransparent}()
        @test base_group(G) === G
        @test NotImplementedOperation(NotImplementedManifold()) === G
        @test (NotImplementedOperation())(NotImplementedManifold()) === G

        @test_throws ErrorException base_group(
            MetricManifold(Euclidean(3), EuclideanMetric()),
        )
        @test_throws ErrorException hat(Rotations(3), eg, [1, 2, 3])
        # If you force it, you get a not that readable MethodError
        @test_throws MethodError hat(
            GroupManifold(Rotations(3), NotImplementedOperation()),
            eg,
            [1, 2, 3],
        )
        @test_throws ErrorException vee(Rotations(3), eg, [1, 2, 3])
        @test_throws MethodError vee(
            GroupManifold(Rotations(3), NotImplementedOperation()),
            eg,
            [1, 2, 3],
        )

        @test_throws ErrorException inv!(G, p, p)
        @test_throws MethodError inv!(G, p, eg)
        @test_throws ErrorException inv(G, p)

        # no function defined to return the identity array representation
        @test_throws MethodError copyto!(G, p, eg)

        @test_throws MethodError compose(G, p, p)
        @test compose(G, p, eg) == p
        xO = deepcopy(p)
        compose!(G, p, eg, p)
        @test xO == p
        compose!(G, p, p, eg)
        @test xO == p
        @test_throws MethodError compose!(G, p, p, p)
        @test_throws MethodError compose!(G, p, eg, eg)

        @test_throws MethodError translate(G, p, p)
        @test_throws MethodError translate(G, p, p, LeftAction())
        @test_throws MethodError translate(G, p, p, RightAction())
        @test_throws MethodError translate!(G, p, p, p)
        @test_throws MethodError translate!(G, p, p, p, LeftAction())
        @test_throws MethodError translate!(G, p, p, p, RightAction())

        @test_throws ErrorException inverse_translate(G, p, p)
        @test_throws ErrorException inverse_translate(G, p, p, LeftAction())
        @test_throws ErrorException inverse_translate(G, p, p, RightAction())
        @test_throws ErrorException inverse_translate!(G, p, p, p)
        @test_throws ErrorException inverse_translate!(G, p, p, p, LeftAction())
        @test_throws ErrorException inverse_translate!(G, p, p, p, RightAction())

        @test_throws ErrorException translate_diff(G, p, p, X)
        @test_throws ErrorException translate_diff(G, p, p, X, LeftAction())
        @test_throws ErrorException translate_diff(G, p, p, X, RightAction())
        @test_throws ErrorException translate_diff!(G, X, p, p, X)
        @test_throws ErrorException translate_diff!(G, X, p, p, X, LeftAction())
        @test_throws ErrorException translate_diff!(G, X, p, p, X, RightAction())

        @test_throws ErrorException inverse_translate_diff(G, p, p, X)
        @test_throws ErrorException inverse_translate_diff(G, p, p, X, LeftAction())
        @test_throws ErrorException inverse_translate_diff(G, p, p, X, RightAction())
        @test_throws ErrorException inverse_translate_diff!(G, X, p, p, X)
        @test_throws ErrorException inverse_translate_diff!(G, X, p, p, X, LeftAction())
        @test_throws ErrorException inverse_translate_diff!(G, X, p, p, X, RightAction())

        @test_throws ErrorException exp_lie(G, X)
        @test_throws ErrorException exp_lie!(G, p, X)
        # no transparency error, but _log_lie missing
        @test_throws MethodError log_lie(G, p)
        @test_throws MethodError log_lie!(G, X, p)

        for f in [translate, translate!]
            @test Manifolds.decorator_transparent_dispatch(f, G) === Val{:intransparent}()
        end
        for f in
            [get_vector, get_coordinates, inverse_translate_diff!, inverse_translate_diff]
            @test Manifolds.decorator_transparent_dispatch(f, G) === Val{:transparent}()
        end
        for f in [exp_lie!, exp_lie, log_lie, log_lie!]
            @test Manifolds.decorator_transparent_dispatch(f, G, p, p) ===
                  Val{:intransparent}()
        end
        @test Manifolds.decorator_transparent_dispatch(isapprox, G, eg, p) ===
              Val{:transparent}()
        @test Manifolds.decorator_transparent_dispatch(isapprox, G, p, eg) ===
              Val{:transparent}()
        @test Manifolds.decorator_transparent_dispatch(isapprox, G, eg, eg) ===
              Val{:transparent}()
    end

    @testset "Action direction" begin
        @test switch_direction(LeftAction()) == RightAction()
        @test switch_direction(RightAction()) == LeftAction()

        @test Manifolds._action_order(1, 2, LeftAction()) === (1, 2)
        @test Manifolds._action_order(1, 2, RightAction()) === (2, 1)
    end

    @testset "Addition operation" begin
        G = GroupManifold(NotImplementedManifold(), Manifolds.AdditionOperation())
        test_group(
            G,
            [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]],
            [],
            [[1.0, 2.0]];
            test_exp_lie_log=false, # there is no identity element so log/exp on Lie do not work
            test_one_arg_identity_element=false,
        )

        p = [1.0, 2.0]
        X = [3.0, 4.0]
        ge = Identity(G)
        @test number_eltype(ge) == Bool
        y = allocate(p)
        copyto!(G, y, ge)
        @test y ≈ zero(p)
        @test ge - p == -p
        @test p - ge === p
        @test ge - ge === ge
        @test ge + p ≈ p
        @test p + ge ≈ p
        @test ge + ge === ge
        @test -(ge) === ge
        @test +(ge) === ge
        @test ge * 1 === ge
        @test 1 * ge === ge
        @test ge * ge === ge
        @test inv(G, p) ≈ -p
        @test inv(G, ge) === ge
        @test compose(G, p, p) ≈ p + p
        @test compose(G, p, ge) ≈ p
        @test compose(G, ge, p) ≈ p
        @test compose(G, ge, ge) == ge
        compose!(G, y, p, p)
        @test y ≈ p + p
        compose!(G, y, p, ge)
        @test y ≈ p
        compose!(G, y, ge, p)
        @test y ≈ p
        @test exp_lie(G, X) === X
        @test log_lie(G, p) === p
    end

    @testset "Multiplication operation" begin
        G = GroupManifold(NotImplementedManifold(), Manifolds.MultiplicationOperation())
        test_group(
            G,
            [[2.0 1.0; 3.0 4.0], [3.0 2.0; 4.0 5.0], [4.0 3.0; 5.0 6.0]],
            [],
            [[1.0 2.0; 3.0 4.0]];
            test_exp_lie_log=false, # no identity available as array
            test_one_arg_identity_element=false,
        )

        p = [2.0 1.0; 2.0 3.0]
        ge = Identity(G)
        @test number_eltype(ge) == Bool
        @test copyto!(G, ge, ge) === ge
        y = allocate(p)
        identity_element!(G, y)
        @test_throws DimensionMismatch identity_element!(G, [1, 2, 3])
        @test y ≈ one(p)
        @test one(ge) === ge
        @test transpose(ge) === ge
        @test det(ge) == 1
        @test ge * p ≈ p
        @test p * ge ≈ p
        @test ge * ge === ge
        @test inv(G, ge) === ge
        @test *(ge) === ge

        @test p / ge ≈ p
        @test ge \ p ≈ p
        @test ge / ge === ge
        @test ge \ ge === ge
        @test ge / p ≈ inv(G, p)
        @test p \ ge ≈ inv(G, p)
        y = allocate(p)
        @test LinearAlgebra.mul!(y, p, ge) === y
        @test y ≈ p
        y = allocate(p)
        @test LinearAlgebra.mul!(y, ge, p) === y
        @test y ≈ p
        y = allocate(p)
        @test LinearAlgebra.mul!(y, ge, ge) === y
        @test y ≈ one(y)

        @test inv(G, p) ≈ inv(p)
        @test inv(G, ge) === ge
        z = allocate(p)
        copyto!(G, z, p)
        z2 = allocate(p)
        copyto!(G.manifold, z2, p)
        @test z == z2
        X = zeros(2, 2)
        Y = allocate(X)
        copyto!(G, Y, p, X)
        Y2 = allocate(X)
        copyto!(G.manifold, Y2, p, X)
        @test Y == Y2

        @test compose(G, p, p) ≈ p * p
        @test compose(G, p, ge) ≈ p
        @test compose(G, ge, p) ≈ p
        @test compose(G, ge, ge) == ge
        compose!(G, y, p, p)
        @test y ≈ p * p
        compose!(G, y, p, ge)
        @test y ≈ p
        compose!(G, y, ge, p)
        @test y ≈ p
        X = [1.0 2.0; 3.0 4.0]
        @test exp_lie!(G, y, X) === y
        @test_throws ErrorException exp_lie!(G, y, :a)
        @test y ≈ exp(X)
        Y = allocate(X)
        @test log_lie!(G, Y, y) === Y
        @test Y ≈ log(y)

        q2 = SVDMPoint(2 * Matrix{Float64}(I, 3, 3))
        mul!(q2, ge, ge)
        qT = SVDMPoint(Matrix{Float64}(I, 3, 3))
        @test isapprox(FixedRankMatrices(3, 3, 3), q2, qT)
    end

    @testset "Identity on Group Manifolds" begin
        G = TranslationGroup(3)
        e = Identity(G)
        @test get_vector_lie(G, ones(3), DefaultOrthogonalBasis()) == ones(3)
        @test e - e == e
        @test ones(3) + e == ones(3)
        e_add = Identity(AdditionOperation)
        e_mul = Identity(MultiplicationOperation)
        @test e_add * e_mul === e_add
        @test e_mul * e_add === e_add
        @test mul!(e_mul, e_mul, e_mul) === e_mul
    end

    @testset "Transparency tests" begin
        G = DefaultTransparencyGroup(Euclidean(3), AdditionOperation())
        p = ones(3)
        q = 2 * p
        X = zeros(3)
        Y = similar(X)
        for f in
            [vector_transport_along!, vector_transport_direction!, vector_transport_to!]
            @test ManifoldsBase.decorator_transparent_dispatch(
                f,
                G,
                Y,
                p,
                X,
                q,
                ParallelTransport(),
            ) == Val(:intransparent)
        end
    end
end

struct NotImplementedAction <: AbstractGroupAction{LeftAction} end

@testset "General group action tests" begin
    @testset "Not implemented operations" begin
        A = NotImplementedAction()
        p = [1.0, 2.0]
        a = [1.0, 2.0]
        X = [1.0, 2.0]

        @test_throws ErrorException base_group(A)
        @test_throws ErrorException g_manifold(A)
        @test_throws ErrorException apply(A, a, p)
        @test_throws ErrorException apply!(A, p, a, p)
        @test_throws ErrorException inverse_apply(A, a, p)
        @test_throws ErrorException inverse_apply!(A, p, a, p)
        @test_throws ErrorException apply_diff(A, a, p, X)
        @test_throws ErrorException apply_diff!(A, X, p, a, X)
        @test_throws ErrorException inverse_apply_diff(A, a, p, X)
        @test_throws ErrorException inverse_apply_diff!(A, X, p, a, X)
        @test_throws ErrorException compose(A, a, a)
        @test_throws ErrorException compose!(A, a, a, a)
        @test_throws ErrorException optimal_alignment(A, p, p)
        @test_throws ErrorException optimal_alignment!(A, a, p, p)
    end
end


text:
get_inference_cache(interp::CustomInterpreter) = CustomLocalCache(interp, interp.native.cache)

struct CustomLocalCache
    interp::CustomInterpreter
    native::Vector{InferenceResult}
end

# here we can work on local cache retrieval
function CC.cache_lookup(linfo::MethodInstance, given_argtypes::Vector{Any}, inf_cache::CustomLocalCache)
    ret = cache_lookup(linfo, given_argtypes, inf_cache.native)

    # return nothing # to invalidate local cache (for constant analysis)

    return ret
end

function CC.push!(inf_cache::CustomLocalCache, inf_result::InferenceResult)
    return CC.push!(inf_cache.native, inf_result)
end

max_stars_repo_name: aviatesk/AbstractInterpreterPlayground

max_issues_repo_name: aviatesk/AbstractInterpreterPlayground

max_forks_repo_name: aviatesk/AbstractInterpreterPlayground


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

using Markdown
using InteractiveUtils

# ╔═╡ 958d41ca-1b5e-405b-8767-d4bebb3aac66
begin
	import Pkg
	Pkg.activate(mktempdir())
	Pkg.add(["MLDatasets", "Images", "Flux", "ImageIO"])

	using MLDatasets
	using Images
	using Flux
	using Flux: onehotbatch, onecold, unsqueeze, Data.DataLoader
	using Statistics
end

# ╔═╡ 2b038257-a1a4-40d3-bbba-6dc0ff1e2474
using Serialization

# ╔═╡ b3b34e7a-3831-4e70-a4e2-8499108c3d60
md"## Training notebook for \"PlutoCon 2021 WYSIWYR Demo (MNIST)\"
Once again I shoud stress that the focus of this talk is *not* on this model, but rather on \"building\" an API around it with [upcoming Pluto features](https://github.com/fonsp/Pluto.jl/pull/1052)!"

# ╔═╡ ac3dfbe8-5298-43f5-b639-6f4599cf6ced
ENV["DATADEPS_ALWAYS_ACCEPT"] = "true";

# ╔═╡ aeccd705-966f-44da-888b-dd025ef82185
MNIST.download(; i_accept_the_terms_of_use=true)

# ╔═╡ eb78c825-da2b-4b90-bf3e-967191b23aca
md"Loads the MNIST dataset from downloaded files"

# ╔═╡ 4f336d93-5dd8-4412-af6f-aa1749fb5d61
train_raw_x, train_cold_y = MNIST.traindata();

# ╔═╡ 5cf9e100-4112-48b5-8235-e6bacc44f102
test_raw_x,  test_cold_y  = MNIST.testdata();

# ╔═╡ a0230805-9fc9-4a88-884d-ed6d4aae5129
md"Reshapes the data to work with `Flux.jl` model"

# ╔═╡ da7feb20-812b-47e1-88a4-430d9f87630d
train_x, train_y = unsqueeze(train_raw_x, 3), onehotbatch(train_cold_y, 0:9);

# ╔═╡ b637e559-88c7-472f-9985-39a1d0541dd4
test_x, test_y = unsqueeze(test_raw_x, 3), onehotbatch(test_cold_y, 0:9);

# ╔═╡ 92dde47d-53d1-4f88-9616-67c1e07f22c7
train_data = DataLoader(train_x, train_y; batchsize=128);

# ╔═╡ de8da9ba-3604-4616-ad02-fa7a3f0ff5f3
size(train_x)

# ╔═╡ fd5f98ca-e8f1-4ded-a5e8-40930aa06163
md"The first image in the test set is shown below"

# ╔═╡ ceb5c86a-6c3e-4d6e-bcff-26c5216a9731
Gray.(permutedims(train_x[:, :, 1, 1], (2, 1)))

# ╔═╡ 12ed781c-ceb5-4064-ac95-2e497cbf6082
md"Now we define a simple model involving several convolutional layers, max pooling layers, and a dense layer"

# ╔═╡ f260f73e-9504-410b-afea-4160351e04c3
model = Chain(
	Conv((3, 3), 1=>8, relu),
	MaxPool((2, 2)),
	Conv((3, 3), 8=>16, relu),
	MaxPool((2, 2)),
	Conv((3, 3), 16=>32, relu),
	MaxPool((2, 2)),
	flatten,

	Dense(32, 10),
	softmax
)

# ╔═╡ 8726661b-9321-4daa-85e8-ce208a0bbf2d
size(model(train_x[:, :, :, 1:2]))

# ╔═╡ ad95785a-1aa1-4eab-9acb-f46757fc69b8
md"Functions for calculating our model's loss and accuracy"

# ╔═╡ 6fcf9495-bad3-4e94-8674-526266c8b645
accuracy(ŷ, y) = mean(onecold(ŷ) .== onecold(y))

# ╔═╡ e34d2bc6-c4c1-40d3-b3f6-356cfecac442
loss(x, y) = Flux.crossentropy(model(x), y)

# ╔═╡ 674c2b37-e4c0-4271-8b47-147ce1b777d0
loss(train_x, train_y)

# ╔═╡ 8bb2e369-5019-409d-a3fc-93d74b32e9f0
md"Now we define some basic hyperparameters of our model"

# ╔═╡ 5ddd3c96-37fc-4eff-be70-f48200f5db6b
α = 0.1

# ╔═╡ e9367fdd-a77c-43dd-b7a5-ffacfc940fff
opt = Descent(α)

# ╔═╡ 292d2dea-8d9e-40d1-b7ba-9893cecdd9f9
epochs = 10

# ╔═╡ 5b44fe18-7b33-4e26-9ae7-3b9c83aa422f
params = Flux.params(model)

# ╔═╡ 1ae3ed92-fe72-408e-96e4-ef0f4b7c496d
md"We are ready to train our model now. Training this model takes about 10 minutes"

# ╔═╡ 4a355a94-0f90-4b89-a35c-a325b0249886
for epoch ∈ 1:epochs
	@info epoch accuracy(model(train_x), train_y) accuracy(model(test_x), test_y)

	for batch ∈ train_data
		∇J = Flux.gradient(params) do
			loss(batch...)
		end

		Flux.update!(opt, params, ∇J)
	end
end

# ╔═╡ 7cf65377-c66e-44ec-bba0-4ae46fbc2d0d
md"And now our model should have around a 98% accuracy"

# ╔═╡ ae4f8ebf-e844-4e0a-a6db-8f8d8dc61df4
accuracy(model(train_x), train_y), accuracy(model(test_x), test_y)

# ╔═╡ 4fbad422-a37c-4588-a864-f591df732775
md"Now we save our model to a `jls` file (stands for julia serialization) which will allow us to load it in other notebooks later."

# ╔═╡ 9505711a-f20c-43f0-87c1-4532007bb0af
open(io -> serialize(io, model), "mnist_conv.jls", "w")

# ╔═╡ 0394483b-d85e-496f-b439-ff9c3aa506aa
md"And now that the model is trained we can hop back on over to the test notebook!"

# ╔═╡ Cell order:
# ╟─b3b34e7a-3831-4e70-a4e2-8499108c3d60
# ╟─958d41ca-1b5e-405b-8767-d4bebb3aac66
# ╟─ac3dfbe8-5298-43f5-b639-6f4599cf6ced
# ╠═aeccd705-966f-44da-888b-dd025ef82185
# ╟─eb78c825-da2b-4b90-bf3e-967191b23aca
# ╠═4f336d93-5dd8-4412-af6f-aa1749fb5d61
# ╠═5cf9e100-4112-48b5-8235-e6bacc44f102
# ╟─a0230805-9fc9-4a88-884d-ed6d4aae5129
# ╠═da7feb20-812b-47e1-88a4-430d9f87630d
# ╠═b637e559-88c7-472f-9985-39a1d0541dd4
# ╠═92dde47d-53d1-4f88-9616-67c1e07f22c7
# ╠═de8da9ba-3604-4616-ad02-fa7a3f0ff5f3
# ╟─fd5f98ca-e8f1-4ded-a5e8-40930aa06163
# ╠═ceb5c86a-6c3e-4d6e-bcff-26c5216a9731
# ╟─12ed781c-ceb5-4064-ac95-2e497cbf6082
# ╠═f260f73e-9504-410b-afea-4160351e04c3
# ╠═8726661b-9321-4daa-85e8-ce208a0bbf2d
# ╟─ad95785a-1aa1-4eab-9acb-f46757fc69b8
# ╠═6fcf9495-bad3-4e94-8674-526266c8b645
# ╠═e34d2bc6-c4c1-40d3-b3f6-356cfecac442
# ╠═674c2b37-e4c0-4271-8b47-147ce1b777d0
# ╟─8bb2e369-5019-409d-a3fc-93d74b32e9f0
# ╠═5ddd3c96-37fc-4eff-be70-f48200f5db6b
# ╠═e9367fdd-a77c-43dd-b7a5-ffacfc940fff
# ╠═292d2dea-8d9e-40d1-b7ba-9893cecdd9f9
# ╠═5b44fe18-7b33-4e26-9ae7-3b9c83aa422f
# ╟─1ae3ed92-fe72-408e-96e4-ef0f4b7c496d
# ╠═4a355a94-0f90-4b89-a35c-a325b0249886
# ╟─7cf65377-c66e-44ec-bba0-4ae46fbc2d0d
# ╠═ae4f8ebf-e844-4e0a-a6db-8f8d8dc61df4
# ╟─4fbad422-a37c-4588-a864-f591df732775
# ╠═2b038257-a1a4-40d3-bbba-6dc0ff1e2474
# ╠═9505711a-f20c-43f0-87c1-4532007bb0af
# ╟─0394483b-d85e-496f-b439-ff9c3aa506aa

max_stars_repo_path: MNIST Training.jl

max_stars_repo_name: ctrekker/pluto-static-test

max_issues_repo_path: MNIST Training.jl

max_issues_repo_name: ctrekker/pluto-static-test

max_forks_repo_path: MNIST Training.jl

max_forks_repo_name: ctrekker/pluto-static-test


text:
function sum0(a)
    # create variable to store ouput
    out = 0.0

    # loop
    for i in a
        out += i
    end

    # return
    return out
end


text:
using GeoData, Test, Dates
using GeoData: formatdims, dims, name

data1 = cumsum(cumsum(ones(10, 11); dims=1); dims=2)
data2 = 2cumsum(cumsum(ones(10, 11, 1); dims=1); dims=2)
dims1 = Lon<|(10, 100), Lat<|(-50, 50)
dims2 = (dims1..., Ti([DateTime(2019)]))
refdimz = ()
mval = -9999.0
meta = NoMetadata()
nme = :test

# Formatting only occurs in shorthand constructors
ga2 = GeoArray(data2, dims2)
ga1 = GeoArray(data1, formatdims(data1, dims1), refdimz, nme, meta, mval)

@test ga1 == data1
@test ga2 == data2

@testset "arary dims have been formatted" begin
    @test val.(dims(ga2)) == val.((Lon<|LinRange(10.0, 100.0, 10),
                                   Lat<|LinRange(-50.0, 50.0, 11),
                                   Ti<|[DateTime(2019)]))
    @test dims(ga1)[1:2] == dims(ga2)[1:2]
    @test name(ga1) == :test
    @test missingval(ga1) == -9999.0
end

@testset "show" begin
    sh = sprint(show, ga1)
    # Test but don't lock this down too much
    @test occursin("GeoArray", sh)
    @test occursin("Latitude", sh)
    @test occursin("Longitude", sh)
end


text:
import NNlib: conv_direct, conv_im2col, channels_in, channels_out

@testset "Conv Inference" begin
    for T in (Float32, Float64)
        impl = [conv, conv_direct, conv_im2col]
        if NNlib.is_nnpack_available() && T == Float32
            push!(impl, NNlib.conv_nnpack)
        end

        x = rand(T, 10, 10, 3, 2)
        w = rand(T, 3, 3, 3, 1)

        for f in impl
            @test @inferred(f(x, w, DenseConvDims(x, w))) isa Array{T,4}
        end
    end
end

@testset "DenseConvDims Inference" begin
    # this needs to be in a function to trigger inference problems
    function channels_in_test(w::AbstractArray)
        cdims = DenseConvDims((1,1,1,1), size(w))
        channels_in(cdims)
    end

    # this needs to be in a function to trigger inference problems
    function channels_out_test(w::AbstractArray)
        cdims = DenseConvDims((1,1,1,1), size(w))
        channels_out(cdims)
    end

    w = rand(Float32, 1, 1, 1, 1)

    @test @inferred(channels_in_test(w)) isa Int
    @test @inferred(channels_out_test(w)) isa Int
end


text:
using DiffEqSensitivity, OrdinaryDiffEq, Flux, DiffEqFlux, CUDA, Zygote
CUDA.allowscalar(false) # Makes sure no slow operations are occuring

# Generate Data
u0 = Float32[2.0; 0.0]
datasize = 30
tspan = (0.0f0, 1.5f0)
tsteps = range(tspan[1], tspan[2], length = datasize)
function trueODEfunc(du, u, p, t)
    true_A = [-0.1 2.0; -2.0 -0.1]
    du .= ((u.^3)'true_A)'
end
prob_trueode = ODEProblem(trueODEfunc, u0, tspan)
# Make the data into a GPU-based array if the user has a GPU
ode_data = gpu(solve(prob_trueode, Tsit5(), saveat = tsteps))

dudt2 = Chain(x -> x.^3,
              Dense(2, 50, tanh),
              Dense(50, 2)) |> gpu
u0 = Float32[2.0; 0.0] |> gpu

_p,re = Flux.destructure(dudt2)
p = gpu(_p)

prob_neuralode = NeuralODE(dudt2, tspan, Tsit5(), saveat = tsteps)

function predict_neuralode(p)
  gpu(prob_neuralode(u0,p))
end
function loss_neuralode(p)
    pred = predict_neuralode(p)
    loss = sum(abs2, ode_data .- pred)
    return loss
end
# Callback function to observe training
list_plots = []
iter = 0

Zygote.gradient(loss_neuralode, p)


text:
abstract type AbstractWasmExport end

mutable struct WasmExports{I,E<:AbstractWasmExport}
    wasm_instance::I # I may either be a WamsInstance or a WasmtimeModule
    wasm_exports::Vector{E}
end

function Base.getproperty(wasm_exports::WasmExports, f::Symbol)
    if f ∈ fieldnames(WasmExports)
        return getfield(wasm_exports, f)
    end

    lookup_name = string(f)
    export_index =
        findfirst(wasm_export -> wasm_export.name == lookup_name, wasm_exports.wasm_exports)
    @assert export_index !== nothing "Export $f not found"

    wasm_exports.wasm_exports[export_index]
end


text:
# Let's keep C function calls until Julia function has been tested functional.
#=//===--------------------------------------------------------------------===//
// Open/Connect
//===--------------------------------------------------------------------===//
=#
"""
	duckdb_open(path, out_database)

Creates a new database or opens an existing database file stored at the the given path.
If no path is given a new in-memory database is created instead.

* `path`: Path to the database file on disk, or `nullptr` or `:memory:` to open an in-memory database.
* `out_database`: The result database object.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

"""
function duckdb_open(path, out_database)
    return ccall(
        (:duckdb_open, libduckdb),
        Int32,
        (Ptr{UInt8}, Ptr{Cvoid}),
        path,
        out_database,
    )
end
"""
	duckdb_close(database)

Closes the specified database and de-allocates all memory allocated for that database.
This should be called after you are done with any database allocated through `duckdb_open`.
Note that failing to call `duckdb_close` (in case of e.g. a program crash) will not cause data corruption.
Still it is recommended to always correctly close a database object after you are done with it.

* `database`: The database object to shut down.

"""
function duckdb_close(database)
    return ccall((:duckdb_close, libduckdb), Cvoid, (Ptr{Cvoid},), database)
end
"""
	duckdb_connect(database, out_connection)

Opens a connection to a database. Connections are required to query the database, and store transactional state
associated with the connection.

* `database`: The database file to connect to.
* `out_connection`: The result connection object.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

"""
function duckdb_connect(database, out_connection)
    return ccall(
        (:duckdb_connect, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{Cvoid}),
        database[],
        out_connection,
    )
end

"""
	duckdb_disconnect(connection)

Closes the specified connection and de-allocates all memory allocated for that connection.
* `connection`: The connection to close.

"""
function duckdb_disconnect(connection)
    return ccall((:duckdb_disconnect, libduckdb), Cvoid, (Ptr{Cvoid},), connection)
end

#=
//===--------------------------------------------------------------------===//
// Configuration
//===--------------------------------------------------------------------===//
=#

"""
	duckdb_create_config(config)

Initializes an empty configuration object that can be used to provide start-up options for the DuckDB instance
through `duckdb_open_ext`.

This will always succeed unless there is a malloc failure.

* `out_config`: The result configuration object.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

"""
function duckdb_create_config(config)
    return ccall((:duckdb_create_config, libduckdb), Int32, (Ptr{Cvoid},), config)
end

"""
	duckdb_config_count()

This returns the total amount of configuration options available for usage with `duckdb_get_config_flag`.

This should not be called in a loop as it internally loops over all the options.

* returns: The amount of config options available.

"""
function duckdb_config_count()
    return ccall((:duckdb_config_count, libduckdb), Int32, ())
end

"""
	duckdb_get_config_flag(index,out_name,out_description)

Obtains a human-readable name and description of a specific configuration option. This can be used to e.g.
display configuration options. This will succeed unless `index` is out of range (i.e. `>= duckdb_config_count`).

The result name or description MUST NOT be freed.

* `index`: The index of the configuration option (between 0 and `duckdb_config_count`)
* `out_name`: A name of the configuration flag.
* `out_description`: A description of the configuration flag.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

"""
function duckdb_get_config_flag(index, out_name, out_description)
    return ccall(
        (:duckdb_get_config_flag, libduckdb),
        Int32,
        (Int32, Ptr{Ptr{UInt8}}, Ptr{Ptr{UInt8}}),
        index,
        out_name,
        out_description,
    )
end

"""
	duckdb_set_config(config,name,option)

Sets the specified option for the specified configuration. The configuration option is indicated by name.
To obtain a list of config options, see `duckdb_get_config_flag`.

In the source code, configuration options are defined in `config.cpp`.

This can fail if either the name is invalid, or if the value provided for the option is invalid.

* `duckdb_config`: The configuration object to set the option on.
* `name`: The name of the configuration flag to set.
* `option`: The value to set the configuration flag to.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

"""
function duckdb_set_config(duckdb_config, name, option)
    return ccall(
        (:duckdb_set_config, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}, Ptr{UInt8}),
        duckdb_config,
        name,
        option,
    )
end

"""
	duckdb_destroy_config(config)

Destroys the specified configuration option and de-allocates all memory allocated for the object.

* `config`: The configuration object to destroy.

"""
function duckdb_destroy_config(config)
    return ccall((:duckdb_destroy_config, libduckdb), Cvoid, (Ptr{Cvoid},), config)
end

#=
//===--------------------------------------------------------------------===//
// Query Execution
//===--------------------------------------------------------------------===//
=#

"""
	duckdb_query(connection,query,out_result)

Executes a SQL query within a connection and stores the full (materialized) result in the out_result pointer.
If the query fails to execute, DuckDBError is returned and the error message can be retrieved by calling
`duckdb_result_error`.

Note that after running `duckdb_query`, `duckdb_destroy_result` must be called on the result object even if the
query fails, otherwise the error stored within the result will not be freed correctly.

* `connection`: The connection to perform the query in.
* `query`: The SQL query to run.
* `out_result`: The query result.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

"""
function duckdb_query(connection, query, out_result)
    return ccall(
        (:duckdb_query, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}, Ptr{Cvoid}),
        connection[],
        query,
        out_result,
    )
end

"""
	duckdb_destroy_result(result)
Closes the result and de-allocates all memory allocated for that connection.

* `result`: The result to destroy.

"""
function duckdb_destroy_result(result)
    return ccall((:duckdb_destroy_result, libduckdb), Cvoid, (Ptr{Cvoid},), result)
end

"""
	duckdb_column_name(result,col)

Returns the column name of the specified column. The result should not need be freed; the column names will
automatically be destroyed when the result is destroyed.

Returns `NULL` if the column is out of range.

* `result`: The result object to fetch the column name from.
* `col`: The column index.
* returns: The column name of the specified column.

"""
function duckdb_column_name(result, col)
    return ccall(
        (:duckdb_column_name, libduckdb),
        Ptr{UInt8},
        (Ptr{Cvoid}, Int32),
        result,
        col - 1,
    )
end

"""
	duckdb_column_type(result,col)

Returns the column type of the specified column.

Returns `DUCKDB_TYPE_INVALID` if the column is out of range.

* `result`: The result object to fetch the column type from.
* `col`: The column index.
* returns: The column type of the specified column.

"""
function duckdb_column_type(result, col)
    return ccall(
        (:duckdb_column_type, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        result,
        col - 1,
    )
end

"""
	duckdb_column_count(result)

Returns the number of columns present in a the result object.

* `result`: The result object.
* returns: The number of columns present in the result object.

"""
function duckdb_column_count(result)
    return ccall((:duckdb_column_count, libduckdb), Int32, (Ptr{Cvoid},), result)
end

"""
	duckdb_row_count(result)

Returns the number of rows present in a the result object.

* `result`: The result object.
* returns: The number of rows present in the result object.

"""
function duckdb_row_count(result)
    return ccall((:duckdb_row_count, libduckdb), Int64, (Ptr{Cvoid},), result)
end

"""
	duckdb_rows_changed(result)

Returns the number of rows changed by the query stored in the result. This is relevant only for INSERT/UPDATE/DELETE
queries. For other queries the rows_changed will be 0.

* `result`: The result object.
* returns: The number of rows changed.

"""
function duckdb_rows_changed(result)
    return ccall((:duckdb_rows_changed, libduckdb), Int64, (Ptr{Cvoid},), result)
end

"""
	duckdb_column_data(result,col)

Returns the data of a specific column of a result in columnar format. This is the fastest way of accessing data in a
query result, as no conversion or type checking must be performed (outside of the original switch). If performance
is a concern, it is recommended to use this API over the `duckdb_value` functions.

The function returns a dense array which contains the result data. The exact type stored in the array depends on the
corresponding duckdb_type (as provided by `duckdb_column_type`). For the exact type by which the data should be
accessed, see the comments in [the types section](types) or the `DUCKDB_TYPE` enum.

For example, for a column of type `DUCKDB_TYPE_INTEGER`, rows can be accessed in the following manner:
```c
int32_t *data = (int32_t *) duckdb_column_data(&result, 0);
printf("Data for row %d: %d\\n", row, data[row]);
```

* `result`: The result object to fetch the column data from.
* `col`: The column index.
* returns: The column data of the specified column.

"""
function duckdb_column_data(result, col)
    return ccall(
        (:duckdb_column_data, libduckdb),
        Ptr{Cvoid},
        (Ptr{Cvoid}, Int32),
        result,
        col - 1,
    )
end

"""
	duckdb_nullmask_data(result,col)

Returns the nullmask of a specific column of a result in columnar format. The nullmask indicates for every row
whether or not the corresponding row is `NULL`. If a row is `NULL`, the values present in the array provided
by `duckdb_column_data` are undefined.

```c
int32_t *data = (int32_t *) duckdb_column_data(&result, 0);
bool *nullmask = duckdb_nullmask_data(&result, 0);
if (nullmask[row]) {
    printf("Data for row %d: NULL\n", row);
} else {
    printf("Data for row %d: %d\n", row, data[row]);
}
```

* `result`: The result object to fetch the nullmask from.
* `col`: The column index.
* returns: The nullmask of the specified column.

"""
function duckdb_nullmask_data(result, col)
    return ccall(
        (:duckdb_nullmask_data, libduckdb),
        Ptr{Int32},
        (Ptr{Cvoid}, Int32),
        result,
        col - 1,
    )
end

"""
	duckdb_result_error(result)

Returns the error message contained within the result. The error is only set if `duckdb_query` returns `DuckDBError`.

The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_result` is called.

* `result`: The result object to fetch the nullmask from.
* returns: The error of the result.

"""
function duckdb_result_error(result)
    return ccall((:duckdb_result_error, libduckdb), Ptr{UInt8}, (Ptr{Cvoid},), result)
end

#=
//===--------------------------------------------------------------------===//
// Result Functions
//===--------------------------------------------------------------------===//

// Safe fetch functions
// These functions will perform conversions if necessary.
// On failure (e.g. if conversion cannot be performed or if the value is NULL) a default value is returned.
// Note that these functions are slow since they perform bounds checking and conversion
// For fast access of values prefer using duckdb_column_data and duckdb_nullmask_data
=#

"""
	duckdb_value_boolean(result,col,row)

* returns: The boolean value at the specified location, or false if the value cannot be converted.

"""
function duckdb_value_boolean(result, col, row)
    return ccall(
        (:duckdb_value_boolean, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_int8(result,col,row)

* returns: The int8_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_int8(result, col, row)
    return ccall(
        (:duckdb_value_int8, libduckdb),
        Int8,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_int16(result,col,row)

 * returns: The int16_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_int16(result, col, row)
    return ccall(
        (:duckdb_value_int16, libduckdb),
        Int16,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_int32(result,col,row)

 * returns: The int32_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_int32(result, col, row)
    return ccall(
        (:duckdb_value_int32, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_int64(result,col,row)

 * returns: The int64_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_int64(result, col, row)
    return ccall(
        (:duckdb_value_int64, libduckdb),
        Int64,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_hugeint(result,col,row)

 * returns: The duckdb_hugeint value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_hugeint(result, col, row)
    return ccall(
        (:duckdb_value_hugeint, libduckdb),
        Int64,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_uint8(result,col,row)

 * returns: The uint8_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_uint8(result, col, row)
    return ccall(
        (:duckdb_value_uint8, libduckdb),
        UInt8,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_uint16(result,col,row)

 * returns: The uint16_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_uint16(result, col, row)
    return ccall(
        (:duckdb_value_uint16, libduckdb),
        UInt16,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_uint32(result,col,row)

 * returns: The uint32_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_uint32(result, col, row)
    return ccall(
        (:duckdb_value_uint32, libduckdb),
        UInt32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_uint64(result,col,row)

* returns: The uint64_t value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_uint64(result, col, row)
    return ccall(
        (:duckdb_value_uint64, libduckdb),
        UInt64,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_float(result,col,row)

 * returns: The float value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_float(result, col, row)
    return ccall(
        (:duckdb_value_float, libduckdb),
        Float32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
	duckdb_value_double(result,col,row)

 * returns: The double value at the specified location, or 0 if the value cannot be converted.

"""
function duckdb_value_double(result, col, row)
    return ccall(
        (:duckdb_value_double, libduckdb),
        Float64,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_date(result,col,row)

 * returns: The duckdb_date value at the specified location, or 0 if the value cannot be converted.

DUCKDB_API duckdb_date duckdb_value_date(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_date(result, col, row)
    return ccall(
        (:duckdb_value_date, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_time(result,col,row)

 * returns: The duckdb_time value at the specified location, or 0 if the value cannot be converted.

DUCKDB_API duckdb_time duckdb_value_time(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_time(result, col, row)
    return ccall(
        (:duckdb_value_time, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_timestamp(result,col,row)

 * returns: The duckdb_timestamp value at the specified location, or 0 if the value cannot be converted.

DUCKDB_API duckdb_timestamp duckdb_value_timestamp(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_timestamp(result, col, row)
    return ccall(
        (:duckdb_value_timestamp, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_interval(result,col,row)

 * returns: The duckdb_interval value at the specified location, or 0 if the value cannot be converted.

DUCKDB_API duckdb_interval duckdb_value_interval(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_interval(result, col, row)
    return ccall(
        (:duckdb_value_interval, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_varchar(result,col,row)

* returns: The char* value at the specified location, or nullptr if the value cannot be converted.
The result must be freed with `duckdb_free`.

DUCKDB_API char *duckdb_value_varchar(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_varchar(result, col, row)
    return ccall(
        (:duckdb_value_varchar, libduckdb),
        Ptr{UInt8},
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_varchar_internal(result,col,row)

* returns: The char* value at the specified location. ONLY works on VARCHAR columns and does not auto-cast.
If the column is NOT a VARCHAR column this function will return NULL.

The result must NOT be freed.

DUCKDB_API char *duckdb_value_varchar_internal(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_varchar_internal(result, col, row)
    return ccall(
        (:duckdb_value_varchar_internal, libduckdb),
        Ptr{UInt8},
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_blob(result,col,row)

* returns: The duckdb_blob value at the specified location. Returns a blob with blob.data set to nullptr if the
value cannot be converted. The resulting "blob.data" must be freed with `duckdb_free.`

DUCKDB_API duckdb_blob duckdb_value_blob(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_blob(result, col, row)
    return ccall(
        (:duckdb_value_blob, libduckdb),
        Ptr{Cvoid},
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

"""
duckdb_value_is_null(result,col,row)

 * returns: Returns true if the value at the specified index is NULL, and false otherwise.

DUCKDB_API bool duckdb_value_is_null(duckdb_result *result, idx_t col, idx_t row);
"""
function duckdb_value_is_null(result, col, row)
    return ccall(
        (:duckdb_value_is_null, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        result,
        col - 1,
        row - 1,
    )
end

#=
//===--------------------------------------------------------------------===//
// Helpers
//===--------------------------------------------------------------------===//
=#

"""
duckdb_malloc(size)

Allocate `size` bytes of memory using the duckdb internal malloc function. Any memory allocated in this manner
should be freed using `duckdb_free`.

* size: The number of bytes to allocate.
* returns: A pointer to the allocated memory region.

DUCKDB_API void *duckdb_malloc(size_t size);
"""
function duckdb_malloc(size)
    return ccall((:duckdb_malloc, libduckdb), Cvoid, (Csize_t,), size)
end

"""
duckdb_free(ptr)

Free a value returned from `duckdb_malloc`, `duckdb_value_varchar` or `duckdb_value_blob`.

* ptr: The memory region to de-allocate.

DUCKDB_API void duckdb_free(void *ptr);
"""
function duckdb_free(ptr)
    return ccall((:duckdb_malloc, libduckdb), Cvoid, (Ptr{Cvoid},), ptr)
end

#=
//===--------------------------------------------------------------------===//
// Date/Time/Timestamp Helpers
//===--------------------------------------------------------------------===//
=#

"""
duckdb_from_date(date)

Decompose a `duckdb_date` object into year, month and date (stored as `duckdb_date_struct`).

* date: The date object, as obtained from a `DUCKDB_TYPE_DATE` column.
* returns: The `duckdb_date_struct` with the decomposed elements.

DUCKDB_API duckdb_date_struct duckdb_from_date(duckdb_date date);
"""
function duckdb_from_date(date)
    return ccall((:duckdb_from_date, libduckdb), Ptr{Cvoid}, (Ptr{Cvoid},), date)
end

"""
duckdb_to_date(date)

Re-compose a `duckdb_date` from year, month and date (`duckdb_date_struct`).

* date: The year, month and date stored in a `duckdb_date_struct`.
* returns: The `duckdb_date` element.

DUCKDB_API duckdb_date duckdb_to_date(duckdb_date_struct date);
"""
function duckdb_to_date(date)
    return ccall((:duckdb_to_date, libduckdb), Ptr{Cvoid}, (Ptr{Cvoid},), date)
end

"""
duckdb_from_time(time)

Decompose a `duckdb_time` object into hour, minute, second and microsecond (stored as `duckdb_time_struct`).

* time: The time object, as obtained from a `DUCKDB_TYPE_TIME` column.
* returns: The `duckdb_time_struct` with the decomposed elements.

DUCKDB_API duckdb_time_struct duckdb_from_time(duckdb_time time);
"""
function duckdb_from_time(time)
    return ccall((:duckdb_from_time, libduckdb), Ptr{Cvoid}, (Ptr{Cvoid},), time)
end

"""
duckdb_to_time(time)

Re-compose a `duckdb_time` from hour, minute, second and microsecond (`duckdb_time_struct`).

* time: The hour, minute, second and microsecond in a `duckdb_time_struct`.
* returns: The `duckdb_time` element.

DUCKDB_API duckdb_time duckdb_to_time(duckdb_time_struct time);
"""
function duckdb_to_time(time)
    return ccall((:duckdb_to_time, libduckdb), Ptr{Cvoid}, (Ptr{Cvoid},), time)
end

"""
duckdb_from_timestamp(ts)

Decompose a `duckdb_timestamp` object into a `duckdb_timestamp_struct`.

* ts: The ts object, as obtained from a `DUCKDB_TYPE_TIMESTAMP` column.
* returns: The `duckdb_timestamp_struct` with the decomposed elements.

DUCKDB_API duckdb_timestamp_struct duckdb_from_timestamp(duckdb_timestamp ts);
"""
function duckdb_from_timestamp(ts)
    return ccall((:duckdb_from_timestamp, libduckdb), Ptr{Cvoid}, (Ptr{Cvoid},), ts)
end

"""
duckdb_to_timestamp(ts)

Re-compose a `duckdb_timestamp` from a duckdb_timestamp_struct.

* ts: The de-composed elements in a `duckdb_timestamp_struct`.
* returns: The `duckdb_timestamp` element.
*/
DUCKDB_API duckdb_timestamp duckdb_to_timestamp(duckdb_timestamp_struct ts);
"""
function duckdb_to_timestamp(ts)
    return ccall((:duckdb_to_timestamp, libduckdb), Ptr{Cvoid}, (Ptr{Cvoid},), ts)
end

#=
//===--------------------------------------------------------------------===//
// Hugeint Helpers
//===--------------------------------------------------------------------===//
=#

"""
duckdb_hugeint_to_double(val)

Converts a duckdb_hugeint object (as obtained from a `DUCKDB_TYPE_HUGEINT` column) into a double.

* val: The hugeint value.
* returns: The converted `double` element.

DUCKDB_API double duckdb_hugeint_to_double(duckdb_hugeint val);
"""
function duckdb_hugeint_to_double(val)
    return ccall((:duckdb_hugeint_to_double, libduckdb), Float64, (Int64,), val)
end

"""
duckdb_double_to_hugeint(val)

Converts a double value to a duckdb_hugeint object.

If the conversion fails because the double value is too big the result will be 0.

* val: The double value.
* returns: The converted `duckdb_hugeint` element.

DUCKDB_API duckdb_hugeint duckdb_double_to_hugeint(double val);
"""
function duckdb_double_to_hugeint(val)
    return ccall((:duckdb_double_to_hugeint, libduckdb), Int64, (Float64,), val)
end

#=
//===--------------------------------------------------------------------===//
// Prepared Statements
//===--------------------------------------------------------------------===//

// A prepared statement is a parameterized query that allows you to bind parameters to it.
// * This is useful to easily supply parameters to functions and avoid SQL injection attacks.
// * This is useful to speed up queries that you will execute several times with different parameters.
// Because the query will only be parsed, bound, optimized and planned once during the prepare stage,
// rather than once per execution.
// For example:
//   SELECT * FROM tbl WHERE id=?
// Or a query with multiple parameters:
//   SELECT * FROM tbl WHERE id=$1 OR name=$2
=#

"""
Create a prepared statement object from a query.

Note that after calling `duckdb_prepare`, the prepared statement should always be destroyed using
`duckdb_destroy_prepare`, even if the prepare fails.

If the prepare fails, `duckdb_prepare_error` can be called to obtain the reason why the prepare failed.

* connection: The connection object
* query: The SQL query to prepare
* out_prepared_statement: The resulting prepared statement object
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_prepare(duckdb_connection connection, const char *query,
                                       duckdb_prepared_statement *out_prepared_statement);
"""
function duckdb_prepare(connection, query, out_prepared_statement)
    return ccall(
        (:duckdb_prepare, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}, Ptr{Cvoid}),
        connection[],
        query,
        out_prepared_statement,
    )
end

"""
Closes the prepared statement and de-allocates all memory allocated for that connection.

* prepared_statement: The prepared statement to destroy.

DUCKDB_API void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);
"""
function duckdb_destroy_prepare(prepared_statement)
    return ccall((:duckdb_prepare, libduckdb), Cvoid, (Ptr{Cvoid},), prepared_statement)
end

"""
Returns the error message associated with the given prepared statement.
If the prepared statement has no error message, this returns `nullptr` instead.

The error message should not be freed. It will be de-allocated when `duckdb_destroy_prepare` is called.

* prepared_statement: The prepared statement to obtain the error from.
* returns: The error message, or `nullptr` if there is none.

DUCKDB_API const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);
"""
function duckdb_prepare_error(prepared_statement)
    return ccall(
        (:duckdb_prepare_error, libduckdb),
        Ptr{UInt8},
        (Ptr{Cvoid},),
        prepared_statement,
    )
end

"""
Returns the number of parameters that can be provided to the given prepared statement.

Returns 0 if the query was not successfully prepared.

* prepared_statement: The prepared statement to obtain the number of parameters for.

DUCKDB_API idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement);
"""
function duckdb_nparams(prepared_statement)
    return ccall((:duckdb_nparams, libduckdb), Int32, (Ptr{Cvoid},), prepared_statement)
end

"""
Returns the parameter type for the parameter at the given index.

Returns `DUCKDB_TYPE_INVALID` if the parameter index is out of range or the statement was not successfully prepared.

* prepared_statement: The prepared statement.
* param_idx: The parameter index.
* returns: The parameter type

DUCKDB_API duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);
"""
function duckdb_param_type(prepared_statement, param_idx)
    return ccall(
        (:duckdb_param_type, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        prepared_statement,
        param_idx,
    )
end

"""
Binds a bool value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_boolean(duckdb_prepared_statement prepared_statement, idx_t param_idx, bool val);
"""
function duckdb_bind_boolean(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_boolean, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an int8_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_int8(duckdb_prepared_statement prepared_statement, idx_t param_idx, int8_t val);
"""
function duckdb_bind_int8(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int8, libduckdb),
        Int16,
        (Ptr{Cvoid}, Int32, Int16),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an int16_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_int16(duckdb_prepared_statement prepared_statement, idx_t param_idx, int16_t val);
"""
function duckdb_bind_int16(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int16, libduckdb),
        Int16,
        (Ptr{Cvoid}, Int32, Int16),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an int32_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_int32(duckdb_prepared_statement prepared_statement, idx_t param_idx, int32_t val);
"""
function duckdb_bind_int32(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int32, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an int64_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_int64(duckdb_prepared_statement prepared_statement, idx_t param_idx, int64_t val);
"""
function duckdb_bind_int64(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int64, libduckdb),
        Int64,
        (Ptr{Cvoid}, Int32, Int64),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an duckdb_hugeint value to the prepared statement at the specified index.
*/
DUCKDB_API duckdb_state duckdb_bind_hugeint(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                            duckdb_hugeint val);
"""
function duckdb_bind_hugeint(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_hugeint, libduckdb),
        Int64,
        (Ptr{Cvoid}, Int32, Int64),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an uint8_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_uint8(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint8_t val);
"""
function duckdb_bind_uint8(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint8, libduckdb),
        UInt16,
        (Ptr{Cvoid}, Int32, UInt16),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an uint16_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_uint16(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint16_t val);
"""
function duckdb_bind_uint16(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint16, libduckdb),
        UInt16,
        (Ptr{Cvoid}, Int32, UInt16),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an uint32_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_uint32(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint32_t val);
"""
function duckdb_bind_uint32(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint32, libduckdb),
        UInt32,
        (Ptr{Cvoid}, Int32, UInt32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an uint64_t value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_uint64(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint64_t val);
"""
function duckdb_bind_uint64(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint64, libduckdb),
        UInt64,
        (Ptr{Cvoid}, Int32, UInt64),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an float value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_float(duckdb_prepared_statement prepared_statement, idx_t param_idx, float val);
"""
function duckdb_bind_float(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_float, libduckdb),
        Float32,
        (Ptr{Cvoid}, Int32, Float32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds an double value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_double(duckdb_prepared_statement prepared_statement, idx_t param_idx, double val);
"""
function duckdb_bind_double(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_float, libduckdb),
        Float64,
        (Ptr{Cvoid}, Int32, Float64),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds a duckdb_date value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_date(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                         duckdb_date val);
"""
function duckdb_bind_date(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_date, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds a duckdb_time value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_time(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                         duckdb_time val);
"""
function duckdb_bind_time(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_time, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds a duckdb_timestamp value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_timestamp(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                              duckdb_timestamp val);
"""
function duckdb_bind_timestamp(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_timestamp, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds a duckdb_interval value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_interval(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                             duckdb_interval val);
"""
function duckdb_bind_interval(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_interval, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Int32),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds a null-terminated varchar value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_varchar(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                            const char *val);
"""
function duckdb_bind_varchar(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_varchar, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Ptr{UInt8}),
        prepared_statement,
        param_idx,
        val,
    )
end

"""
Binds a varchar value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_varchar_length(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                                   const char *val, idx_t length);
"""
function duckdb_bind_varchar_length(prepared_statement, param_idx, val, length)
    return ccall(
        (:duckdb_bind_varchar_length, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Ptr{UInt8}, Int32),
        prepared_statement,
        param_idx,
        val,
        length,
    )
end

"""
Binds a blob value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_blob(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                         const void *data, idx_t length);
"""
function duckdb_bind_blob(prepared_statement, param_idx, val, length)
    return ccall(
        (:duckdb_bind_blob, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32, Ptr{Cvoid}, Int32),
        prepared_statement,
        param_idx,
        data,
        length,
    )
end

"""
Binds a NULL value to the prepared statement at the specified index.

DUCKDB_API duckdb_state duckdb_bind_null(duckdb_prepared_statement prepared_statement, idx_t param_idx);
"""
function duckdb_bind_null(prepared_statement, param_idx)
    return ccall(
        (:duckdb_bind_null, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        prepared_statement,
        param_idx,
    )
end

"""
Executes the prepared statement with the given bound parameters, and returns a materialized query result.

This method can be called multiple times for each prepared statement, and the parameters can be modified
between calls to this function.

* prepared_statement: The prepared statement to execute.
* out_result: The query result.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statement,
                                                duckdb_result *out_result);
"""
function duckdb_execute_prepared(prepared_statement, out_result)
    return ccall(
        (:duckdb_execute_prepared, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{Cvoid}),
        prepared_statement,
        out_result,
    )
end

"""
Executes the prepared statement with the given bound parameters, and returns an arrow query result.

* prepared_statement: The prepared statement to execute.
* out_result: The query result.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_statement,
                                                      duckdb_arrow *out_result);
"""
function duckdb_execute_prepared_arrow(prepared_statement, out_result)
    return ccall(
        (:duckdb_execute_prepared_arrow, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{Cvoid}),
        prepared_statement,
        out_result,
    )
end

#=
//===--------------------------------------------------------------------===//
// Appender
//===--------------------------------------------------------------------===//

// Appenders are the most efficient way of loading data into DuckDB from within the C interface, and are recommended for
// fast data loading. The appender is much faster than using prepared statements or individual `INSERT INTO` statements.

// Appends are made in row-wise format. For every column, a `duckdb_append_[type]` call should be made, after which
// the row should be finished by calling `duckdb_appender_end_row`. After all rows have been appended,
// `duckdb_appender_destroy` should be used to finalize the appender and clean up the resulting memory.

// Note that `duckdb_appender_destroy` should always be called on the resulting appender, even if the function returns
// `DuckDBError`.
=#

"""
Creates an appender object.

* connection: The connection context to create the appender in.
* schema: The schema of the table to append to, or `nullptr` for the default schema.
* table: The table name to append to.
* out_appender: The resulting appender object.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_appender_create(duckdb_connection connection, const char *schema, const char *table,
                                               duckdb_appender *out_appender);
"""
function duckdb_appender_create(connection, schema, table, out_appender)
    return ccall(
        (:duckdb_appender_create, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Cvoid}),
        connection[],
        schema,
        table,
        out_appender,
    )
end

"""
Returns the error message associated with the given appender.
If the appender has no error message, this returns `nullptr` instead.

The error message should not be freed. It will be de-allocated when `duckdb_appender_destroy` is called.

* appender: The appender to get the error from.
* returns: The error message, or `nullptr` if there is none.

DUCKDB_API const char *duckdb_appender_error(duckdb_appender appender);
"""
function duckdb_appender_error(appender)
    return ccall((:duckdb_appender_error, libduckdb), Ptr{UInt8}, (Ptr{Cvoid},), appender)
end

"""
Flush the appender to the table, forcing the cache of the appender to be cleared and the data to be appended to the
base table.

This should generally not be used unless you know what you are doing. Instead, call `duckdb_appender_destroy` when you
are done with the appender.

* appender: The appender to flush.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_appender_flush(duckdb_appender appender);
"""
function duckdb_appender_flush(appender)
    return ccall((:duckdb_appender_flush, libduckdb), Int32, (Ptr{Cvoid},), appender)
end

"""
Close the appender, flushing all intermediate state in the appender to the table and closing it for further appends.

This is generally not necessary. Call `duckdb_appender_destroy` instead.

* appender: The appender to flush and close.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_appender_close(duckdb_appender appender);
"""
function duckdb_appender_close(appender)
    return ccall((:duckdb_appender_close, libduckdb), Int32, (Ptr{Cvoid},), appender)
end

"""
Close the appender and destroy it. Flushing all intermediate state in the appender to the table, and de-allocating
all memory associated with the appender.

* appender: The appender to flush, close and destroy.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_appender_destroy(duckdb_appender *appender);
"""
function duckdb_appender_destroy(appender)
    return ccall((:duckdb_appender_destroy, libduckdb), Int32, (Ptr{Ptr{Cvoid}},), appender)
end

"""
A nop function, provided for backwards compatibility reasons. Does nothing. Only `duckdb_appender_end_row` is required.

DUCKDB_API duckdb_state duckdb_appender_begin_row(duckdb_appender appender);
"""
function duckdb_appender_begin_row(appender)
    return ccall((:duckdb_appender_begin_row, libduckdb), Int32, (Ptr{Cvoid},), appender)
end

"""
Finish the current row of appends. After end_row is called, the next row can be appended.

* appender: The appender.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_appender_end_row(duckdb_appender appender);
"""
function duckdb_appender_end_row(appender)
    return ccall((:duckdb_appender_end_row, libduckdb), Int32, (Ptr{Cvoid},), appender)
end

"""
Append a bool value to the appender.

DUCKDB_API duckdb_state duckdb_append_bool(duckdb_appender appender, bool value);
"""
function duckdb_append_bool(appender, value)
    return ccall(
        (:duckdb_append_bool, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        appender,
        value,
    )
end

"""
Append an int8_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_int8(duckdb_appender appender, int8_t value);
"""
function duckdb_append_int8(appender, value)
    return ccall(
        (:duckdb_append_int8, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int16),
        appender,
        value,
    )
end

"""
Append an int16_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_int16(duckdb_appender appender, int16_t value);
"""
function duckdb_append_int16(appender, value)
    return ccall(
        (:duckdb_append_int16, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int16),
        appender,
        value,
    )
end

"""
Append an int32_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_int32(duckdb_appender appender, int32_t value);
"""
function duckdb_append_int32(appender, value)
    return ccall(
        (:duckdb_append_int16, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        appender,
        value,
    )
end

"""
Append an int64_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_int64(duckdb_appender appender, int64_t value);
"""
function duckdb_append_int64(appender, value)
    return ccall(
        (:duckdb_append_int64, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int64),
        appender,
        value,
    )
end

"""
Append a duckdb_hugeint value to the appender.

DUCKDB_API duckdb_state duckdb_append_hugeint(duckdb_appender appender, duckdb_hugeint value);
"""
function duckdb_append_hugeint(appender, value)
    return ccall(
        (:duckdb_append_hugeint, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int64),
        appender,
        value,
    )
end

"""
Append a uint8_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_uint8(duckdb_appender appender, uint8_t value);
"""
function duckdb_append_uint8(appender, value)
    return ccall(
        (:duckdb_append_uint8, libduckdb),
        Int32,
        (Ptr{Cvoid}, UInt16),
        appender,
        value,
    )
end

"""
Append a uint16_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_uint16(duckdb_appender appender, uint16_t value);
"""
function duckdb_append_uint16(appender, value)
    return ccall(
        (:duckdb_append_uint16, libduckdb),
        Int32,
        (Ptr{Cvoid}, UInt16),
        appender,
        value,
    )
end

"""
Append a uint32_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_uint32(duckdb_appender appender, uint32_t value);
"""
function duckdb_append_uint32(appender, value)
    return ccall(
        (:duckdb_append_uint32, libduckdb),
        Int32,
        (Ptr{Cvoid}, UInt32),
        appender,
        value,
    )
end

"""
Append a uint64_t value to the appender.

DUCKDB_API duckdb_state duckdb_append_uint64(duckdb_appender appender, uint64_t value);
"""
function duckdb_append_uint64(appender, value)
    return ccall(
        (:duckdb_append_uint64, libduckdb),
        Int32,
        (Ptr{Cvoid}, UInt64),
        appender,
        value,
    )
end

"""
Append a float value to the appender.

DUCKDB_API duckdb_state duckdb_append_float(duckdb_appender appender, float value);
"""
function duckdb_append_float(appender, value)
    return ccall(
        (:duckdb_append_float, libduckdb),
        Int32,
        (Ptr{Cvoid}, Float32),
        appender,
        value,
    )
end

"""
Append a double value to the appender.

DUCKDB_API duckdb_state duckdb_append_double(duckdb_appender appender, double value);
"""
function duckdb_append_double(appender, value)
    return ccall(
        (:duckdb_append_double, libduckdb),
        Int32,
        (Ptr{Cvoid}, Float64),
        appender,
        value,
    )
end

"""
Append a duckdb_date value to the appender.

DUCKDB_API duckdb_state duckdb_append_date(duckdb_appender appender, duckdb_date value);
"""
function duckdb_append_date(appender, value)
    return ccall(
        (:duckdb_append_date, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        appender,
        value,
    )
end

"""
Append a duckdb_time value to the appender.

DUCKDB_API duckdb_state duckdb_append_time(duckdb_appender appender, duckdb_time value);
"""
function duckdb_append_time(appender, value)
    return ccall(
        (:duckdb_append_time, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        appender,
        value,
    )
end

"""
Append a duckdb_timestamp value to the appender.

DUCKDB_API duckdb_state duckdb_append_timestamp(duckdb_appender appender, duckdb_timestamp value);
"""
function duckdb_append_timestamp(appender, value)
    return ccall(
        (:duckdb_append_timestamp, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        appender,
        value,
    )
end

"""
Append a duckdb_interval value to the appender.

DUCKDB_API duckdb_state duckdb_append_interval(duckdb_appender appender, duckdb_interval value);
"""
function duckdb_append_interval(appender, value)
    return ccall(
        (:duckdb_append_interval, libduckdb),
        Int32,
        (Ptr{Cvoid}, Int32),
        appender,
        value,
    )
end

"""
Append a varchar value to the appender.

DUCKDB_API duckdb_state duckdb_append_varchar(duckdb_appender appender, const char *val);
"""
function duckdb_append_varchar(appender, value)
    return ccall(
        (:duckdb_append_varchar, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}),
        appender,
        value,
    )
end

"""
Append a varchar value to the appender.

DUCKDB_API duckdb_state duckdb_append_varchar_length(duckdb_appender appender, const char *val, idx_t length);
"""
function duckdb_append_varchar_length(appender, value, length)
    return ccall(
        (:duckdb_append_varchar_length, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}, Int32),
        appender,
        value,
        length,
    )
end

"""
Append a blob value to the appender.

DUCKDB_API duckdb_state duckdb_append_blob(duckdb_appender appender, const void *data, idx_t length);
"""
function duckdb_append_blob(appender, data, length)
    return ccall(
        (:duckdb_append_blob, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{Cvoid}, Int32),
        appender,
        data,
        length,
    )
end

"""
Append a NULL value to the appender (of any type).

DUCKDB_API duckdb_state duckdb_append_null(duckdb_appender appender);
"""
function duckdb_append_null(appender)
    return ccall((:duckdb_append_null, libduckdb), Int32, (Ptr{Cvoid},), appender)
end

#=
//===--------------------------------------------------------------------===//
// Arrow Interface
//===--------------------------------------------------------------------===//
=#

"""
Executes a SQL query within a connection and stores the full (materialized) result in an arrow structure.
If the query fails to execute, DuckDBError is returned and the error message can be retrieved by calling
`duckdb_query_arrow_error`.

Note that after running `duckdb_query_arrow`, `duckdb_destroy_arrow` must be called on the result object even if the
query fails, otherwise the error stored within the result will not be freed correctly.

* connection: The connection to perform the query in.
* query: The SQL query to run.
* out_result: The query result.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_query_arrow(duckdb_connection connection, const char *query, duckdb_arrow *out_result);
"""
function duckdb_query_arrow(connection, query, out_result)
    return ccall(
        (:duckdb_query_arrow, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}, Ptr{Cvoid}),
        connection[],
        query,
        out_result,
    )
end

"""
Fetch the internal arrow schema from the arrow result.

* result: The result to fetch the schema from.
* out_schema: The output schema.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_query_arrow_schema(duckdb_arrow result, duckdb_arrow_schema *out_schema);
"""
function duckdb_query_arrow_schema(result, out_schema)
    return ccall(
        (:duckdb_query_arrow_schema, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{UInt8}),
        result,
        out_schema,
    )
end

"""
Fetch an internal arrow array from the arrow result.

This function can be called multiple time to get next chunks, which will free the previous out_array.
So consume the out_array before calling this function again.

* result: The result to fetch the array from.
* out_array: The output array.
* returns: `DuckDBSuccess` on success or `DuckDBError` on failure.

DUCKDB_API duckdb_state duckdb_query_arrow_array(duckdb_arrow result, duckdb_arrow_array *out_array);
"""
function duckdb_query_arrow_array(result, out_array)
    return ccall(
        (:duckdb_query_arrow_array, libduckdb),
        Int32,
        (Ptr{Cvoid}, Ptr{Cvoid}),
        result,
        out_array,
    )
end

"""
Returns the number of columns present in a the arrow result object.

* result: The result object.
* returns: The number of columns present in the result object.

DUCKDB_API idx_t duckdb_arrow_column_count(duckdb_arrow result);
"""
function duckdb_arrow_column_count(result)
    return ccall((:duckdb_arrow_column_count, libduckdb), Int32, (Ptr{Cvoid},), result)
end

"""
Returns the number of rows present in a the arrow result object.

* result: The result object.
* returns: The number of rows present in the result object.

DUCKDB_API idx_t duckdb_arrow_row_count(duckdb_arrow result);
"""
function duckdb_arrow_row_count(result)
    return ccall((:duckdb_arrow_row_count, libduckdb), Int64, (Ptr{Cvoid},), result)
end

"""
Returns the number of rows changed by the query stored in the arrow result. This is relevant only for
INSERT/UPDATE/DELETE queries. For other queries the rows_changed will be 0.

* result: The result object.
* returns: The number of rows changed.

DUCKDB_API idx_t duckdb_arrow_rows_changed(duckdb_arrow result);
"""
function duckdb_arrow_rows_changed(result)
    return ccall((:duckdb_arrow_rows_changed, libduckdb), Int64, (Ptr{Cvoid},), result)
end

"""
Returns the error message contained within the result. The error is only set if `duckdb_query_arrow` returns
`DuckDBError`.

The error message should not be freed. It will be de-allocated when `duckdb_destroy_arrow` is called.

* result: The result object to fetch the nullmask from.
* returns: The error of the result.

DUCKDB_API const char *duckdb_query_arrow_error(duckdb_arrow result);
"""
function duckdb_query_arrow_error(result)
    return ccall((:duckdb_query_arrow_error, libduckdb), Ptr{UInt8}, (Ptr{Cvoid},), result)
end

"""
Closes the result and de-allocates all memory allocated for the arrow result.

* result: The result to destroy.

DUCKDB_API void duckdb_destroy_arrow(duckdb_arrow *result);
"""
function duckdb_destroy_arrow(result)
    return ccall((:duckdb_destroy_arrow, libduckdb), Cvoid, (Ptr{Ptr{Cvoid}},), result)
end


text:
module MaxHelpingHandCustomTutorialWithNoBird

using ..Ahorn, Maple

@mapdef Entity "MaxHelpingHand/CustomTutorialWithNoBird" CustomTutorialWithNoBird(x::Integer, y::Integer, birdId::String="", onlyOnce::Bool=false,
    info::String="TUTORIAL_DREAMJUMP", controls::String="DownRight,+,Dash,tinyarrow,Jump", hasPointer::Bool=true)

using ..Ahorn, Maple

const placements = Ahorn.PlacementDict(
    "Custom Tutorial with No Bird (max480's Helping Hand)" => Ahorn.EntityPlacement(
        CustomTutorialWithNoBird
    )
)

Ahorn.editingOptions(entity::CustomTutorialWithNoBird) = return Dict{String, Any}(
    "info" => Maple.everest_bird_tutorial_tutorials
)

sprite = "ahorn/MaxHelpingHand/greyscale_birb"

function Ahorn.selection(entity::CustomTutorialWithNoBird)
    x, y = Ahorn.position(entity)
    scaleX = -1

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

function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::CustomTutorialWithNoBird, room::Maple.Room)
    scaleX = -1

    Ahorn.drawSprite(ctx, sprite, 0, 0, sx=scaleX, jx=0.5, jy=1.0)
end

end

max_stars_repo_name: Kitty-Cats/MaxHelpingHand

max_issues_repo_name: Kitty-Cats/MaxHelpingHand

max_forks_repo_name: Kitty-Cats/MaxHelpingHand


text:
@testset "uniform random walk" begin
    @testset "initialisation" begin
        @test_throws MethodError BSI.UniformRandomWalk([1.0])
        @test BSI.UniformRandomWalk(1.0).ϵ == 1.0
        @test BSI.UniformRandomWalk(1.0).pos == false
        @test BSI.UniformRandomWalk(2.0, true).ϵ == 2.0
        @test BSI.UniformRandomWalk(1.0, true).pos
    end
    @testset "random draw" begin
        using Random
        ϵ = 1.0
        Random.seed!(4)
        rand_value = rand(Uniform(-ϵ, ϵ))

        Random.seed!(4)
        rw = BSI.UniformRandomWalk(ϵ)
        θ = [2.0, 3.0]
        @test rand(rw, θ, Val{(false,true)}()) == θ .+ [0.0, rand_value]
        @test θ == [2.0, 3.0]

        Random.seed!(4)
        rand!(rw, θ, Val{(false,true)}())
        @test θ == [2.0, 3.0 + rand_value]
    end
    @testset "logpdf" begin
        ϵ = 1.0
        rw = BSI.UniformRandomWalk(ϵ)
        θ, θᵒ = [2.0, 3.0], [1.0, 5.0]
        @test logpdf(rw, Val{(true, false)}(), θ, θᵒ) == 0.0
        rw = BSI.UniformRandomWalk(1.0, true)
        @test logpdf(rw, Val{(true, false)}(), θ, θᵒ) == -log(2.0*ϵ)-log(θᵒ[1])
        @test_throws AssertionError logpdf(rw, Val{(true, true)}(), θ, θᵒ)
    end
    @testset "readjustment" begin
        ϵ = 1.0
        rw = BSI.UniformRandomWalk(ϵ, true)
        accpt_track = BSI.AccptTracker(0)
        for i in 1:10 BSI.register_accpt!(accpt_track, true) end
        for i in 1:10 BSI.register_accpt!(accpt_track, false) end
        δ = 0.1
        param = BSI.named_readjust((100, δ, 0.0, 999.9, 0.234, 50))
        @suppress BSI.readjust!(rw, accpt_track, param, nothing, 10, nothing)
        @test rw.ϵ == 1.0+δ

        BSI.reset!(accpt_track)
        for i in 1:2 BSI.register_accpt!(accpt_track, true) end
        for i in 1:10 BSI.register_accpt!(accpt_track, false) end
        @suppress BSI.readjust!(rw, accpt_track, param, nothing, 11, nothing)
        @test rw.ϵ == 1.0

    end
end