text:
# -------- Layer ------------------------------------------------------------- #

"""
Layers are the functional units for `NeuralNetworkModels`. They are composable
and, by the macros `@chain` and `@stack`, allow for the easy creation of neural
networks that are compatible to a given game.
"""
abstract type Layer{GPU} <: Element{GPU} end

valid_insize(:: Layer, _) = error("Not implemented")
outsize(:: Layer, _) = error("Not implemented")

# -------- Primitive / Composite --------------------------------------------- #

"""
An atomic neural network operation.
"""
abstract type PrimitiveLayer{GPU} <: Layer{GPU} end

"""
A composed neural network operation
"""
abstract type CompositeLayer{GPU} <: Layer{GPU} end

"""
    layers(clayer)

Get all neural network layers of an the composite layer `clayer`.
"""
layers( :: CompositeLayer) = error("Not implemented")

# -------- Auxiliary Functions ----------------------------------------------- #

# Convert (gpu :: Bool) to the underlying representing array type

atype(gpu :: Bool) = gpu ? Knet.KnetArray{Float32} : Array{Float32}

# Check if something is a AutoGrad param or not

is_param(p) = isa(p, Knet.Param)

# Function to copy (and convert) objects of type Param
# For convenience, we allow this function to be applied to other objects as well

function copy_param(p :: Knet.Param; at = nothing)

  if at == nothing || isa(Knet.value(p), at)
    val = copy(Knet.value(p))
  else
    val = convert(at, Knet.value(p))
  end

  param = Knet.Param(val)
  param.opt = p.opt
  param

end

function copy_param(p; at = nothing)
  if at == nothing || isa(p, at)
    copy(p)
  else
    convert(at, p)
  end
end

# Auxiliary function used for the constructor of some layers

expand_to_pair(t :: NTuple{2, Int}) = t
expand_to_pair(t :: Int) = (t, t)

# -------- Pointwise --------------------------------------------------------- #

"""
Neural network layer that applies a function pointwisely.
"""
struct Pointwise{GPU} <: PrimitiveLayer{GPU}
  f # Activation function
end

Pointwise( f = Knet.identity; gpu = false ) = Pointwise{gpu}(f)

(p :: Pointwise)(x) = p.f.(x)

swap(p :: Pointwise{GPU}) where {GPU} = Pointwise(p.f, gpu = !GPU)
Base.copy(p :: Pointwise) = p

valid_insize(:: Pointwise, _) = true
outsize(p :: Pointwise, s) = s

# -------- Dense ------------------------------------------------------------- #

"""
Dense neural network layer.
"""
struct Dense{GPU} <: PrimitiveLayer{GPU}
  w  # Weight matrix
  b  # Bias vector
  f  # Activation function
end

function Dense( i :: Int, o :: Int, f = Knet.identity;
                bias = true, gpu = false )
  at = atype(gpu)
  w = Knet.param(o, i, atype = at)
  b = bias ? Knet.param0(o, atype = at) : convert(at, zeros(Float32, o))
  Dense{gpu}(w, b, f)
end

(d :: Dense)(x) = d.f.(d.w * Knet.mat(x) .+ d.b)

function swap(d :: Dense{GPU}) where {GPU}
  at = atype(!GPU)
  w = copy_param(d.w, at = at)
  b = copy_param(d.b, at = at)
  Dense{!GPU}(w, b, d.f)
end

function Base.copy(d :: Dense{GPU}) where {GPU}
  Dense{GPU}(copy_param(d.w), copy_param(d.b), d.f)
end

# Check if some input of a given size s can be processed by the layer
# Note that the batchsize is not part of s, so s will usually have
# Dimension 1 (after dense layers) or 3 (before/after convolution layers)
valid_insize(d :: Dense, s) = (prod(s) == size(d.w, 2))

# Get the correct output size for a respective input size
function outsize(d :: Dense, s)
  @assert valid_insize(d, s) "Layer cannot be applied to input of size $s"
  size(d.w, 1)
end

# ------- Convolution -------------------------------------------------------- #

"""
Convolutional neural network layer.
"""
struct Conv{GPU} <: PrimitiveLayer{GPU}
  w  # Convolutional kernel
  b  # Bias vector
  f  # Activation function

  p  # Padding for the convolution
  s  # Stride for the convolution
end

function Conv( ci :: Int, co :: Int, f = Knet.identity;
               window = 3, padding = 0,
               stride = 1, bias = true, gpu = false )

  k = expand_to_pair(window)
  p = expand_to_pair(padding)
  s = expand_to_pair(stride)

  at = atype(gpu)
  w = Knet.param(k[1], k[2], ci, co, atype = at)

  if bias
    b = Knet.param0(1, 1, co, 1, atype = at)
  else
    b = convert(at, zeros(Float32, 1, 1, co, 1))
  end

  Conv{gpu}(w, b, f, p, s)

end

(c :: Conv)(x) = c.f.(Knet.conv4(c.w, x, padding = c.p, stride = c.s) .+ c.b)

function swap(c :: Conv{GPU}) where {GPU}
  at = atype(!GPU)
  w = copy_param(c.w, at = at)
  b = copy_param(c.b, at = at)
  Conv{!GPU}(w, b, c.f, c.p, c.s)
end

function Base.copy(c :: Conv{GPU}) where {GPU}
  Conv{GPU}(copy_param(c.w), copy_param(c.b), c.f, c.p, c.s)
end

function valid_insize(c :: Conv, s)
  all(( length(s) == 3,
        s[1] >= size(c.w, 1) - c.p[1],
        s[2] >= size(c.w, 2) - c.p[2],
        s[3] == size(c.w, 3) ))
end

function outsize(c :: Conv, s)
  @assert valid_insize(c, s) "Layer cannot be applied to input of size $s"
  ( 1 + (div(s[1] + 2c.p[1] - size(c.w, 1), c.s[1]) |> floor),
    1 + (div(s[2] + 2c.p[2] - size(c.w, 2), c.s[2]) |> floor),
    size(c.w, 4)
  )
end

# -------- Deconvolution ----------------------------------------------------- #

"""
De-convolutional neural network layer.
"""
struct Deconv{GPU} <: PrimitiveLayer{GPU}
  w  # Deconvolutional kernel
  b  # Bias vector
  f  # Activation function

  p  # Padding for the convolution
  s  # Stride for the convolution
end

function Deconv( ci :: Int, co :: Int, f = Knet.identity;
                 window :: Int = 3, padding = 0,
                 stride = 1, bias = true, gpu = false )

  k = expand_to_pair(window)
  p = expand_to_pair(padding)
  s = expand_to_pair(stride)

  at = atype(gpu)
  w = Knet.param(k[1], k[2], co, ci, atype = at)

  if bias
    b = Knet.param0(1, 1, co, 1, atype = at)
  else
    b = convert(at, zeros(Float32, 1, 1, co, 1))
  end

  Deconv{gpu}(w, b, f, p, s)

end

(d :: Deconv)(x) = d.f.(Knet.deconv4(d.w, x, padding = d.p, stride = d.s) .+ d.b)

function swap(d :: Deconv{GPU}) where {GPU}
  at = atype(!GPU)
  w = copy_param(d.w, at = at)
  b = copy_param(d.b, at = at)
  Deconv{!GPU}(w, b, d.f, d.p, d.s)
end

function Base.copy(d :: Deconv{GPU}) where {GPU}
  Deconv{GPU}(copy_param(d.w), copy_param(d.b), d.f, d.p, d.s)
end

valid_insize(d :: Deconv, s) = (length(s) == 3)

function outsize(d :: Deconv, s)
  @assert valid_insize(d, s) "Layer cannot be applied to input of size $s"
  ( size(d.w, 1) + d.s[1] * (s[1] - 1) - 2d.p[1],
    size(d.w, 2) + d.s[2] * (s[1] - 1) - 2d.p[2],
    size(d.w, 3) )
end

# -------- Pooling ----------------------------------------------------------- #

"""
Pooling layer.
"""
struct Pool{GPU} <: PrimitiveLayer{GPU}
  w  # Window size for the pooling operation
  p  # Padding
  s  # Stride
  f  # Activation function
end

function Pool(f = Knet.identity;
              window = 2, padding = 0, stride = window, gpu = false)
  w, p, s = expand_to_pair.((window, padding, stride))
  Pool{gpu}(w, p, s, f)
end

function (p :: Pool)(x)
  p.f.(Knet.pool(x, window = p.w, padding = p.p, stride = p.s))
end

swap(p :: Pool{GPU}) where {GPU} = Pool{!GPU}(p.w, p.p, p.s, p.f)
Base.copy(p :: Pool) = p

function valid_insize(p :: Pool, s)
  all(( length(s) == 3,
        s[1] >= p.w[1] - p.p[1],
        s[2] >= p.w[2] - p.p[2] ))
end

function outsize(p :: Pool, s)
  @assert valid_insize(p, s) "Layer cannot be applied to input of size $s"
  ( 1 + div(s[1] + 2p.p[1] - p.w[1], p.s[1]),
    1 + div(s[2] + 2p.p[2] - p.w[2], p.s[2]),
    s[3]
  )
end

# -------- Dropout ----------------------------------------------------------- #

# Note that we try to recognize if we are training (dropout is active)
# or not. This can only be done if the Dropout layer is not the first layer
# that manipulates the weights

"""
Dropout layer. This must not be the first layer of the network.
"""
struct Dropout{GPU} <: PrimitiveLayer{GPU}
  prob
  f
end

Dropout(prob, f = Knet.identity; gpu = false) = Dropout{gpu}(prob, f)

function (d :: Dropout)(x)
  if isa(x, AutoGrad.Value)
    d.f.(Knet.dropout(x, d.prob))
  else
    d.f.(x)
  end
end

swap(d :: Dropout{GPU}) where {GPU} = Dropout{!GPU}(d.prob, d.f)
Base.copy(d :: Dropout) = d

valid_insize(:: Dropout, s) = true
outsize(:: Dropout, s) = s

# -------- Batch Normalization ----------------------------------------------- #

"""
Batch normalization layer.
"""
struct Batchnorm{GPU} <: PrimitiveLayer{GPU}
  moments
  params
  f
end

function Batchnorm(channels, f = Knet.identity; gpu = false)
  b = Batchnorm{false}(Knet.bnmoments(), Knet.bnparams(Float32, channels), f)
  gpu ? swap(b) : b
end

(b :: Batchnorm)(x) = b.f.(Knet.batchnorm(x, b.moments, b.params))

function swap(b :: Batchnorm{GPU}) where {GPU}
  at = atype(!GPU)
  mean = (b.moments.mean != nothing) ? convert(at, b.moments.mean) : nothing
  var  = (b.moments.var != nothing) ? convert(at, b.moments.var) : nothing
  moments = Knet.bnmoments(momentum = b.moments.momentum, mean = mean, var = var)
  Batchnorm{!GPU}(moments, copy_param(b.params, at = at), b.f)
end

function Base.copy(b :: Batchnorm{GPU}) where {GPU}
  mean = (b.moments.mean != nothing) ? copy(b.moments.mean) : nothing
  var  = (b.moments.var  != nothing) ? copy(b.moments.var)  : nothing
  moments = Knet.bnmoments(momentum = b.moments.momentum, mean = mean, var = var)
  Batchnorm{GPU}(moments, copy_param(b.params), b.f)
end

valid_insize(:: Batchnorm, s) = true
outsize(:: Batchnorm, s) = s

# -------- Chain ------------------------------------------------------------- #

"""
Composition of neural network layers.
"""
struct Chain{GPU} <: CompositeLayer{GPU}
  layers
end

function Chain(layers :: Layer{GPU}...; gpu = nothing) where {GPU}
  c = Chain{GPU}(Layer[l for l in layers])
  if !isnothing(gpu)
    gpu != GPU ? swap(c) : c
  else
    c
  end
end

function (c :: Chain)(x)
  for l in c.layers
    x = l(x)
  end
  x
end

swap(c :: Chain{GPU}) where {GPU} = Chain(swap.(c.layers)...)
Base.copy(c :: Chain{GPU}) where {GPU} = Chain(copy.(c.layers)...)

valid_insize(c :: Chain, s) = valid_insize(c.layers[1], s)

function outsize(c :: Chain, s)
  for l in c.layers
    s = outsize(l, s)
  end
  s
end

layers(c :: Chain) = c.layers

# -------- Stack ------------------------------------------------------------- #

"""
A stack of neural network layers. It is similar to a chain, but all
intermediate layers are concatenated in the output of the stack.
"""
struct Stack{GPU} <: CompositeLayer{GPU}
  layers
  stack_input :: Bool
end

function Stack(layers :: Layer{GPU}...;
               gpu = nothing, stack_input :: Bool = false) where {GPU}

  s = Stack{GPU}(Layer[l for l in layers], stack_input)

  if !isnothing(gpu)
    gpu != GPU ? swap(s) : s
  else
    s
  end

end

function (s :: Stack{GPU})(x) where {GPU}

  batchsize = size(x)[end]

  features = s.stack_input ? Any[x] : Any[]

  for layer in s.layers
    x = layer(x)
    push!(features, x)
  end

  features = map(features) do data
    reshape(data, (prod(size(data)[1:end-1]), batchsize))
  end

  vcat(features...)

end

function swap(s :: Stack{GPU}) where {GPU}
  Stack(swap.(s.layers)..., stack_input = s.stack_input)
end

function Base.copy(s :: Stack{GPU}) where {GPU}
  Stack(copy.(s.layers)..., stack_input = s.stack_input)
end

valid_insize(stack :: Stack, s) = valid_insize(stack.layers[1], s)

function outsize(stack :: Stack, s)

  shapes  = []
  lengths = Int[]

  if stack.stack_input
    push!(shapes, s)
    push!(lengths, prod(s))
  end

  for layer in stack.layers
    @assert valid_insize(layer, s)
    s = outsize(layer, s)
    push!(shapes, s)
    push!(lengths, prod(s))
  end

  sum(lengths)
end

layers(s :: Stack) = s.layers

# -------- Residual ---------------------------------------------------------- #

"""
Residual block that wraps a chain. The input to the residual block is added
to the output of the chain (on the same input). Note that the chain must be
shape-conserving.
"""
struct Residual{GPU} <: CompositeLayer{GPU}
  chain :: Chain{GPU}
end

#function Residual(c :: Chain{GPU}; gpu = GPU) where {GPU}
#  new{gpu}(gpu == GPU ? c : swap(c))
#end

function Residual(layers :: Layer{GPU}...; gpu = GPU) where {GPU}
  ls = (gpu == GPU) ? Layer[layers...] : Layer[swap.(layers)...]
  Residual(Chain(ls...))
end

(r :: Residual)(x) = r.chain(x) .+ x

swap(r :: Residual{GPU}) where {GPU} = Residual{!GPU}(swap(r.chain))
Base.copy(r :: Residual{GPU}) where {GPU} = Residual{GPU}(copy(r.chain))

function valid_insize(r :: Residual, s)

  valid = valid_insize(r.chain, s)

  if valid
    os = outsize(r.chain, s)
    os != s && error("Residual chain is not shape-conserving: $os != $s.")
  end

  valid

end

function outsize(r :: Residual, s)
  os = outsize(r.chain, s)
  os != s && error("Residual layer is not shape-conserving: $os != $s.")
  os
end

layers(r :: Residual) = layers(r.chain)

# -------- Chain/Stack Macro ------------------------------------------------- #

getsize(t :: Int) = t
getsize(t :: Tuple) = t
getsize(g :: Game) = size(g)
getsize(:: Type{G}) where {G <: Game} = size(G)

function composite_arguments(symbol :: Symbol, size)
  if symbol in (:Dense,)
    (prod(size),)
  elseif symbol in (:Conv, :Deconv)
    (size[3],)
  elseif symbol in (:Batchnorm,)
    (size[end],)
  elseif symbol in (:Chain, :Stack, :Pool, :Dropout, :Pointwise)
    ()
  else
    error("$symbol is no valid layer constructor")
  end
end

# Take the size of a game / a game type itself as first argument,
# and take a tuple of "partial" layer constructors as second argument.
# The macro will calculate and prepend the constructor arguments that relate to
# the input size for each layer consecutively.
#
# Example:
#
#   @chain (9,9,1) (Conv(10), Dense(50))
#
# will call
#
#   Chain(Conv(1, 10), Dense(490, 50))
#
# such that the two layers are compatible.

function composite_macro_body(c, ex, layers...)

  s = :(Jtac.getsize($ex))

  ssym = gensym("s")
  names = []
  body = Any[:(local $ssym = $s)]

  # Expand begin-end blocks
  layers = mapreduce(vcat, layers) do layer
    if isa(layer, Expr) && layer.head == :block
      filter(x -> !isa(x, LineNumberNode), layer.args)
    else
      [layer]
    end
  end

  # Catch keyword arguments
  kwidx = findall(layers) do layer
    isa(layer, Expr) && layer.head == :(=)
  end

  # Convert them to real keyword arguments
  kwargs = map(layers[kwidx]) do kw
    Expr(:call, :(=>), QuoteNode(kw.args[1]), kw.args[2])
  end

  # Extract network layers
  layers = layers[setdiff(1:length(layers), kwidx)]

  if length(layers) == 1 && isa(layers[1], Expr) && layers[1].head == :block
    layers = filter(x -> !isa(x, LineNumberNode), layers[1].args)
  end

  for layer in layers

    # The "layer" is assumed to be a
    #   1. :call Expression
    #   2. :macrocall Expression
    #   3. Symbol
    #   4. Keyword argument for the chain call
    #
    # If it is a call, we may insert additional input size information
    # via Jtac.composite_arguments. If it is a macrocall, we give the macro a
    # new first argument, the total input size. If it is a symbol, we
    # leave it as it is.

    if isa(layer, Expr) && layer.head == :call

      # Maybe add missing input size argument
      ltype = :($(layer.args[1]))
      args = Expr(:call, :(Jtac.composite_arguments), QuoteNode(ltype), ssym)
      insert!(layer.args, 2, :($args...))

    elseif isa(layer, Expr) && layer.head == :macrocall

      # Add input size argument
      insert!(layer.args, 3, ssym)

    end

    # Give the layer a temporary name
    name = gensym("l")
    push!(names, name)

    # Add the evaluation of the completed layer constructor to the body
    push!(body, :(local $name = $(layer)))

    # Obtain the new input size
    push!(body, :(local $ssym = outsize($name, $ssym)))

  end

  name = gensym("l")
  # Join all defined layers to a chain
  push!(body, :(local $name = $c($(Expr(:vect, names...))...; $(Expr(:vect, kwargs...))...)))
  push!(body, :(@assert valid_insize($name, $s) "Macro failed to respect input size. This should not happen."))
  push!(body, :($name))

  # Return the created block of code
  esc(Expr(:block, body...))

end

"""
    @chain(gametype, [kwoptions...,] partial_layer_constructors...)

Macro to comfortably create chains that are consistent with `gametype`.

The layer constructors in the arguments following `gametype` are supposed to
lack the input dimensions, as they are auto-derived from the gametype and the
previous layers. Keyword options to the call to `Chain` in the macro can also be
given.

# Examples
```julia
# The following two calls will create the same networks that are compatible
# with TicTacToe

Chain([ Conv(1, 32, relu), Dense(32, 50) ])
@chain TicTacToe Conv(32, relu) Dense(50)
```
"""
macro chain(ex, layers...)
  composite_macro_body(:(Jtac.Chain), ex, layers...)
end

"""
    @stack(gametype, [kwoptions...,] partial_layer_constructors...)

Stack macro that works analogously to `@chain`.
"""
macro stack(ex, layers...)
  composite_macro_body(:(Jtac.Stack), ex, layers...)
end

"""
    @residual(gametype, [kwoptions...,] partial_layer_constructors...)

Macro to comfortably create residual blocks.
"""
macro residual(ex, layers...)
  composite_macro_body(:(Jtac.Residual), ex, layers...)
end

max_stars_repo_name: roSievers/jtac


text:
module Decimals
import Base: +, -, *, /, div, inv,
             ==, <, <=, >, >=,
             signbit, sign, decompose,
             one, zero,
             eps, parse, print

export Decimal, @d_str, strip_trailing_zeros,
       RoundUnnecessary, RoundFloor, RoundCeiling

struct Decimal <: AbstractFloat
    c::BigInt  # coefficient
    q::Integer # exponent
end

PRECISION, ROUNDING = 9, RoundDown

function setprecision!(; precision::Integer=16, rounding::RoundingMode=RoundDown)
    global PRECISION = precision
    global ROUNDING = rounding
    precision, rounding
end

include("decimal.jl")
include("arithmetic.jl")

function decompose(x::Decimal)
    x = strip_trailing_zeros(x)
    x.q >= 0 ? decompose(x.c * 10^x.q) : decompose(x.c // 10^-x.q)
end

end

ext: jl


text:
# Julia wrapper for header: pg_query.h
# Automatically generated using Clang.jl

function pg_query_normalize(input)
    ccall((:pg_query_normalize, libpg_query), PgQueryNormalizeResult, (Cstring,), input)
end

function pg_query_parse(input)
    ccall((:pg_query_parse, libpg_query), PgQueryParseResult, (Cstring,), input)
end

function pg_query_parse_plpgsql(input)
    ccall((:pg_query_parse_plpgsql, libpg_query), PgQueryPlpgsqlParseResult, (Cstring,), input)
end

function pg_query_fingerprint(input)
    ccall((:pg_query_fingerprint, libpg_query), PgQueryFingerprintResult, (Cstring,), input)
end

function pg_query_free_normalize_result(result)
    ccall((:pg_query_free_normalize_result, libpg_query), Cvoid, (PgQueryNormalizeResult,), result)
end

function pg_query_free_parse_result(result)
    ccall((:pg_query_free_parse_result, libpg_query), Cvoid, (PgQueryParseResult,), result)
end

function pg_query_free_plpgsql_parse_result(result)
    ccall((:pg_query_free_plpgsql_parse_result, libpg_query), Cvoid, (PgQueryPlpgsqlParseResult,), result)
end

function pg_query_free_fingerprint_result(result)
    ccall((:pg_query_free_fingerprint_result, libpg_query), Cvoid, (PgQueryFingerprintResult,), result)
end

function pg_query_init()
    ccall((:pg_query_init, libpg_query), Cvoid, ())
end
# Julia wrapper for header: sdir.h
# Automatically generated using Clang.jl

# Julia wrapper for header: postgres_ext.h
# Automatically generated using Clang.jl

# Julia wrapper for header: pg_query_fingerprint.h
# Automatically generated using Clang.jl

function pg_query_fingerprint_with_opts(input, printTokens)
    ccall((:pg_query_fingerprint_with_opts, libpg_query), PgQueryFingerprintResult, (Cstring, bool), input, printTokens)
end
# Julia wrapper for header: pg_query_internal.h
# Automatically generated using Clang.jl

function pg_query_raw_parse(input)
    ccall((:pg_query_raw_parse, libpg_query), PgQueryInternalParsetreeAndError, (Cstring,), input)
end

function pg_query_free_error(error)
    ccall((:pg_query_free_error, libpg_query), Cvoid, (Ptr{Cint},), error)
end

function pg_query_enter_memory_context(ctx_name)
    ccall((:pg_query_enter_memory_context, libpg_query), MemoryContext, (Cstring,), ctx_name)
end

function pg_query_exit_memory_context(ctx)
    ccall((:pg_query_exit_memory_context, libpg_query), Cvoid, (MemoryContext,), ctx)
end
# Julia wrapper for header: pg_query_json.h
# Automatically generated using Clang.jl

function pg_query_nodes_to_json(obj)
    ccall((:pg_query_nodes_to_json, libpg_query), Cstring, (Ptr{Cvoid},), obj)
end
# Julia wrapper for header: pg_query_json_plpgsql.h
# Automatically generated using Clang.jl

function plpgsqlToJSON(func)
    ccall((:plpgsqlToJSON, libpg_query), Cstring, (Ptr{PLpgSQL_function},), func)
end
# Julia wrapper for header: bitmapset.h
# Automatically generated using Clang.jl

function bms_copy(a)
    ccall((:bms_copy, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset},), a)
end

function bms_equal(a, b)
    ccall((:bms_equal, libpg_query), bool, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_make_singleton(x)
    ccall((:bms_make_singleton, libpg_query), Ptr{Bitmapset}, (Cint,), x)
end

function bms_free(a)
    ccall((:bms_free, libpg_query), Cvoid, (Ptr{Bitmapset},), a)
end

function bms_union(a, b)
    ccall((:bms_union, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_intersect(a, b)
    ccall((:bms_intersect, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_difference(a, b)
    ccall((:bms_difference, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_is_subset(a, b)
    ccall((:bms_is_subset, libpg_query), bool, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_subset_compare(a, b)
    ccall((:bms_subset_compare, libpg_query), BMS_Comparison, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_is_member(x, a)
    ccall((:bms_is_member, libpg_query), bool, (Cint, Ptr{Bitmapset}), x, a)
end

function bms_overlap(a, b)
    ccall((:bms_overlap, libpg_query), bool, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_overlap_list(a, b)
    ccall((:bms_overlap_list, libpg_query), bool, (Ptr{Bitmapset}, Ptr{List}), a, b)
end

function bms_nonempty_difference(a, b)
    ccall((:bms_nonempty_difference, libpg_query), bool, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_singleton_member(a)
    ccall((:bms_singleton_member, libpg_query), Cint, (Ptr{Bitmapset},), a)
end

function bms_get_singleton_member(a, member)
    ccall((:bms_get_singleton_member, libpg_query), bool, (Ptr{Bitmapset}, Ptr{Cint}), a, member)
end

function bms_num_members(a)
    ccall((:bms_num_members, libpg_query), Cint, (Ptr{Bitmapset},), a)
end

function bms_membership(a)
    ccall((:bms_membership, libpg_query), BMS_Membership, (Ptr{Bitmapset},), a)
end

function bms_is_empty(a)
    ccall((:bms_is_empty, libpg_query), bool, (Ptr{Bitmapset},), a)
end

function bms_add_member(a, x)
    ccall((:bms_add_member, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Cint), a, x)
end

function bms_del_member(a, x)
    ccall((:bms_del_member, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Cint), a, x)
end

function bms_add_members(a, b)
    ccall((:bms_add_members, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_int_members(a, b)
    ccall((:bms_int_members, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_del_members(a, b)
    ccall((:bms_del_members, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_join(a, b)
    ccall((:bms_join, libpg_query), Ptr{Bitmapset}, (Ptr{Bitmapset}, Ptr{Bitmapset}), a, b)
end

function bms_first_member(a)
    ccall((:bms_first_member, libpg_query), Cint, (Ptr{Bitmapset},), a)
end

function bms_next_member(a, prevbit)
    ccall((:bms_next_member, libpg_query), Cint, (Ptr{Bitmapset}, Cint), a, prevbit)
end

function bms_hash_value(a)
    ccall((:bms_hash_value, libpg_query), uint32, (Ptr{Bitmapset},), a)
end
# Julia wrapper for header: extensible.h
# Automatically generated using Clang.jl

function RegisterExtensibleNodeMethods(method)
    ccall((:RegisterExtensibleNodeMethods, libpg_query), Cvoid, (Ptr{ExtensibleNodeMethods},), method)
end

function GetExtensibleNodeMethods(name, missing_ok)
    ccall((:GetExtensibleNodeMethods, libpg_query), Ptr{ExtensibleNodeMethods}, (Cstring, bool), name, missing_ok)
end

function RegisterCustomScanMethods(methods)
    ccall((:RegisterCustomScanMethods, libpg_query), Cvoid, (Ptr{CustomScanMethods},), methods)
end

function GetCustomScanMethods(CustomName, missing_ok)
    ccall((:GetCustomScanMethods, libpg_query), Ptr{CustomScanMethods}, (Cstring, bool), CustomName, missing_ok)
end
# Julia wrapper for header: lockoptions.h
# Automatically generated using Clang.jl

# Julia wrapper for header: makefuncs.h
# Automatically generated using Clang.jl

function makeA_Expr(kind, name, lexpr, rexpr, location)
    ccall((:makeA_Expr, libpg_query), Ptr{A_Expr}, (A_Expr_Kind, Ptr{List}, Ptr{Node}, Ptr{Node}, Cint), kind, name, lexpr, rexpr, location)
end

function makeSimpleA_Expr(kind, name, lexpr, rexpr, location)
    ccall((:makeSimpleA_Expr, libpg_query), Ptr{A_Expr}, (A_Expr_Kind, Cstring, Ptr{Node}, Ptr{Node}, Cint), kind, name, lexpr, rexpr, location)
end

function makeVar(varno, varattno, vartype, vartypmod, varcollid, varlevelsup)
    ccall((:makeVar, libpg_query), Ptr{Var}, (Index, AttrNumber, Oid, int32, Oid, Index), varno, varattno, vartype, vartypmod, varcollid, varlevelsup)
end

function makeVarFromTargetEntry(varno, tle)
    ccall((:makeVarFromTargetEntry, libpg_query), Ptr{Var}, (Index, Ptr{TargetEntry}), varno, tle)
end

function makeWholeRowVar(rte, varno, varlevelsup, allowScalar)
    ccall((:makeWholeRowVar, libpg_query), Ptr{Var}, (Ptr{RangeTblEntry}, Index, Index, bool), rte, varno, varlevelsup, allowScalar)
end

function makeTargetEntry(expr, resno, resname, resjunk)
    ccall((:makeTargetEntry, libpg_query), Ptr{TargetEntry}, (Ptr{Expr}, AttrNumber, Cstring, bool), expr, resno, resname, resjunk)
end

function flatCopyTargetEntry(src_tle)
    ccall((:flatCopyTargetEntry, libpg_query), Ptr{TargetEntry}, (Ptr{TargetEntry},), src_tle)
end

function makeFromExpr(fromlist, quals)
    ccall((:makeFromExpr, libpg_query), Ptr{FromExpr}, (Ptr{List}, Ptr{Node}), fromlist, quals)
end

function makeConst(consttype, consttypmod, constcollid, constlen, constvalue, constisnull, constbyval)
    ccall((:makeConst, libpg_query), Ptr{Const}, (Oid, int32, Oid, Cint, Cint, bool, bool), consttype, consttypmod, constcollid, constlen, constvalue, constisnull, constbyval)
end

function makeNullConst(consttype, consttypmod, constcollid)
    ccall((:makeNullConst, libpg_query), Ptr{Const}, (Oid, int32, Oid), consttype, consttypmod, constcollid)
end

function makeBoolConst(value, isnull)
    ccall((:makeBoolConst, libpg_query), Ptr{Node}, (bool, bool), value, isnull)
end

function makeBoolExpr(boolop, args, location)
    ccall((:makeBoolExpr, libpg_query), Ptr{Expr}, (BoolExprType, Ptr{List}, Cint), boolop, args, location)
end

function makeAlias(aliasname, colnames)
    ccall((:makeAlias, libpg_query), Ptr{Alias}, (Cstring, Ptr{List}), aliasname, colnames)
end

function makeRelabelType(arg, rtype, rtypmod, rcollid, rformat)
    ccall((:makeRelabelType, libpg_query), Ptr{RelabelType}, (Ptr{Expr}, Oid, int32, Oid, CoercionForm), arg, rtype, rtypmod, rcollid, rformat)
end

function makeRangeVar(schemaname, relname, location)
    ccall((:makeRangeVar, libpg_query), Ptr{RangeVar}, (Cstring, Cstring, Cint), schemaname, relname, location)
end

function makeTypeName(typnam)
    ccall((:makeTypeName, libpg_query), Ptr{TypeName}, (Cstring,), typnam)
end

function makeTypeNameFromNameList(names)
    ccall((:makeTypeNameFromNameList, libpg_query), Ptr{TypeName}, (Ptr{List},), names)
end

function makeTypeNameFromOid(typeOid, typmod)
    ccall((:makeTypeNameFromOid, libpg_query), Ptr{TypeName}, (Oid, int32), typeOid, typmod)
end

function makeColumnDef(colname, typeOid, typmod, collOid)
    ccall((:makeColumnDef, libpg_query), Ptr{ColumnDef}, (Cstring, Oid, int32, Oid), colname, typeOid, typmod, collOid)
end

function makeFuncExpr(funcid, rettype, args, funccollid, inputcollid, fformat)
    ccall((:makeFuncExpr, libpg_query), Ptr{FuncExpr}, (Oid, Oid, Ptr{List}, Oid, Oid, CoercionForm), funcid, rettype, args, funccollid, inputcollid, fformat)
end

function makeFuncCall(name, args, location)
    ccall((:makeFuncCall, libpg_query), Ptr{FuncCall}, (Ptr{List}, Ptr{List}, Cint), name, args, location)
end

function makeDefElem(name, arg, location)
    ccall((:makeDefElem, libpg_query), Ptr{DefElem}, (Cstring, Ptr{Node}, Cint), name, arg, location)
end

function makeDefElemExtended(nameSpace, name, arg, defaction, location)
    ccall((:makeDefElemExtended, libpg_query), Ptr{DefElem}, (Cstring, Cstring, Ptr{Node}, DefElemAction, Cint), nameSpace, name, arg, defaction, location)
end

function makeGroupingSet(kind, content, location)
    ccall((:makeGroupingSet, libpg_query), Ptr{GroupingSet}, (GroupingSetKind, Ptr{List}, Cint), kind, content, location)
end
# Julia wrapper for header: memnodes.h
# Automatically generated using Clang.jl

# Julia wrapper for header: nodeFuncs.h
# Automatically generated using Clang.jl

function exprType(expr)
    ccall((:exprType, libpg_query), Oid, (Ptr{Node},), expr)
end

function exprTypmod(expr)
    ccall((:exprTypmod, libpg_query), int32, (Ptr{Node},), expr)
end

function exprIsLengthCoercion(expr, coercedTypmod)
    ccall((:exprIsLengthCoercion, libpg_query), bool, (Ptr{Node}, Ptr{int32}), expr, coercedTypmod)
end

function relabel_to_typmod(expr, typmod)
    ccall((:relabel_to_typmod, libpg_query), Ptr{Node}, (Ptr{Node}, int32), expr, typmod)
end

function strip_implicit_coercions(node)
    ccall((:strip_implicit_coercions, libpg_query), Ptr{Node}, (Ptr{Node},), node)
end

function expression_returns_set(clause)
    ccall((:expression_returns_set, libpg_query), bool, (Ptr{Node},), clause)
end

function exprCollation(expr)
    ccall((:exprCollation, libpg_query), Oid, (Ptr{Node},), expr)
end

function exprInputCollation(expr)
    ccall((:exprInputCollation, libpg_query), Oid, (Ptr{Node},), expr)
end

function exprSetCollation(expr, collation)
    ccall((:exprSetCollation, libpg_query), Cvoid, (Ptr{Node}, Oid), expr, collation)
end

function exprSetInputCollation(expr, inputcollation)
    ccall((:exprSetInputCollation, libpg_query), Cvoid, (Ptr{Node}, Oid), expr, inputcollation)
end

function exprLocation(expr)
    ccall((:exprLocation, libpg_query), Cint, (Ptr{Node},), expr)
end

function fix_opfuncids(node)
    ccall((:fix_opfuncids, libpg_query), Cvoid, (Ptr{Node},), node)
end

function set_opfuncid(opexpr)
    ccall((:set_opfuncid, libpg_query), Cvoid, (Ptr{OpExpr},), opexpr)
end

function set_sa_opfuncid(opexpr)
    ccall((:set_sa_opfuncid, libpg_query), Cvoid, (Ptr{ScalarArrayOpExpr},), opexpr)
end

function check_functions_in_node(node, checker, context)
    ccall((:check_functions_in_node, libpg_query), bool, (Ptr{Node}, check_function_callback, Ptr{Cvoid}), node, checker, context)
end

function expression_tree_walker(node, walker, context)
    ccall((:expression_tree_walker, libpg_query), bool, (Ptr{Node}, Ptr{Cvoid}, Ptr{Cvoid}), node, walker, context)
end

function expression_tree_mutator(node, mutator, context)
    ccall((:expression_tree_mutator, libpg_query), Ptr{Node}, (Ptr{Node}, Ptr{Cvoid}, Ptr{Cvoid}), node, mutator, context)
end

function query_tree_walker(query, walker, context, flags)
    ccall((:query_tree_walker, libpg_query), bool, (Ptr{Query}, Ptr{Cvoid}, Ptr{Cvoid}, Cint), query, walker, context, flags)
end

function query_tree_mutator(query, mutator, context, flags)
    ccall((:query_tree_mutator, libpg_query), Ptr{Query}, (Ptr{Query}, Ptr{Cvoid}, Ptr{Cvoid}, Cint), query, mutator, context, flags)
end

function range_table_walker(rtable, walker, context, flags)
    ccall((:range_table_walker, libpg_query), bool, (Ptr{List}, Ptr{Cvoid}, Ptr{Cvoid}, Cint), rtable, walker, context, flags)
end

function range_table_mutator(rtable, mutator, context, flags)
    ccall((:range_table_mutator, libpg_query), Ptr{List}, (Ptr{List}, Ptr{Cvoid}, Ptr{Cvoid}, Cint), rtable, mutator, context, flags)
end

function query_or_expression_tree_walker(node, walker, context, flags)
    ccall((:query_or_expression_tree_walker, libpg_query), bool, (Ptr{Node}, Ptr{Cvoid}, Ptr{Cvoid}, Cint), node, walker, context, flags)
end

function query_or_expression_tree_mutator(node, mutator, context, flags)
    ccall((:query_or_expression_tree_mutator, libpg_query), Ptr{Node}, (Ptr{Node}, Ptr{Cvoid}, Ptr{Cvoid}, Cint), node, mutator, context, flags)
end

function raw_expression_tree_walker(node, walker, context)
    ccall((:raw_expression_tree_walker, libpg_query), bool, (Ptr{Node}, Ptr{Cvoid}, Ptr{Cvoid}), node, walker, context)
end

function planstate_tree_walker(planstate, walker, context)
    ccall((:planstate_tree_walker, libpg_query), bool, (Ptr{PlanState}, Ptr{Cvoid}, Ptr{Cvoid}), planstate, walker, context)
end
# Julia wrapper for header: nodes.h
# Automatically generated using Clang.jl

function outNode(str, obj)
    ccall((:outNode, libpg_query), Cvoid, (Ptr{StringInfoData}, Ptr{Cvoid}), str, obj)
end

function outToken(str, s)
    ccall((:outToken, libpg_query), Cvoid, (Ptr{StringInfoData}, Cstring), str, s)
end

function outBitmapset(str, bms)
    ccall((:outBitmapset, libpg_query), Cvoid, (Ptr{StringInfoData}, Ptr{Bitmapset}), str, bms)
end

function outDatum(str, value, typlen, typbyval)
    ccall((:outDatum, libpg_query), Cvoid, (Ptr{StringInfoData}, Csize_t, Cint, bool), str, value, typlen, typbyval)
end

function nodeToString(obj)
    ccall((:nodeToString, libpg_query), Cstring, (Ptr{Cvoid},), obj)
end

function bmsToString(bms)
    ccall((:bmsToString, libpg_query), Cstring, (Ptr{Bitmapset},), bms)
end

function stringToNode(str)
    ccall((:stringToNode, libpg_query), Ptr{Cvoid}, (Cstring,), str)
end

function readBitmapset()
    ccall((:readBitmapset, libpg_query), Ptr{Bitmapset}, ())
end

function readDatum(typbyval)
    ccall((:readDatum, libpg_query), Csize_t, (bool,), typbyval)
end

function readBoolCols(numCols)
    ccall((:readBoolCols, libpg_query), Ptr{bool}, (Cint,), numCols)
end

function readIntCols(numCols)
    ccall((:readIntCols, libpg_query), Ptr{Cint}, (Cint,), numCols)
end

function readOidCols(numCols)
    ccall((:readOidCols, libpg_query), Ptr{Oid}, (Cint,), numCols)
end

function readAttrNumberCols(numCols)
    ccall((:readAttrNumberCols, libpg_query), Ptr{int16}, (Cint,), numCols)
end

function copyObjectImpl(obj)
    ccall((:copyObjectImpl, libpg_query), Ptr{Cvoid}, (Ptr{Cvoid},), obj)
end

function equal(a, b)
    ccall((:equal, libpg_query), bool, (Ptr{Cvoid}, Ptr{Cvoid}), a, b)
end
# Julia wrapper for header: params.h
# Automatically generated using Clang.jl

function copyParamList(from)
    ccall((:copyParamList, libpg_query), ParamListInfo, (ParamListInfo,), from)
end

function EstimateParamListSpace(paramLI)
    ccall((:EstimateParamListSpace, libpg_query), Size, (ParamListInfo,), paramLI)
end

function SerializeParamList(paramLI, start_address)
    ccall((:SerializeParamList, libpg_query), Cvoid, (ParamListInfo, Ptr{Cstring}), paramLI, start_address)
end

function RestoreParamList(start_address)
    ccall((:RestoreParamList, libpg_query), ParamListInfo, (Ptr{Cstring},), start_address)
end
# Julia wrapper for header: parsenodes.h
# Automatically generated using Clang.jl

# Julia wrapper for header: pg_list.h
# Automatically generated using Clang.jl

function list_head(l)
    ccall((:list_head, libpg_query), Ptr{ListCell}, (Ptr{List},), l)
end

function list_tail(l)
    ccall((:list_tail, libpg_query), Ptr{ListCell}, (Ptr{List},), l)
end

function list_length(l)
    ccall((:list_length, libpg_query), Cint, (Ptr{List},), l)
end

function lappend(list, datum)
    ccall((:lappend, libpg_query), Ptr{List}, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function lappend_int(list, datum)
    ccall((:lappend_int, libpg_query), Ptr{List}, (Ptr{List}, Cint), list, datum)
end

function lappend_oid(list, datum)
    ccall((:lappend_oid, libpg_query), Ptr{List}, (Ptr{List}, Oid), list, datum)
end

function lappend_cell(list, prev, datum)
    ccall((:lappend_cell, libpg_query), Ptr{ListCell}, (Ptr{List}, Ptr{ListCell}, Ptr{Cvoid}), list, prev, datum)
end

function lappend_cell_int(list, prev, datum)
    ccall((:lappend_cell_int, libpg_query), Ptr{ListCell}, (Ptr{List}, Ptr{ListCell}, Cint), list, prev, datum)
end

function lappend_cell_oid(list, prev, datum)
    ccall((:lappend_cell_oid, libpg_query), Ptr{ListCell}, (Ptr{List}, Ptr{ListCell}, Oid), list, prev, datum)
end

function lcons(datum, list)
    ccall((:lcons, libpg_query), Ptr{List}, (Ptr{Cvoid}, Ptr{List}), datum, list)
end

function lcons_int(datum, list)
    ccall((:lcons_int, libpg_query), Ptr{List}, (Cint, Ptr{List}), datum, list)
end

function lcons_oid(datum, list)
    ccall((:lcons_oid, libpg_query), Ptr{List}, (Oid, Ptr{List}), datum, list)
end

function list_concat(list1, list2)
    ccall((:list_concat, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_truncate(list, new_size)
    ccall((:list_truncate, libpg_query), Ptr{List}, (Ptr{List}, Cint), list, new_size)
end

function list_nth_cell(list, n)
    ccall((:list_nth_cell, libpg_query), Ptr{ListCell}, (Ptr{List}, Cint), list, n)
end

function list_nth(list, n)
    ccall((:list_nth, libpg_query), Ptr{Cvoid}, (Ptr{List}, Cint), list, n)
end

function list_nth_int(list, n)
    ccall((:list_nth_int, libpg_query), Cint, (Ptr{List}, Cint), list, n)
end

function list_nth_oid(list, n)
    ccall((:list_nth_oid, libpg_query), Oid, (Ptr{List}, Cint), list, n)
end

function list_member(list, datum)
    ccall((:list_member, libpg_query), bool, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function list_member_ptr(list, datum)
    ccall((:list_member_ptr, libpg_query), bool, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function list_member_int(list, datum)
    ccall((:list_member_int, libpg_query), bool, (Ptr{List}, Cint), list, datum)
end

function list_member_oid(list, datum)
    ccall((:list_member_oid, libpg_query), bool, (Ptr{List}, Oid), list, datum)
end

function list_delete(list, datum)
    ccall((:list_delete, libpg_query), Ptr{List}, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function list_delete_ptr(list, datum)
    ccall((:list_delete_ptr, libpg_query), Ptr{List}, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function list_delete_int(list, datum)
    ccall((:list_delete_int, libpg_query), Ptr{List}, (Ptr{List}, Cint), list, datum)
end

function list_delete_oid(list, datum)
    ccall((:list_delete_oid, libpg_query), Ptr{List}, (Ptr{List}, Oid), list, datum)
end

function list_delete_first(list)
    ccall((:list_delete_first, libpg_query), Ptr{List}, (Ptr{List},), list)
end

function list_delete_cell(list, cell, prev)
    ccall((:list_delete_cell, libpg_query), Ptr{List}, (Ptr{List}, Ptr{ListCell}, Ptr{ListCell}), list, cell, prev)
end

function list_union(list1, list2)
    ccall((:list_union, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_union_ptr(list1, list2)
    ccall((:list_union_ptr, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_union_int(list1, list2)
    ccall((:list_union_int, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_union_oid(list1, list2)
    ccall((:list_union_oid, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_intersection(list1, list2)
    ccall((:list_intersection, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_intersection_int(list1, list2)
    ccall((:list_intersection_int, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_difference(list1, list2)
    ccall((:list_difference, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_difference_ptr(list1, list2)
    ccall((:list_difference_ptr, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_difference_int(list1, list2)
    ccall((:list_difference_int, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_difference_oid(list1, list2)
    ccall((:list_difference_oid, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_append_unique(list, datum)
    ccall((:list_append_unique, libpg_query), Ptr{List}, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function list_append_unique_ptr(list, datum)
    ccall((:list_append_unique_ptr, libpg_query), Ptr{List}, (Ptr{List}, Ptr{Cvoid}), list, datum)
end

function list_append_unique_int(list, datum)
    ccall((:list_append_unique_int, libpg_query), Ptr{List}, (Ptr{List}, Cint), list, datum)
end

function list_append_unique_oid(list, datum)
    ccall((:list_append_unique_oid, libpg_query), Ptr{List}, (Ptr{List}, Oid), list, datum)
end

function list_concat_unique(list1, list2)
    ccall((:list_concat_unique, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_concat_unique_ptr(list1, list2)
    ccall((:list_concat_unique_ptr, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_concat_unique_int(list1, list2)
    ccall((:list_concat_unique_int, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_concat_unique_oid(list1, list2)
    ccall((:list_concat_unique_oid, libpg_query), Ptr{List}, (Ptr{List}, Ptr{List}), list1, list2)
end

function list_free(list)
    ccall((:list_free, libpg_query), Cvoid, (Ptr{List},), list)
end

function list_free_deep(list)
    ccall((:list_free_deep, libpg_query), Cvoid, (Ptr{List},), list)
end

function list_copy(list)
    ccall((:list_copy, libpg_query), Ptr{List}, (Ptr{List},), list)
end

function list_copy_tail(list, nskip)
    ccall((:list_copy_tail, libpg_query), Ptr{List}, (Ptr{List}, Cint), list, nskip)
end
# Julia wrapper for header: plannodes.h
# Automatically generated using Clang.jl

# Julia wrapper for header: primnodes.h
# Automatically generated using Clang.jl

# Julia wrapper for header: print.h
# Automatically generated using Clang.jl

function print(obj)
    ccall((:print, libpg_query), Cvoid, (Ptr{Cvoid},), obj)
end

function pprint(obj)
    ccall((:pprint, libpg_query), Cvoid, (Ptr{Cvoid},), obj)
end

function elog_node_display(lev, title, obj, pretty)
    ccall((:elog_node_display, libpg_query), Cvoid, (Cint, Cstring, Ptr{Cvoid}, bool), lev, title, obj, pretty)
end

function format_node_dump(dump)
    ccall((:format_node_dump, libpg_query), Cstring, (Cstring,), dump)
end

function pretty_format_node_dump(dump)
    ccall((:pretty_format_node_dump, libpg_query), Cstring, (Cstring,), dump)
end

function print_rt(rtable)
    ccall((:print_rt, libpg_query), Cvoid, (Ptr{List},), rtable)
end

function print_expr(expr, rtable)
    ccall((:print_expr, libpg_query), Cvoid, (Ptr{Node}, Ptr{List}), expr, rtable)
end

function print_pathkeys(pathkeys, rtable)
    ccall((:print_pathkeys, libpg_query), Cvoid, (Ptr{List}, Ptr{List}), pathkeys, rtable)
end

function print_tl(tlist, rtable)
    ccall((:print_tl, libpg_query), Cvoid, (Ptr{List}, Ptr{List}), tlist, rtable)
end

function print_slot(slot)
    ccall((:print_slot, libpg_query), Cvoid, (Ptr{TupleTableSlot},), slot)
end
# Julia wrapper for header: relation.h
# Automatically generated using Clang.jl

function is_dummy_rel(rel)
    ccall((:is_dummy_rel, libpg_query), bool, (Ptr{RelOptInfo},), rel)
end
# Julia wrapper for header: tidbitmap.h
# Automatically generated using Clang.jl

function tbm_create(maxbytes, dsa)
    ccall((:tbm_create, libpg_query), Ptr{TIDBitmap}, (Clong, Ptr{dsa_area}), maxbytes, dsa)
end

function tbm_free(tbm)
    ccall((:tbm_free, libpg_query), Cvoid, (Ptr{TIDBitmap},), tbm)
end

function tbm_free_shared_area(dsa, dp)
    ccall((:tbm_free_shared_area, libpg_query), Cvoid, (Ptr{dsa_area}, dsa_pointer), dsa, dp)
end

function tbm_add_tuples(tbm, tids, ntids, recheck)
    ccall((:tbm_add_tuples, libpg_query), Cvoid, (Ptr{TIDBitmap}, ItemPointer, Cint, bool), tbm, tids, ntids, recheck)
end

function tbm_add_page(tbm, pageno)
    ccall((:tbm_add_page, libpg_query), Cvoid, (Ptr{TIDBitmap}, BlockNumber), tbm, pageno)
end

function tbm_union(a, b)
    ccall((:tbm_union, libpg_query), Cvoid, (Ptr{TIDBitmap}, Ptr{TIDBitmap}), a, b)
end

function tbm_intersect(a, b)
    ccall((:tbm_intersect, libpg_query), Cvoid, (Ptr{TIDBitmap}, Ptr{TIDBitmap}), a, b)
end

function tbm_is_empty(tbm)
    ccall((:tbm_is_empty, libpg_query), bool, (Ptr{TIDBitmap},), tbm)
end

function tbm_begin_iterate(tbm)
    ccall((:tbm_begin_iterate, libpg_query), Ptr{TBMIterator}, (Ptr{TIDBitmap},), tbm)
end

function tbm_prepare_shared_iterate(tbm)
    ccall((:tbm_prepare_shared_iterate, libpg_query), dsa_pointer, (Ptr{TIDBitmap},), tbm)
end

function tbm_iterate(iterator)
    ccall((:tbm_iterate, libpg_query), Ptr{TBMIterateResult}, (Ptr{TBMIterator},), iterator)
end

function tbm_shared_iterate(iterator)
    ccall((:tbm_shared_iterate, libpg_query), Ptr{TBMIterateResult}, (Ptr{TBMSharedIterator},), iterator)
end

function tbm_end_iterate(iterator)
    ccall((:tbm_end_iterate, libpg_query), Cvoid, (Ptr{TBMIterator},), iterator)
end

function tbm_end_shared_iterate(iterator)
    ccall((:tbm_end_shared_iterate, libpg_query), Cvoid, (Ptr{TBMSharedIterator},), iterator)
end

function tbm_attach_shared_iterate(dsa, dp)
    ccall((:tbm_attach_shared_iterate, libpg_query), Ptr{TBMSharedIterator}, (Ptr{dsa_area}, dsa_pointer), dsa, dp)
end
# Julia wrapper for header: value.h
# Automatically generated using Clang.jl

function makeInteger(i)
    ccall((:makeInteger, libpg_query), Ptr{Value}, (Clong,), i)
end

function makeFloat(numericStr)
    ccall((:makeFloat, libpg_query), Ptr{Value}, (Cstring,), numericStr)
end

function makeString(str)
    ccall((:makeString, libpg_query), Ptr{Value}, (Cstring,), str)
end

function makeBitString(str)
    ccall((:makeBitString, libpg_query), Ptr{Value}, (Cstring,), str)
end


text:
"""
    MultiContinuousSpace(low::Number, high::Number, size::Tuple{Vararg{Int}})
    MultiContinuousSpace(low::Array{<:Number}, high::Array{<:Number})

# Examples
```julia-repl
MultiContinuousSpace(-1, 1, (2,3))
MultiContinuousSpace([0, 0, 0], [1, 2, 3])
```
"""
struct MultiContinuousSpace{T <: Number,N} <: AbstractContinuousSpace
    low::Array{T,N}
    high::Array{T,N}
    MultiContinuousSpace(low::Number, high::Number, size::Tuple{Vararg{Int}}) = MultiContinuousSpace(fill(low, size), fill(high, size))
    function MultiContinuousSpace(low::Array{T, N}, high::Array{T, N}) where {T, N}
        size(low) != size(high) && throw(DimensionMismatch("size of low and high must match!"))
        new{T, N}(low, high)
    end
end

eltype(s::MultiContinuousSpace{T, N}) where {T, N} = Array{T, N}  # TODO: StaticArray
sample(s::MultiContinuousSpace) = map((l, h) -> l + rand() * (h - l), s.low, s.high)
in(xs::AbstractArray{T, N} where T, s::MultiContinuousSpace{T, N} where T) where N = all(map((a, b, c) -> a ≤ b ≤ c, s.low, xs, s.high))


text:
using Gadfly, RDatasets

plot(dataset("mlmRev", "Chem97"),
     x=:GCSEScore,
     ygroup=:Gender,
     xgroup=:Score,
     y=:Age,
     Geom.subplot_grid(Geom.point, free_y_axis=true),
     Theme(default_point_size=0.1mm, highlight_width=0.0mm))


text:
"""`newton1d` performs the interval Newton method on the given function `f`
with its derivative `f′` and initial interval `x`.
Optional keyword arguments give the tolerances `reltol` and `abstol`.
`reltol` is the tolerance on the relative error whereas `abstol` is the tolerance on |f(X)|,
and a `debug` boolean argument that prints out diagnostic information."""

function newton1d{T}(f::Function, f′::Function, x::Interval{T};
                    reltol=eps(T), abstol=eps(T), debug=false)

    L = Interval{T}[]

    R = Root{Interval{T}}[]

    push!(L, x)

    while !isempty(L)
        X = pop!(L)
        m = mid(X)
        if (isempty(X))
            continue
        end

        if 0 ∉ f′(X)
            while true
                m = mid(X)
                N = m - (f(Interval(m)) / f′(X))
                X = X ∩ N

                if isempty(X)
                    break

                elseif 0 ∈ f(Interval(prevfloat(m), nextfloat(m)))
                    push!(R, Root(X, :unique))
                    break
                end
            end

        else
            # 0 ∈ f'(X)
            expansion_pt = Inf
            # expansion point for the newton step might be m, X.lo or X.hi according to some conditions

            if 0 ∈ f(Interval(mid(X)))
                # 0 ∈ fⁱ(x)
                # Step 7

                if 0 ∉ f(Interval(X.lo))
                    expansion_pt = X.lo

                elseif 0 ∉ f(Interval(X.hi))
                    expansion_pt = X.hi

                else
                    x1 = mid(Interval(X.lo, mid(X)))
                    x2 = mid(Interval(mid(X), X.hi))
                    if 0 ∉ f(Interval(x1)) || 0 ∉ f(Interval(x2))
                        push!(L, Interval(X.lo, m))
                        push!(L, Interval(m, X.hi))
                        continue

                    else
                        push!(R, Root(X, :unique))
                        continue
                    end
                end

            else
                # 0 ∉ fⁱ(x)

                if (diam(X)/mag(X)) < reltol && diam(f(X)) < abstol
                    push!(R, Root(X, :unknown))
                    continue
                end
            end
            # Step 8

            if isinf(expansion_pt)
                expansion_pt = mid(X)
            end

            initial_width = diam(X)

            a = f(Interval(expansion_pt))
            b = f′(X)

            if 0 < b.hi && 0 > b.lo && 0 ∉ a
                if a.hi < 0
                    push!(L, X ∩ (expansion_pt - Interval(-Inf, a.hi / b.hi)))
                    push!(L, X ∩ (expansion_pt - Interval(a.hi / b.lo, Inf)))

                elseif a.lo > 0
                    push!(L, X ∩ (expansion_pt - Interval(-Inf, a.lo / b.lo)))
                    push!(L, X ∩ (expansion_pt - Interval(a.lo / b.hi, Inf)))

                end

                continue

            else
                N = expansion_pt - (f(Interval(expansion_pt))/f′(X))
                X = X ∩ N
                m = mid(X)

                if isempty(X)
                    continue
                end
            end

            if diam(X) > initial_width/2
                push!(L, Interval(m, X.hi))
                X = Interval(X.lo, m)
            end

            push!(L, X)
        end
    end

    return R
end

"""`newton1d` performs the interval Newton method on the given function `f` and initial interval `x`.
Optional keyword arguments give the tolerances `reltol` and `abstol`.
`reltol` is the tolerance on the relative error whereas `abstol` is the tolerance on |f(X)|,
and a `debug` boolean argument that prints out diagnostic information."""

newton1d{T}(f::Function, x::Interval{T};  args...) =
    newton1d(f, x->D(f,x), x; args...)


text:
################################################# FILE DESCRIPTION #########################################################

# Graft allows users to refer to vertices externally, through arbitrary Julia types. The LabelMap is responsible
# for the resolution of these arbitrary objects into the internally used Integer indices.

# The label map is the datastructure that is used to realize two separate labelling schemes:
# 1. By default, vertices don't have labels, and are referred to by their internally used integer indices.
#    The IdentityLM type is used in this case. This labelling scheme is similar to the one used in LightGraphs.jl
#    and is confusing to use when vertices are removed etc. Sometimes its very inconvenient to think of vertices
#    as numbers! However this scheme incurs no performance overhead in label resolution.
#
# 2. Once the user assigns labels to all vertices, the DictLM datastructure is used to accomplish forward and
#    reverse translations. While both translations are done in constant time, a user defined vertex labelling
#    scheme can incur significant overheads in label translations, especially in large graphs.
#
# Since the type of the map can change depending on the nature of the operation, the modified label map is returned.
# Most label operations should therefore be called as:
# g.lmap = mutate!(g.lmap)

################################################# IMPORT/EXPORT #######################################################

export
# Types
setlabel!, relabel!, haslabel, decode, encode

"""
A type that forward maps labels into internally used vertex identifiers,
and reverse maps vertex identifiers into labels.
"""
abstract LabelMap{T}

################################################# CONSTRUCTORS ########################################################

LabelMap(nv::Int) = IdentityLM(nv)

LabelMap{T}(ls::Vector{T}) = DictLM(ls)

################################################# IDENTITYLM ##########################################################

"""
The default label map, that indicates the absence of meaningful vertex labels.
The usage of this type incurs zero overhead in label resolution.

Since vertices are referred to by their internally used indices, the usage
of this labelling scheme can be problematic when vertices are deleted.
"""
type IdentityLM <: LabelMap{Int}
   nv::Int
end

nv(x::IdentityLM) = x.nv

################################################# DICTLM ##############################################################

"""
This label map is used when vertices are assigned meaningful labels. This type uses
a dictionary to map labels onto vertex identifies, and a vector to map vertex
identifiers onto labels.

Labels can be of any user defined type.
"""
type DictLM{T} <: LabelMap{T}
   nv::Int
   fmap::Dict{T,VertexID}
   rmap::Vector{T}
end

""" Construct a label map from a list of labels """
function DictLM{T}(labels::AbstractVector{T})
   nv = length(labels)
   fmap = Dict(l => i for (i,l) in enumerate(labels))
   return DictLM{T}(nv, fmap, copy(labels))
end

"""
Construct a label map from the internally used vertex identifiers.
"""
DictLM(x::IdentityLM) = DictLM([i for i in 1 : nv(x)])

# Accessors
nv(x::DictLM) = x.nv
fmap(x::DictLM) = x.fmap
rmap(x::DictLM) = x.rmap

################################################# MSC ################################################################

###
# ELTYPE
###
Base.eltype(x::IdentityLM) = Int
Base.eltype{T}(x::DictLM{T}) = T

###
# ==
###
(==)(x::LabelMap, y::LabelMap) = encode(x) == encode(y)

###
# COPY
###
Base.copy(x::IdentityLM) = IdentityLM(nv(x))
Base.copy(x::DictLM) = DictLM(nv(x), copy(fmap(x)), copy(rmap(x)))

###
# DEEPCOPY
###
Base.deepcopy(x::IdentityLM) = IdentityLM(nv(x))
Base.deepcopy(x::DictLM) = DictLM(nv(x), deepcopy(fmap(x)), deepcopy(rmap(x)))

################################################# SETLABEL ############################################################

""" Remove vertex labels """
setlabel!(x::LabelMap) = IdentityLM(x.nv)

""" Set new labels for all vertices """
setlabel!(x::IdentityLM, ls::AbstractVector) = DictLM(ls)
setlabel!(x::DictLM, ls::AbstractVector) = DictLM(ls)

################################################# RELABEL SINGLE ######################################################

""" Change the label of a single vertex """
relabel!(x::IdentityLM, v::VertexID, l) = relabel!(DictLM(x), v, l)

function relabel!{T}(x::DictLM{T}, v::VertexID, l)
   l = convert(T, l)
   fmap(x)[l] = v
   rmap(x)[v] = l
   return x
end

################################################# RELABEL MUTLI #######################################################

""" Change labels for a list of vertices """
relabel!(x::IdentityLM, vs::VertexList, ls::AbstractVector) = relabel!(DictLM(x), vs, ls)

function relabel!{T}(x::DictLM{T}, vs::VertexList, ls::AbstractVector)
   ls = collect(T, ls)
   D = fmap(x)
   for i in eachindex(vs, ls)
      D[ls[i]] = vs[i]
   end
   rmap(x)[vs] = ls
   return x
end

################################################# HASLABEL ############################################################

""" Check if the input vertex label is valid """
haslabel(x::IdentityLM, v::VertexID) = 1 <= v <= nv(x)
haslabel(x::IdentityLM, l) = false

haslabel(x::DictLM, l) = haskey(fmap(x), l)

################################################# DECODE VERTEX #######################################################
""" Translate a vertex label into the internally used vertex identifier """
decode(x::IdentityLM, v::VertexID) = 1 <= v <= nv(x) ? v : error("Couldn't decode vertex label $v")

decode(x::IdentityLM, l) = error("Couldn't decode vertex label $l")

function decode(x::DictLM, l)
   get(fmap(x), l) do
      error("Couldn't decode vertex label $l")
   end
end

################################################# DECODE VERTICES ##########################################################

""" Translate a list of labels into the internally used vertex identifiers """
decode(x::IdentityLM, vs::VertexList) = vs
decode(x::DictLM, ls::AbstractVector) = [decode(x, l) for l in ls]

################################################# DECODE EDGE ##############################################################

""" Decode both vertices in a labelled edge """
decode(x::IdentityLM, e::EdgeID) = e
decode(x::DictLM, el::Pair) = EdgeID(decode(x, el.first), decode(x, el.second))

################################################# ENCODE VERTEX ############################################################

""" Map the input vertex identifier into the externally used label """
encode(x::IdentityLM, v::VertexID) = v
encode(x::DictLM, v::VertexID) = getindex(rmap(x), v)

################################################# ENCODE VERTICES ##########################################################

""" Map the input vertex identifier into its externally used label """
encode(x::IdentityLM, vs::VertexList) = collect(vs)
encode(x::DictLM, vs::VertexList) = getindex(rmap(x), vs)

################################################# FETCH ALL LABELS #########################################################

""" Map the input list of vertex identifiers into their externally used labels """
encode(x::IdentityLM) = collect(1 : x.nv)
encode(x::DictLM) = copy(rmap(x))

################################################# ENCODE EDGE ##############################################################

""" Encode both vertices in an edge identifier """
encode(x::IdentityLM, e::EdgeID) = e
encode{T}(x::DictLM{T}, e::EdgeID) = Pair{T,T}(encode(x, e.first), encode(x, e.second))

################################################# ENCODE EDGES #############################################################

""" Encode all edges in an input edge list """
encode(x::IdentityLM, es::EdgeList) = es

encode(x::DictLM, es::EdgeList) = [encode(x, e) for e in es]

################################################# ADDVERTEX ################################################################

"""
Add an unlabelled vertex to the graph. This method throws
an error, when used on a labelled graph.
"""
function addvertex!(x::IdentityLM)
   x.nv += 1
   return x
end

addvertex!(x::DictLM) = error("Please supply a label")

"""
Add a labelled vertex to the graph. If used on an
unlabelled graph, this method will assign the internally
used vertex identifiers as labels to existing vertices.
"""
function addvertex!(x::IdentityLM, l)
   if l == nv(x) + 1
      addvertex!(x)
   else
      addvertex!(DictLM(x), l)
   end
end

function addvertex!{T}(x::DictLM{T}, l)
   l = convert(T, l)
   x.nv += 1
   push!(rmap(x), l)
   fmap(x)[l] = nv(x)
   return x
end

################################################# RMVERTEX ###################################################################

""" Remove a list of vertices from the graph. """
function rmvertex!(x::IdentityLM, vs)
   x.nv -= length(vs)
   return x
end

function rmvertex!(x::DictLM, vs)
   F = fmap(x)
   R = rmap(x)

   ls = encode(x, vs)

   # Remove labels from Forward map
   for l in ls
      delete!(F, l)
   end

   # Remove labels from Reverse map
   deleteat!(R, vs)

   # Redirect labels in Forward map to new indexes
   for v in minimum(vs) : length(R)
      F[R[v]] = v
   end

   # Decrement Label Map size
   x.nv -= length(vs)

   return x
end

################################################# SUBGRAPH ####################################################################

""" Retrieve a subset of vertex labels """
subgraph(x::IdentityLM, vlist::VertexList) = IdentityLM(length(vlist))

function subgraph(x::DictLM, vlist::VertexList)
   DictLM(rmap(x)[vlist])
end


text:
abstract type CalibrationErrorEstimator end

"""
    (estimator::CalibrationErrorEstimator)(predictions, targets)

Estimate the calibration error of a model from the set of `predictions`
and corresponding `targets` using the `estimator`.
"""
(::CalibrationErrorEstimator)(predictions, targets)

function check_nsamples(predictions, targets, min::Int=1)
    n = length(predictions)
    length(targets) == n ||
        throw(DimensionMismatch("number of predictions and targets must be equal"))
    n ≥ min || error("there must be at least ", min, min == 1 ? " sample" : " samples")
    return n
end


text:
<extend src="layout.jl">
    <block name="content">
        <form action="/submit" method="post">
            title
            <input id="title" name="title" type="text" size="50" required>

            url
            <input id="url" name="link" type="text" size="50">

            or

            text
            <textarea id="text" name="text" rows="4" cols="49"></textarea>

            <input style="margin-left: 3em" value="submit" type="submit">
        </form>

    </block>
</extend>


text:
get_inner_vars_count(::PSY.DynamicGenerator) = GEN_INNER_VARS_SIZE
get_inner_vars_count(::PSY.DynamicInverter) = INV_INNER_VARS_SIZE
get_inner_vars_count(::PSY.PeriodicVariableSource) = 0

index(::Type{<:PSY.TurbineGov}) = 1
index(::Type{<:PSY.PSS}) = 2
index(::Type{<:PSY.Machine}) = 3
index(::Type{<:PSY.Shaft}) = 4
index(::Type{<:PSY.AVR}) = 5

index(::Type{<:PSY.DCSource}) = 1
index(::Type{<:PSY.FrequencyEstimator}) = 2
index(::Type{<:PSY.OuterControl}) = 3
index(::Type{<:PSY.InnerControl}) = 4
index(::Type{<:PSY.Converter}) = 5
index(::Type{<:PSY.Filter}) = 6

"""
Wraps DynamicInjection devices from PowerSystems to handle changes in controls and connection
status, and allocate the required indexes of the state space.
"""
struct DynamicWrapper{T <: PSY.DynamicInjection}
    device::T
    system_base_power::Float64
    system_base_frequency::Float64
    static_type::Type{<:PSY.StaticInjection}
    bus_category::Type{<:BusCategory}
    connection_status::Base.RefValue{Float64}
    V_ref::Base.RefValue{Float64}
    ω_ref::Base.RefValue{Float64}
    P_ref::Base.RefValue{Float64}
    Q_ref::Base.RefValue{Float64}
    inner_vars_index::Vector{Int}
    ix_range::Vector{Int}
    ode_range::Vector{Int}
    bus_ix::Int
    global_index::Base.ImmutableDict{Symbol, Int}
    component_state_mapping::Base.ImmutableDict{Int, Vector{Int}}
    input_port_mapping::Base.ImmutableDict{Int, Vector{Int}}
end

function DynamicWrapper(
    device::T,
    bus_ix::Int,
    ix_range,
    ode_range,
    inner_var_range,
    sys_base_power,
    sys_base_freq,
) where {T <: PSY.Device}
    dynamic_device = PSY.get_dynamic_injector(device)
    @assert dynamic_device !== nothing
    device_states = PSY.get_states(dynamic_device)
    component_state_mapping = Dict{Int, Vector{Int}}()
    input_port_mapping = Dict{Int, Vector{Int}}()

    for c in PSY.get_dynamic_components(dynamic_device)
        ix = index(typeof(c))
        component_state_mapping[ix] = _index_local_states(c, device_states)
        input_port_mapping[ix] = _index_port_mapping!(c, device_states)
    end

    return DynamicWrapper{typeof(dynamic_device)}(
        dynamic_device,
        sys_base_power,
        sys_base_freq,
        T,
        BUS_MAP[PSY.get_bustype(PSY.get_bus(device))],
        Base.Ref(1.0),
        Base.Ref(PSY.get_V_ref(dynamic_device)),
        Base.Ref(PSY.get_ω_ref(dynamic_device)),
        Base.Ref(PSY.get_P_ref(dynamic_device)),
        Base.Ref(PSY.get_reactive_power(device)),
        inner_var_range,
        ix_range,
        ode_range,
        bus_ix,
        Base.ImmutableDict(
            sort!(device_states .=> ix_range, by = x -> x.second, rev = true)...,
        ),
        Base.ImmutableDict(component_state_mapping...),
        Base.ImmutableDict(input_port_mapping...),
    )
end

function DynamicWrapper(
    device::PSY.Source,
    bus_ix::Int,
    ix_range,
    ode_range,
    inner_var_range,
    sys_base_power,
    sys_base_freq,
)
    dynamic_device = PSY.get_dynamic_injector(device)
    @assert dynamic_device !== nothing
    device_states = PSY.get_states(dynamic_device)
    @assert PSY.get_X_th(dynamic_device) == PSY.get_X_th(device)
    @assert PSY.get_R_th(dynamic_device) == PSY.get_R_th(device)

    return DynamicWrapper{typeof(dynamic_device)}(
        dynamic_device,
        sys_base_power,
        sys_base_freq,
        PSY.Source,
        BUS_MAP[PSY.get_bustype(PSY.get_bus(device))],
        Base.Ref(1.0),
        Base.Ref(0.0),
        Base.Ref(0.0),
        Base.Ref(0.0),
        Base.Ref(0.0),
        collect(inner_var_range),
        collect(ix_range),
        collect(ode_range),
        bus_ix,
        Base.ImmutableDict(Dict(device_states .=> ix_range)...),
        Base.ImmutableDict{Int, Vector{Int}}(),
        Base.ImmutableDict{Int, Vector{Int}}(),
    )
end

function _index_local_states(component::PSY.DynamicComponent, device_states::Vector{Symbol})
    component_state_index = Vector{Int}(undef, PSY.get_n_states(component))
    component_states = PSY.get_states(component)
    for (ix, s) in enumerate(component_states)
        component_state_index[ix] = findfirst(x -> x == s, device_states)
    end
    return component_state_index
end

function _index_port_mapping!(
    component::PSY.DynamicComponent,
    device_states::Vector{Symbol},
)
    ports = Ports(component)
    index_component_inputs = Vector{Int}()
    for i in ports[:states]
        tmp = [(ix, var) for (ix, var) in enumerate(device_states) if var == i]
        isempty(tmp) && continue
        push!(index_component_inputs, tmp[1][1])
    end
    return index_component_inputs
end

get_device(wrapper::DynamicWrapper) = wrapper.device
get_device_type(::DynamicWrapper{T}) where {T <: PSY.DynamicInjection} = T
get_bus_category(wrapper::DynamicWrapper) = wrapper.bus_category
get_inner_vars_index(wrapper::DynamicWrapper) = wrapper.inner_vars_index
get_ix_range(wrapper::DynamicWrapper) = wrapper.ix_range
get_ode_ouput_range(wrapper::DynamicWrapper) = wrapper.ode_range
get_bus_ix(wrapper::DynamicWrapper) = wrapper.bus_ix
get_global_index(wrapper::DynamicWrapper) = wrapper.global_index
get_component_state_mapping(wrapper::DynamicWrapper) = wrapper.component_state_mapping
get_input_port_mapping(wrapper::DynamicWrapper) = wrapper.input_port_mapping

get_system_base_power(wrapper::DynamicWrapper) = wrapper.system_base_power
get_system_base_frequency(wrapper::DynamicWrapper) = wrapper.system_base_frequency

get_P_ref(wrapper::DynamicWrapper) = wrapper.P_ref[]
get_Q_ref(wrapper::DynamicWrapper) = wrapper.Q_ref[]
get_V_ref(wrapper::DynamicWrapper) = wrapper.V_ref[]
get_ω_ref(wrapper::DynamicWrapper) = wrapper.ω_ref[]

set_P_ref(wrapper::DynamicWrapper, val::Float64) = wrapper.P_ref[] = val
set_Q_ref(wrapper::DynamicWrapper, val::Float64) = wrapper.Q_ref[] = val
set_V_ref(wrapper::DynamicWrapper, val::Float64) = wrapper.V_ref[] = val
set_ω_ref(wrapper::DynamicWrapper, val::Float64) = wrapper.ω_ref[] = val

# PSY overloads for the wrapper
PSY.get_name(wrapper::DynamicWrapper) = PSY.get_name(wrapper.device)
PSY.get_ext(wrapper::DynamicWrapper) = PSY.get_ext(wrapper.device)
PSY.get_states(wrapper::DynamicWrapper) = PSY.get_states(wrapper.device)
PSY.get_n_states(wrapper::DynamicWrapper) = PSY.get_n_states(wrapper.device)
PSY.get_base_power(wrapper::DynamicWrapper) = PSY.get_base_power(wrapper.device)

PSY.get_machine(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicGenerator} =
    wrapper.device.machine
PSY.get_shaft(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicGenerator} =
    wrapper.device.shaft
PSY.get_avr(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicGenerator} =
    wrapper.device.avr
PSY.get_prime_mover(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicGenerator} =
    wrapper.device.prime_mover
PSY.get_pss(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicGenerator} =
    wrapper.device.pss

PSY.get_converter(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicInverter} =
    wrapper.device.converter
PSY.get_outer_control(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicInverter} =
    wrapper.device.outer_control
PSY.get_inner_control(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicInverter} =
    wrapper.device.inner_control
PSY.get_dc_source(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicInverter} =
    wrapper.device.dc_source
PSY.get_freq_estimator(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicInverter} =
    wrapper.device.freq_estimator
PSY.get_filter(wrapper::DynamicWrapper{T}) where {T <: PSY.DynamicInverter} =
    wrapper.device.filter

function get_local_state_ix(
    wrapper::DynamicWrapper,
    ::Type{T},
) where {T <: PSY.DynamicComponent}
    return wrapper.component_state_mapping[index(T)]
end

function get_input_port_ix(
    wrapper::DynamicWrapper,
    ::Type{T},
) where {T <: PSY.DynamicComponent}
    return wrapper.input_port_mapping[index(T)]
end

function get_local_state_ix(wrapper::DynamicWrapper, ::T) where {T <: PSY.DynamicComponent}
    return get_local_state_ix(wrapper, T)
end

function get_input_port_ix(wrapper::DynamicWrapper, ::T) where {T <: PSY.DynamicComponent}
    return get_input_port_ix(wrapper, T)
end

struct StaticWrapper{T <: PSY.StaticInjection, V}
    device::T
    connection_status::Base.RefValue{Float64}
    V_ref::Base.RefValue{Float64}
    θ_ref::Base.RefValue{Float64}
    P_ref::Base.RefValue{Float64}
    Q_ref::Base.RefValue{Float64}
    bus_ix::Int
end

function DynamicWrapper(device::T, bus_ix::Int) where {T <: PSY.Device}
    bus = PSY.get_bus(device)
    StaticWrapper{T, BUS_MAP[PSY.get_bustype(bus)]}(
        device,
        Base.Ref(1.0),
        Base.Ref(PSY.get_magnitude(bus)),
        Base.Ref(PSY.get_angle(bus)),
        Base.Ref(PSY.get_active_power(device)),
        Base.Ref(PSY.get_reactive_power(device)),
        bus_ix,
    )
end

function StaticWrapper(device::T, bus_ix::Int) where {T <: PSY.Source}
    bus = PSY.get_bus(device)
    return StaticWrapper{T, BUS_MAP[PSY.get_bustype(bus)]}(
        device,
        Base.Ref(1.0),
        Base.Ref(PSY.get_internal_voltage(device)),
        Base.Ref(PSY.get_internal_angle(device)),
        Base.Ref(PSY.get_active_power(device)),
        Base.Ref(PSY.get_reactive_power(device)),
        bus_ix,
    )
end

# get_bustype is already exported in PSY. So this is named this way to avoid name collisions
get_bus_category(::StaticWrapper{<:PSY.StaticInjection, U}) where {U} = U

function StaticWrapper(device::T, bus_ix::Int) where {T <: PSY.ElectricLoad}
    bus = PSY.get_bus(device)
    return StaticWrapper{T, LOAD_MAP[PSY.get_model(device)]}(
        device,
        Base.Ref(1.0),
        Base.Ref(PSY.get_magnitude(bus)),
        Base.Ref(PSY.get_angle(bus)),
        Base.Ref(PSY.get_active_power(device)),
        Base.Ref(PSY.get_reactive_power(device)),
        bus_ix,
    )
end

# TODO: something smart to forward fields
get_device(wrapper::StaticWrapper) = wrapper.device
get_bus_ix(wrapper::StaticWrapper) = wrapper.bus_ix

# get_bustype is already exported in PSY. So this is named this way to avoid name collisions
get_bus_category(::StaticWrapper{<:PSY.ElectricLoad, U}) where {U} = PQBus
get_load_category(::StaticWrapper{<:PSY.ElectricLoad, U}) where {U} = U

get_P_ref(wrapper::StaticWrapper) = wrapper.P_ref[]
get_Q_ref(wrapper::StaticWrapper) = wrapper.Q_ref[]
get_V_ref(wrapper::StaticWrapper) = wrapper.V_ref[]
get_θ_ref(wrapper::StaticWrapper) = wrapper.θ_ref[]

set_P_ref(wrapper::StaticWrapper, val::Float64) = wrapper.P_ref[] = val
set_Q_ref(wrapper::StaticWrapper, val::Float64) = wrapper.Q_ref[] = val
set_V_ref(wrapper::StaticWrapper, val::Float64) = wrapper.V_ref[] = val
set_θ_ref(wrapper::StaticWrapper, val::Float64) = wrapper.θ_ref[] = val

PSY.get_bus(wrapper::StaticWrapper) = PSY.get_bus(wrapper.device)
PSY.get_active_power(wrapper::StaticWrapper) = PSY.get_active_power(wrapper.device)
PSY.get_reactive_power(wrapper::StaticWrapper) = PSY.get_reactive_power(wrapper.device)
PSY.get_name(wrapper::StaticWrapper) = PSY.get_name(wrapper.device)
PSY.get_ext(wrapper::StaticWrapper) = PSY.get_ext(wrapper.device)

function set_connection_status(wrapper::Union{StaticWrapper, DynamicWrapper}, val::Int)
    if val == 0
        @debug "Generator $(PSY.get_name(wrapper)) status set to off"
    elseif val == 1
        @debug "Generator $(PSY.get_name(wrapper)) status set to on"
    else
        error("Invalid status $val. It can only take values 1 or 0")
    end
    wrapper.connection_status[] = Float64(val)
end

get_connection_status(wrapper::Union{StaticWrapper, DynamicWrapper}) =
    wrapper.connection_status[]


text:
module CAGD
	using DataStructures
	using IntervalTrees
	using LinearAlgebra
	using LinearAlgebraicRepresentation
	using NearestNeighbors
	using SparseArrays

	Lar = LinearAlgebraicRepresentation

	include("./model.jl")

	include("./planar_arrangement.jl")
	include("./spatial_arrangement.jl")
	include("./spatial_indices.jl")

#	include("./input.jl")
	include("./splitting.jl")
	include("./congruence.jl")
	include("./tgw2.jl")
	include("./tgw3.jl")
	include("./loops.jl")
	include("./utils.jl")
#	include("./output.jl")
	include("./bool.jl")

	include("lar_interface.jl")

	export chaincongruence
end


text:
const Fractal{D} = Vector{Segment{D}}

"""Bounding CUBEoid of the fractal"""
function Box{D}(fractal::Fractal{D})
    X = Point((minimum(line.box.X[i] for line in fractal) for i in 1:D)...)
    Y = Point((maximum(line.box.Y[i] for line in fractal) for i in 1:D)...)
    dX = Y - X

    shift_size = 0.05*minimum(dX)
    shift = Point(tuple(shift_size*ones(D)...))
    # Shift both a bit not to have corner collisions
    X -= shift
    Y += shift
    dX = Y - X
    # Pick largest
    dx = maximum(dX)
    # Smallest cuboid that contains it
    Y = X + dx*ones(D)

    return Box(X, Y)
end

"""
Estimate the fractal dimension by succesively refining the bounding box
and counting on each level of refinement the number of intersecting boxes
"""
struct BoxCounter{D}
    # THe idea is to split the fractal into pieces
    fractal_pieces::Deque{Fractal{D}}
    # Which might collide with the boxes on this level
    boxes::Deque{Vector{Box{D}}}
    size::Float64  # size of the leaf box
    icount::Int    # segment count of fractal, just for printing
end

show{D}(io::IO, c::BoxCounter{D}) = begin
    print(io, "BoxCounter for curve with $(c.icount) pieces.")
end

"""BoxCounter for the fractal"""
function BoxCounter{D}(fractal::Fractal{D})
    icount = length(fractal)

    fractal_pieces = Deque{Fractal{D}}()
    boxes = Deque{Vector{Box{D}}}()
    # At the beginning there is one bounding box of fracal and
    # fractal is in one piece
    push!(fractal_pieces, fractal)

    box = Box(fractal)
    push!(boxes, [box])

    size = first(box.Y - box.X)

    BoxCounter{D}(fractal_pieces, boxes, size, icount)
end

# One box intersected. That box is bounding box
start{D}(c::BoxCounter{D}, nlevels::Int) = (nlevels, (2*c.size, 1))

"""
The iterator state is the (level of refinment,
                           (size of bbox on this level,
                            count of intersected boxes))
"""
function next{D}(c::BoxCounter{D}, state)

    level, (size, count) = state
    @assert length(c.boxes) == length(c.fractal_pieces)

    count *= 0
    for i in 1:length(c.boxes)
        box = shift!(c.boxes)
        fractal_piece = shift!(c.fractal_pieces)

        for b in box
            b_piece = Fractal{D}()
            # Let's get segments of the piece that can collide with box
            for fj in fractal_piece
                bbox_collides(fj.box, b) && push!(b_piece, fj)
            end
            # See that there really is an intersect
            for fi in b_piece
                if collides(fi, b)
                    count += 1
                    push!(c.boxes, split(b))
                    push!(c.fractal_pieces, b_piece)
                    break
                end
            end
        end
    end
    size /= 2
    level -= 1
    (level, (size, count))
end

done{D}(c::BoxCounter{D}, state) = first(state) < 0

# -------------------------------------------------------------------

# This is a non-iterator version of the above
function fractal_dimension{D}(fractal::Fractal{D}, terminate::Function)
    fractal_pieces = Deque{Fractal{D}}()
    boxes = Deque{Vector{Box{D}}}()
    # At the beginning there is one bounding box of fracal and
    # fractal is in one piece
    push!(fractal_pieces, fractal)

    box = Box(fractal)
    push!(boxes, [box])

    size = first(box.Y - box.X)
    level = 0

    while !terminate(level, size)
        # Intersect on this level
        count = 0
        @assert length(boxes) == length(fractal_pieces)
        for i in 1:length(boxes)
            box = shift!(boxes)
            fractal_piece = shift!(fractal_pieces)

            for b in box
                indices = IntSet(1:length(fractal_piece))
                # Let's get the segments of the piece that can collide with
                # the box
                for (j, fj) in enumerate(fractal_piece)
                    !bbox_collides(fj.box, b) && delete!(indices, j)
                end
                # See that there really is an intersect
                b_piece = fractal_piece[collect(indices)]
                for fi in b_piece
                    if collides(fi, b)
                        count +=1
                        push!(boxes, split(b))
                        # Split box will have to deal with only part
                        push!(fractal_pieces, b_piece)
                        break
                    end
                end
            end
        end
        @show size, count
        size /= 2
        level += 1
    end
end

max_stars_repo_name: MiroK/fractional-dim


text:
module HeartRateVariability

include("TimeDomain.jl")
include("Input.jl")
include("Frequency.jl")
include("Nonlinear.jl")
include("Geometric.jl")

"""
    geometric(n,e="mean")

Arguments:
- n: the array that contains the NN-inetrvals
- e: the maximum distance between two intervals, default="mean" (the mean value of the succsessive differences), has to be "mean" or a number

Results:
- poincare: the Poincaré plot
- recurrence: the recurrence plot
"""
function geometric(n::Array{Float64,1},e="mean")
    if (e!="mean" && !isa(e,Number))
           error("e has to be a numerical value or 'mean'")
       end
    return (poincare=Geometric.poincare(n),recurrence=Geometric.recurrence(n,e))
end # geometric

"""
    nonlinear(n,m=2,r=6)

Arguments:
- n: the array that contains the NN-inetrvals
- m: the embedding dimension, default=2
- r: the tolerance, default=6

Results:
- apen: the approximate entropy
- sampen: the sample entropy
- hurst: the hurst exponent (only valid if the length of n is >= 100)
- renyi0, renyi1, renyi2: the Rényi entropy of order 0,1 and 2
"""
function nonlinear(n::Array{Float64,1},m::Int64=2,r::Number=6)
    if length(n)<100
        @warn("To obtain a valid value for the hurst coefficient, the length of the data series must be greater than or equal to 100.")
    end
    return (apen=Nonlinear.apen(n,m,r), sampen=Nonlinear.sampen(n,m,r),
            hurst=Nonlinear.hurst(n), renyi0=Nonlinear.renyi(n,0),
            renyi1=Nonlinear.renyi(n,1), renyi2=Nonlinear.renyi(n,2))
end # nonlinear

"""
    frequency(n)

Arguments:
- n: the array that contains the NN-inetrvals

Results:
- vlf: the very low-frequency power
- lf: the low-frequency power
- hf: the high-frequency power
- lfhf_ratio: the lf/hf ratio
- tp: the total power
"""
function frequency(n::Array{Float64,1})
    ls=Frequency.lomb_scargle(n)
    vlf=Frequency.get_power(ls.freq,ls.power,0.003,0.04)
    lf=Frequency.get_power(ls.freq,ls.power,0.04,0.15)
    hf=Frequency.get_power(ls.freq,ls.power,0.15,0.4)
    tp=vlf+lf+hf
    return (vlf=vlf, lf=lf, hf=hf, lfhf_ratio=lf/hf, tp=tp)
end # frequency

"""
    time_domain(n)

Arguments:
- n: the array that contains the NN-inetrvals

Results:
- mean: the mean value
- sdnn: the standard deviation
- rmssd: the root mean square of successive differences
- sdsd: the standard deviation of successive differences
- nn50: the number of successive NN intervals with an interval smaller than 50 ms
- pnn50: the percentage of successive NN intervals with an interval smaller than 50 ms
- nn20: the number of successive NN intervals with an interval smaller than 20 ms
- pnn20: the percentage of successive NN intervals with an interval smaller than 20 ms
- rRR: the percentage of relative RR intervals
"""
function time_domain(n::Array{Float64,1})
    diff=TimeDomain.nn_diff(n)
    return (mean=TimeDomain.mean_nn(n),sdnn=TimeDomain.sdnn(n),
            rmssd=TimeDomain.rmssd(diff), sdsd=TimeDomain.sdsd(diff),
            nn50=TimeDomain.nn(diff,50), pnn50=TimeDomain.pnn(diff,50),
            nn20=TimeDomain.nn(diff,20), pnn20=TimeDomain.pnn(diff,20),
            rRR=TimeDomain.rRR(n))
end # time_domain

"""
    infile(file)

This function reads the data from a txt or csv file.

Arguments:
- file: is the path of the input file

"""
function infile(file::String)
    return Input.read_txt(file)
end # infile

"""
    infile(record,annotator)

This function reads the data from a wbdb file.

Arguments:
- record: is the name of the record
- annotator: is the annotator of the record

!!! note
    In order to use the infile function for wfdb files, the WFDB Software Package from
    Pysionet is required. See [Installation](installation) for more information.
"""
function infile(record::String,annotator::String)
    return Input.read_wfdb(record,annotator)
end # infile

export nonlinear, frequency, time_domain, infile, geometric
end # module


text:
#######################################################################
import JSON, Conda
using Compat
using Compat.Unicode: lowercase

jupyter=""

# remove deps.jl at exit if it exists, in case build.jl fails
try
#######################################################################

# Make sure Python uses UTF-8 output for Unicode paths
ENV["PYTHONIOENCODING"] = "UTF-8"

function prog_version(prog)
    v = try
        chomp(read(`$prog --version`, String))
    catch
        return nothing
    end
    try
       return VersionNumber(v)
    catch
        Compat.@warn("`$jupyter --version` returned an unrecognized version number $v")
        return v"0.0"
    end
end

prefsfile = joinpath(first(DEPOT_PATH), "prefs", "IJulia")
mkpath(dirname(prefsfile))

global jupyter = get(ENV, "JUPYTER", isfile(prefsfile) ? readchomp(prefsfile) : Compat.Sys.isunix() && !Compat.Sys.isapple() ? "jupyter" : "")
if isempty(jupyter)
    jupyter_vers = nothing
else
    jupyter_vers = prog_version(jupyter)
    if jupyter_vers === nothing
        jupyter_vers = prog_version(jupyter * "-notebook")
    end
    if jupyter_vers === nothing
        Compat.@warn("Could not execute `$jupyter --version`.")
    end
end
isconda = dirname(jupyter) == abspath(Conda.SCRIPTDIR)
if Sys.ARCH in (:i686, :x86_64) && (jupyter_vers === nothing || jupyter_vers < v"3.0" || isconda)
    isconda || jupyter_vers === nothing || Compat.@info("$jupyter was too old: got $jupyter_vers, required ≥ 3.0")
    Compat.@info("Installing Jupyter via the Conda package.")
    Conda.add("jupyter")
    jupyter = abspath(Conda.SCRIPTDIR, "jupyter")
    jupyter_vers = prog_version(jupyter)
end
if jupyter_vers === nothing || jupyter_vers < v"3.0"
    error("Failed to find or install Jupyter 3.0 or later. Please install Jupyter manually, set `ENV[\"JUPYTER\"]=\"/path/to/jupyter\", and rerun `Pkg.build(\"IJulia\")`.")
end
Compat.@info("Found Jupyter version $jupyter_vers: $jupyter")

#######################################################################
# Get the latest syntax highlighter file.
if isconda
    highlighter = joinpath(Conda.LIBDIR, "python2.7", "site-packages", "notebook", "static",
                           "components", "codemirror", "mode", "julia", "julia.js")
    # CodeMirror commit from which we get the syntax highlighter
    cm_commit = "ed9278cba6e1f75328df6b257f1043d35a690c59"
    highlighter_url = "https://raw.githubusercontent.com/codemirror/CodeMirror/" *
                      cm_commit * "/mode/julia/julia.js"
    if isfile(highlighter)
        try
            download(highlighter_url, highlighter)
        catch e
            Compat.@warn("The following error occurred while attempting to download latest ",
                 "syntax highlighting definitions:\n\n", e, "\n\nSyntax highlighting may ",
                 "not work as expected.")
        end
    end
end

#######################################################################
# Warn people upgrading from older IJulia versions:
try
    juliaprof = chomp(read(pipeline(`$ipython locate profile julia`,
                                    stderr=devnull), String))
    Compat.@warn("""You should now run IJulia just via `$jupyter notebook`, without
            the `--profile julia` flag.  IJulia no longer maintains the profile.
            Consider deleting $juliaprof""")
catch
end

#######################################################################
# Install Jupyter kernel-spec file.

include("kspec.jl")
kspec_cmd, = installkernel("Julia")

# figure out the notebook command by replacing (only!) the last occurrence of
# "kernelspec" with "notebook":
notebook = kspec_cmd.exec
n = notebook[end]
ki = findlast("kernelspec", n)
notebook[end] = n[1:prevind(n,first(ki))] * "notebook" * n[nextind(n,last(ki)):end]

#######################################################################
# make it easier to get more debugging output by setting JULIA_DEBUG=1
# when building.
IJULIA_DEBUG = lowercase(get(ENV, "IJULIA_DEBUG", "0"))
IJULIA_DEBUG = IJULIA_DEBUG in ("1", "true", "yes")

#######################################################################
# Install the deps.jl file:

if v"4.2" ≤ jupyter_vers < v"5.1"
    # disable broken data-rate limit (issue #528)
    push!(notebook, "--NotebookApp.iopub_data_rate_limit=2147483647")
end
deps = """
    const jupyter = "$(escape_string(jupyter))"
    const notebook_cmd = ["$(join(map(escape_string, notebook), "\", \""))"]
    const jupyter_vers = $(repr(jupyter_vers))
    const IJULIA_DEBUG = $(IJULIA_DEBUG)
    """
if !isfile("deps.jl") || read("deps.jl", String) != deps
    write("deps.jl", deps)
end
write(prefsfile, jupyter)

#######################################################################
catch
isfile("deps.jl") && rm("deps.jl") # remove deps.jl file on build error
rethrow()
end


text:
using Xiao2021
using Test

@testset "solve_eqm" begin
    # Write your tests here.
    set = getSettings();
    par = getParams();
    fxp = getFixParameters();
    init = getInit();
    e = solve_eqm.solve(par,set,fxp,init);
    e_matlab = solve_eqm_test.getDictMatlabWoWage();
end


text:
module Assemble

using ..Input: CellData

struct Cell
    # TODO
end

function Cell(data::CellData)

end

end # module Assemble


text:
import ForwardDiff
import LegibleLambdas
import LegibleLambdas: @λ, LegibleLambda
import ACE: read_dict, write_dict

λ(str::String) = λ(Meta.parse(str))

λ(ex::Expr) = LegibleLambda(ex, eval(ex))

analytic(str::String) = legiblelambda(str)

evaluate(t::LegibleLambda, x) = t.λ(x)

evaluate_d(t::LegibleLambda, x::SVector) =  ForwardDiff.gradient(t.λ, x)

ACE.evaluate_ed(t::LegibleLambda, x) =  evaluate(t, x), evaluate_d(t, x)

evaluate_dd(t::LegibleLambda, x::SVector) = ForwardDiff.hessian(t.λ, x)

evaluate_d(t::LegibleLambda, x::Real) =     ForwardDiff.derivative(t.λ, x)

evaluate_dd(t::LegibleLambda, x::Real) =     ForwardDiff.derivative(y -> evaluate_d(t, y), x)

function frule_evaluate(t::LegibleLambda, x::Real, dx::SVector)
      f = evaluate(t, x)
      df = evaluate_d(t, x)
      return f, df * dx
end

function write_dict(t::LegibleLambda)
   buf = IOBuffer()
   show(buf, t)
   return Dict(
         "__id__" => "ACE_LegibleLambda",
         "ex" => "$(t.ex)",             # f is reconstructed from ex
         "meta" => String(take!(buf))   # this will be ignored
      )
end

read_dict(::Val{:ACE_LegibleLambda}, D::Dict) = λ(D["ex"])

import Base: ==

==(F1::LegibleLambda, F2::LegibleLambda) = (F1.ex == F2.ex)


text:
using Resonance
omni, etoh, tps, complete_brain, metabolites, species = startup()
genes = Resonance.read_gfs_arrow()

specu1 = species[:, [!ismissing(a) && 2 < a < 10 for a in get(species, :ageMonths)]]
shannon!(specu1)

set!(genes, leftjoin(tps, select(omni, [:sample, :subject, :timepoint]), on = [:subject, :timepoint]))
genesu1 = genes[:, [!ismissing(a) && 2 < a < 10 for a in get(genes, :ageMonths)]]
shannon!(genesu1)

set!(metabolites, leftjoin(tps, select(etoh, [:sample, :subject, :timepoint]), on = [:subject, :timepoint]))
metabolitesu1 = metabolites[:, [!ismissing(a) && 2 < a < 10 for a in get(metabolites, :ageMonths)]]

pcspec = pcoa(specu1)

pcgenes = pcoa(genesu1)
#-

using CairoMakie
using AlgebraOfGraphics

#-

fig = Figure(resolution=(1000, 1000))
ax1 = Axis(fig[1,1]; ylabel=mdsaxis(pcspec, 2))
ax2 = Axis(fig[2,1]; xlabel=mdsaxis(pcspec, 1), ylabel=mdsaxis(pcspec, 2))
ax3 = Axis(fig[1,2]; ylabel=mdsaxis(pcgenes, 2))
ax4 = Axis(fig[2,2]; xlabel=mdsaxis(pcgenes, 1), ylabel=mdsaxis(pcgenes, 2))

sc1 = scatter!(ax1, loadings(pcspec, 1), loadings(pcspec,2);
                    xlabel=mdsaxis(pcspec, 1),
                    ylabel=mdsaxis(pcspec, 2),
                    color=get(specu1, :ageMonths)
)
sc2 = scatter!(ax2, loadings(pcspec, 1), loadings(pcspec,2);
                    color=get(specu1, :shannon),
                    colormap=:plasma
)

sc3 = scatter!(ax3, loadings(pcgenes, 1), loadings(pcgenes,2);
                    xlabel=mdsaxis(pcgenes, 1),
                    ylabel=mdsaxis(pcgenes, 2),
                    color=get(genesu1, :ageMonths)
)
sc4 = scatter!(ax4, loadings(pcgenes, 1), loadings(pcgenes,2);
                    color=get(genesu1, :shannon),
                    colormap=:plasma
)
Colorbar(fig[1,3], sc1; label="Age (months)")
Colorbar(fig[2,3], sc2; label="Shannon diversity")

Label(fig[0, 1], "Taxonomic Ordinations"; textsize=20, tellwidth=false)
Label(fig[1, 2], "Functional Ordinations"; textsize=20, tellwidth=false)

fig

#-

using PERMANOVA

preds = DataFrame(sample = samplenames(specu1),
                  ageMonths = get(specu1, :ageMonths),
                  cogScore=get(specu1, :cogScore),
                  race=get(specu1, :simple_race)
)

hascog = findall(!ismissing, preds.cogScore)
hasrace = findall(!ismissing, preds.race)

p_spec_age = permanova(select(preds, [:ageMonths]), abundances(specu1)', BrayCurtis, @formula(1~ageMonths))
p_spec_cog = permanova(select(preds, [:cogScore])[hascog, :], abundances(specu1)[:, hascog]', BrayCurtis, @formula(1~cogScore))
p_spec_race = permanova(select(preds, [:race])[hasrace, :], abundances(specu1)[:, hasrace]', BrayCurtis, @formula(1~race))

#-

preds = DataFrame(sample = samplenames(genesu1),
                  ageMonths = get(genesu1, :ageMonths),
                  cogScore=get(genesu1, :cogScore),
                  race=get(genesu1, :simple_race)
)

hascog = findall(!ismissing, preds.cogScore)
hasrace = findall(!ismissing, preds.race)

p_genes_age = permanova(select(preds, [:ageMonths]), abundances(genesu1)', BrayCurtis, @formula(1~ageMonths))
p_genes_cog = permanova(select(preds, [:cogScore])[hascog, :], abundances(genesu1)[:, hascog]', BrayCurtis, @formula(1~cogScore))
p_genes_race = permanova(select(preds, [:race])[hasrace, :], abundances(genesu1)[:, hasrace]', BrayCurtis, @formula(1~race))

#-

preds = DataFrame(sample = samplenames(metabolitesu1),
                  ageMonths = get(metabolitesu1, :ageMonths),
                  cogScore=get(metabolitesu1, :cogScore),
                  race=get(metabolitesu1, :simple_race)
)

hascog = findall(!ismissing, preds.cogScore)
hasrace = findall(!ismissing, preds.race)

p_metabolites_age = permanova(select(preds, [:ageMonths]), abundances(metabolitesu1)', BrayCurtis, @formula(1~ageMonths))
p_metabolites_cog = permanova(select(preds, [:cogScore])[hascog, :], abundances(metabolitesu1)[:, hascog]', BrayCurtis, @formula(1~cogScore))
p_metabolites_race = permanova(select(preds, [:race])[hasrace, :], abundances(metabolitesu1)[:, hasrace]', BrayCurtis, @formula(1~race))

varexpl(p::PERMANOVA.PSummary) = p.results[1, 3] * 100
pvalue(p::PERMANOVA.PSummary) = p.results[1, 5]

vmat = varexpl.([
    p_spec_age  p_genes_age  p_metabolites_age;
    p_spec_cog  p_genes_cog  p_metabolites_cog;
    p_spec_race p_genes_race p_metabolites_race;
])

pmat = pvalue.([
    p_spec_age  p_genes_age  p_metabolites_age;
    p_spec_cog  p_genes_cog  p_metabolites_cog;
    p_spec_race p_genes_race p_metabolites_race;
])

heatmap(vmat; colormap=:blues, colorrange=(0, 10))

#-

using GLM
using MixedModels
using AlgebraOfGraphics
using MultipleTesting

prev = prevalence(specu1, 0.01)

specdf = DataFrame(age=get(specu1, :ageMonths), cogScore=get(specu1, :cogScore))
for sp in features(specu1)[findall(p-> p > 0.1, vec(prev))]
    specdf[:, name(sp)] = vec(abundances(specu1[sp, :]))
end

specdf

lmres = DataFrame()

for sp in Symbol.(name.(features(specu1)[findall(p-> p > 0.1, vec(prev))]))
    f = @eval @formula($sp ~ cogScore+age)
    modl = lm(f, specdf)
    df = DataFrame(coeftable(modl))
    df.species .= string(sp)
    rename!(df, "Pr(>|t|)"=>"pvalue", "Coef."=> "coef")
    append!(lmres, df)
end

subset!(lmres, "Name"=> ByRow(!=("(Intercept)")))
lmres.qvalue = adjust(lmres.pvalue, BenjaminiHochberg())

sort!(lmres, :qvalue)

##

pred = DataFrame(gabasynth = repeat(range(extrema(genemetab.gabasynth)..., length=50), outer=2),
                 gabadegr  = repeat(range(extrema(genemetab.gabadegr)..., length=50), outer=2),
                 gabagut   = zeros(100),
                 glutsynth = repeat(range(extrema(genemetab.glutsynth)..., length=50), outer=2),
                 glutdegr  = repeat(range(extrema(genemetab.glutdegr)..., length=50), outer=2),
                 glutgut   = zeros(100),
                 mc        = repeat(["M", "C"], inner=50))

pred.gabasynth_pred = predict(gabasynthlm, pred)
pred.gabadegr_pred  = predict(gabadegrlm, pred)
pred.glutsynth_pred = predict(glutsynthlm, pred)
pred.glutdegr_pred  = predict(glutdegrlm, pred)

predgrp = groupby(pred, :mc)

max_stars_repo_name: Klepac-Ceraj-Lab/ResonanceAnalysis

max_issues_repo_name: Klepac-Ceraj-Lab/ResonanceAnalysis

max_forks_repo_name: Klepac-Ceraj-Lab/ResonanceAnalysis