text:
const EmptyNamedTuple = NamedTuple{(),Tuple{}}

function Base.show(io::IO, μ::AbstractMeasure)
    io = IOContext(io, :compact => true)
    Pretty.pprint(io, μ)
end

showparams(io::IO, ::EmptyNamedTuple) = print(io, "()")
showparams(io::IO, nt::NamedTuple) = print(io, nt)

@inline function fix(f, x)
    y = f(x)
    # Workaround bug https://github.com/JuliaLang/julia/issues/42615
    while x !== y
        (x, y) = (y, f(y))
    end

    return y
end

# function constructorof(::Type{T}) where {T}
#     C = T
#     while C isa UnionAll
#         C = C.body
#     end

#     return C.name.wrapper
# end

constructor(::T) where {T} = constructor(T)

constructor(::Type{T}) where {T} = constructorof(T)

export testvalue
testvalue(μ::AbstractMeasure) = testvalue(basemeasure(μ))

export rootmeasure

"""
    rootmeasure(μ::AbstractMeasure)

It's sometimes important to be able to find the fix point of a measure under
`basemeasure`. That is, to start with some measure and apply `basemeasure`
repeatedly until there's no change. That's what this does.
"""
rootmeasure(μ::AbstractMeasure) = fix(basemeasure, μ)

# Base on the Tricks.jl README
using Tricks
struct Iterable end
struct NonIterable end
isiterable(::Type{T}) where {T} =
    static_hasmethod(iterate, Tuple{T}) ? Iterable() : NonIterable()

functioninstance(::Type{F}) where {F<:Function} = F.instance

# See https://github.com/cscherrer/KeywordCalls.jl/issues/22
@inline instance_type(f::F) where {F<:Function} = F
@inline instance_type(f::UnionAll) = Type{f}

using MLStyle


text:
###
### String Decorators
###
###
### String literals for LongSequences
###
### This file is a part of BioJulia.
### License is MIT: https://github.com/BioJulia/BioSequences.jl/blob/master/LICENSE.md

remove_newlines(s) = replace(s, r"\r|\n" => "")

macro dna_str(seq, flag)
    if flag == "s"
        return LongDNASeq(remove_newlines(seq))
    elseif flag == "d"
        return quote
            LongDNASeq($(remove_newlines(seq)))
        end
    end
    error("Invalid DNA flag: '$(flag)'")
end

macro dna_str(seq)
    return LongDNASeq(remove_newlines(seq))
end

macro rna_str(seq, flag)
    if flag == "s"
        return LongRNASeq(remove_newlines(seq))
    elseif flag == "d"
        return quote
            LongRNASeq($(remove_newlines(seq)))
        end
    end
    error("Invalid RNA flag: '$(flag)'")
end

macro rna_str(seq)
    return LongRNASeq(remove_newlines(seq))
end

macro aa_str(seq, flag)
    if flag == "s"
        return LongAminoAcidSeq(remove_newlines(seq))
    elseif flag == "d"
        return quote
            LongAminoAcidSeq($(remove_newlines(seq)))
        end
    end
    error("Invalid Amino Acid flag: '$(flag)'")
end

macro aa_str(seq)
    return LongAminoAcidSeq(remove_newlines(seq))
end

macro char_str(seq, flag)
    if flag == "s"
        return LongCharSeq(remove_newlines(seq))
    elseif flag == "d"
        return quote
            LongCharSeq($(remove_newlines(seq)))
        end
    end
    error("Invalid Char flag: '$(flag)'")
end

macro char_str(seq)
    return LongCharSeq(remove_newlines(seq))
end

ext: jl


text:
function MaintenanceSchedulingModel(data::MaintenanceSchedulingData, scenarios::Vector{<:MaintenanceSchedulingScenario}; kw...)
    return StochasticHydroModel("Maintenance scheduling", HydroModels.Day(), data, MaintenanceSchedulingModelDef, scenarios; kw...)
end

function MaintenanceSchedulingModel(data::MaintenanceSchedulingData, sampler::RecurrentMaintenanceSchedulingSampler, n::Integer; kw...)
    return StochasticHydroModel("Maintenance scheduling", HydroModels.Day(), data, MaintenanceSchedulingModelDef, sampler, n; kw...)
end

function MaintenanceSchedulingModelDef(horizon::Horizon, data::MaintenanceSchedulingData, indices::MaintenanceSchedulingIndices)
    stochasticmodel = @stochastic_model begin
        # First stage
        # ========================================================
        @stage 1 begin
            @parameters begin
                horizon = horizon
                indices = indices
                data = data
            end
            @unpack hours, plants, bids = indices
            @unpack hydrodata = data
            # Variables
            # ========================================================
            #@decision(model, maintenance_start[p in plants, t in hours], Bin)
            @decision(model, xᴵ[t in hours] >= 0)
            @decision(model, xᴰ[i in bids, t in hours] >= 0)
            @decision(model, maintenance_period[p in plants, t in hours], Bin)
            # Objectives
            # ========================================================
            # Dummy first-stage objective in order to use Max sense
            @objective(model, Max, 0)
            # Constraints
            # ========================================================
            # Maintenance period should be a consecutive period
            @constraint(model, maintenance_times[p in plants, t in hours],
                        maintenance_period[p,t] - (t > 2 ? maintenance_period[p,t-1] : 0) <= ((t + hydrodata[p].Mt - 1) <= num_hours(horizon) ? maintenance_period[p,t+hydrodata[p].Mt-1] : 0))
            # Ensure maintenance is finished
            @constraint(model, maintenance_finished[p in plants],
                        sum(maintenance_period[p,t] for t in hours) == hydrodata[p].Mt)
            # Increasing bid curve
            @constraint(model, bidcurve[i in bids[1:end-1], t in hours],
                xᴰ[i,t] <= xᴰ[i+1,t]
            )
            # Maximal bids
            @constraint(model, maxhourlybids[t in hours],
                        xᴵ[t] + xᴰ[bids[end],t] <= 2*sum(hydrodata[p].H̄ for p in plants)
                        )
        end
        # Second stage
        # =======================================================
        @stage 2 begin
            @parameters begin
                horizon = horizon
                indices = indices
                data = data
            end
            @unpack hours, plants, segments = indices
            @unpack hydrodata, bidlevels, reschedule = data
            @uncertain ρ Q̃ from ξ::MaintenanceSchedulingScenario
            V = local_inflows(Q̃, hydrodata.Qu)
            # Auxilliary functions
            ih(t) = begin
                idx = findlast(bidlevels[t] .<= ρ[t])
                return idx == nothing ? -1 : idx
            end
            interpolate(ρ, bidlevels, xᴰ, t) = begin
                lower = ((ρ[t] - bidlevels[t][ih(t)])/(bidlevels[t][ih(t)+1]-bidlevels[t][ih(t)]))*xᴰ[ih(t)+1,t]
                upper = ((bidlevels[t][ih(t)+1]-ρ[t])/(bidlevels[t][ih(t)+1]-bidlevels[t][ih(t)]))*xᴰ[ih(t),t]
                return lower + upper
            end
            # Variables
            # =======================================================
            # -------------------------------------------------------
            if reschedule
                @recourse(model, new_schedule[p in plants, t in hours], Bin)
            end
            @recourse(model, yᴴ[t in hours] >= 0)
            @recourse(model, y⁺[t in hours] >= 0)
            @recourse(model, y⁻[t in hours] >= 0)
            @recourse(model, 0 <= Q[p in plants, s in segments, t in hours] <= Q̄(hydrodata, p, s))
            @recourse(model, S[p in plants, t in hours] >= 0)
            @recourse(model, 0 <= M[p in plants, t in hours] <= hydrodata[p].M̄)
            @recourse(model, H[t in hours] >= 0)
            @variable(model, Qf[p in plants, t in hours] >= 0)
            @variable(model, Sf[p in plants, t in hours] >= 0)
            # Objectives
            # ========================================================
            # Net profit
            @expression(model, net_profit,
                        sum(ρ[t]*yᴴ[t]
                            for t in hours))
            # Intraday
            @expression(model, intraday,
                        sum(penalty(ξ,t)*y⁺[t] - reward(ξ,t)*y⁻[t]
                            for t in hours))
            # Define objective
            @objective(model, Max, net_profit - intraday)
            # Constraints
            # ========================================================
            if reschedule
                # Maintenance period should be a consecutive period
                @constraint(model, new_maintenance_times[p in plants, t in hours],
                            new_schedule[p,t] - (t > 2 ? new_schedule[p,t-1] : 0) <= ((t + hydrodata[p].Mt - 1) <= num_hours(horizon) ? new_schedule[p,t+hydrodata[p].Mt-1] : 0))
                # Ensure maintenance is finished
                @constraint(model, new_maintenance_finished[p in plants],
                            sum(new_schedule[p,t] for t in hours) == hydrodata[p].Mt)
                # New schedule can only differ by an hour
                @constraint(model, reschedule_constraint[p in plants, t in hours],
                            new_schedule[p,t] <= sum(maintenance_period[p,tt] for tt in max(1,t-1):1:min(num_hours(horizon),t+1)))
            end
            # Bid-dispatch links
            @constraint(model, hourlybids[t in hours],
                yᴴ[t] == interpolate(ρ, bidlevels, xᴰ, t) + xᴵ[t]
            )
            if reschedule
                # Pause production during new maintenance hours
                @constraint(model, pause_production[p in plants, s in segments, t in hours],
                            Q[p,s,t] <= (1 - new_schedule[p,t])*Q̄(hydrodata, p, s))
            else
                # Pause production during maintenance hours
                @constraint(model, pause_production[p in plants, s in segments, t in hours],
                            Q[p,s,t] <= (1 - maintenance_period[p,t])*Q̄(hydrodata, p, s))
            end
            # Hydrological balance
            @constraint(model, hydro_constraints[p in plants, t in hours],
                        # Previous reservoir content
                        M[p,t] == (t > 1 ? M[p,t-1] : hydrodata[p].M₀)
                        # Inflow
                        + sum(Qf[i,t] for i in intersect(hydrodata.Qu[p],plants))
                        + sum(Sf[i,t] for i in intersect(hydrodata.Su[p],plants))
                        # Local inflow
                        + V[p]
                        # Outflow
                        - sum(Q[p,s,t]
                              for s in segments)
                        - S[p,t]
                        )
            # Production
            @constraint(model, production[t in hours],
                        H[t] == sum(marginal_production(Resolution(1), μ(hydrodata, p, s)) * Q[p,s,t]
                                    for p in plants, s in segments)
                        )
            # Load balance
            @constraint(model, loadbalance[t in hours],
                        yᴴ[t] - H[t] == y⁺[t] - y⁻[t]
                        )
            # Water flow: Discharge + Spillage
            @constraint(model, discharge_flow_time[p in plants, t in hours],
                        Qf[p,t] == (t - water_flow_time(Resolution(1), hydrodata[p].Rq) > 0 ?
                        overflow(Resolution(1), hydrodata[p].Rq) * sum(Q[p,s,t-water_flow_time(Resolution(1), hydrodata[p].Rq)]
                                                                    for s in segments) : 0.0)
                        + (t - water_flow_time(Resolution(1), hydrodata[p].Rq) > 1 ?
                        historic_flow(Resolution(1), hydrodata[p].Rq)*sum(Q[p,s,t-(water_flow_time(Resolution(1), hydrodata[p].Rq)+1)]
                                                                       for s in segments) : 0.0))
            @constraint(model, spillage_flow_time[p in plants, t in hours],
                        Sf[p,t] == (t - water_flow_time(Resolution(1), hydrodata[p].Rs) > 0 ?
                        overflow(Resolution(1), hydrodata[p].Rs) * S[p,t-water_flow_time(Resolution(1), hydrodata[p].Rs)] : 0.0)
                        + (t - water_flow_time(Resolution(1), hydrodata[p].Rs) > 1 ?
                        historic_flow(Resolution(1), hydrodata[p].Rs)*S[p,t-(water_flow_time(Resolution(1), hydrodata[p].Rq)+1)] : 0.0))
        end
    end
    return stochasticmodel
end


text:
using DashBootstrapComponents

alert = html_div([
    dbc_button(
        "Toggle alert with fade",
        id = "alert-toggle-fade",
        className = "me-1",
        n_clicks = 0,
    ),
    dbc_button("Toggle alert without fade", id = "alert-toggle-no-fade", n_clicks = 0),
    html_hr(),
    dbc_alert(
        "Hello! I am an alert",
        id = "alert-fade",
        dismissable = true,
        is_open = true,
    ),
    dbc_alert(
        "Hello! I am an alert that doesn't fade in or out",
        id = "alert-no-fade",
        dismissable = true,
        fade = false,
        is_open = true,
    ),
]);

callback!(
    app,
    Output("alert-fade", "is_open"),
    Input("alert-toggle-fade", "n_clicks"),
    State("alert-fade", "is_open"),
) do n, is_open
    return n > 0 ? is_open == 0 : is_open
end;

callback!(
    app,
    Output("alert-no-fade", "is_open"),
    Input("alert-toggle-no-fade", "n_clicks"),
    State("alert-no-fade", "is_open"),
) do n, is_open
    return n > 0 ? is_open == 0 : is_open
end;

max_issues_repo_name: sthagen/dash-bootstrap-components

max_forks_repo_name: sthagen/dash-bootstrap-components


text:
#using SimpleGraphs, DrawSimpleGraphs, Plots

export KnightTourDrawing

"""
`KnightTourDrawing(r,c)` illustrates a Knight's tour of an r-by-c
chessboard returning `true` if the tour exists and `false` if not.
"""
function KnightTourDrawing(r::Int=6, c::Int=6)
    G = Knight(r,c)
    println("Searching for a Hamiltonian cycle in an $r-by-$c Knight's move graph")
    @time h = hamiltonian_cycle(G)
    println("Finished")

    if length(h)==0
        println("Sorry. This graph is not Hamiltonian")
        return false
    end

    T = vertex_type(G)
    H = SimpleGraph{T}()
    for v in G.V
        add!(H,v)
    end

    for k=1:NV(H)-1
        add!(H,h[k],h[k+1])
    end

    add!(H,h[1],h[end])

    xy = getxy(H)

    for v in H.V
        xy[v] = collect(v)
    end

    embed(H,xy)

    draw(H)

    for a=0:c
        plot!( [0.5, r+0.5], [a+0.5, a+0.5], color="black",
                linestyle=:dash)
    end

    for b=0:r
        plot!( [b+0.5, b+0.5], [0.5, c+0.5], color="black",
            linestyle=:dash)
    end

    finish()

end


text:
function extendedEuclideanAlgorithm(a, b)
    if b == 0
        return (a, 1, 0)
    end
    gcd, x1, y1 = extendedEuclideanAlgorithm(b, a % b)
    x = y1
    y = x1 - floor(a / b) * y1
    return gcd, x, y
end

max_stars_repo_path: Utility Functions/Algorithms/EEA.jl

max_issues_repo_path: Utility Functions/Algorithms/EEA.jl

max_forks_repo_path: Utility Functions/Algorithms/EEA.jl


text:
using ApproxFun, LinearAlgebra, Plots

# In this example, we solve the heat equation with left Neumann and
# right Dirichlet boundary conditions.
# To allow for a solution through matrix exponentiation, we approximate
# the initial condition with a basis that automatically constructs
# even and odd extensions on the left and right boundaries respectively. (Method of images)

n = 100
xlim = 10
xarray = (chebyshevpoints(n) .+ 1) .* xlim/2 # Chebyshev points on 0..xlim
r = 1.0 # right boundary value (left is assumed to be zero)

S = CosSpace(0..4*xlim)

u₀(x) = atan(x)*(π + atan(x-9) + atan(5-x))/π^2 - r # subtract by `r` to homogenise the right BC
   plot(xarray, u₀)
v = u₀.(xarray) # values to use in fitting

m = div(n,2) # m << n for regularisation

# Create a Vandermonde matrix by evaluating the basis at the grid:
# We ensure the basis satisfies the boundary conditions by using
# the entries corresponding to {cos(x), cos(3x), cos(5x), ...}.
V = zeros(n, m)
for k = 1:m
   V[:,k] = Fun(S,[zeros(2*k-1);1]).(xarray)
end

c₀ = zeros(2*m)
c₀[2:2:end] = V\v # do the fit

f = Fun(S, c₀) # Likely not a good approximation due to boundary discontinuities, but high frequencies will disappear quickly anyway
   plot([xarray.+10; xarray; xarray.-10], f, xlims=(-5, 15))
   scatter!(xarray, u₀, markersize=0.2)

L = Derivative(S, 2)
   L = Matrix(L[1:2m,1:2m])

@manipulate for T=[zeros(5); 0.0:0.01:1]
   u_t = Fun(S, exp(T*L)*c₀) + r # calculate solution and add back homogenisation term
   plot(-0:0.05:10, u_t, ylims=(0,1), legend=:none)
end

@gif for T=[zeros(5); 0.0:0.5:50]
   u_t = Fun(S, exp(T*L)*c₀) + r # calculate solution and add back homogenisation term
   plot(-0:0.05:10, u_t, ylims=(0,1), legend=:none)
end

max_stars_repo_path: PDEs/Heat equation image method.jl

max_stars_repo_name: JuliaApproximation/ApproxFunExamples

max_issues_repo_path: PDEs/Heat equation image method.jl

max_issues_repo_name: JuliaApproximation/ApproxFunExamples

max_forks_repo_path: PDEs/Heat equation image method.jl

max_forks_repo_name: JuliaApproximation/ApproxFunExamples


text:
# Depends on test_syllablize to run
info("Testing summary statistics...")

import Birdsong: samplerate, windowstep, lowharmonic, windowlength, harmonic2hz, timeslice2sec, pitch_pool, fit, Histogram

#test harmonic to frequency conversion
@test harmonic2hz(5, 5, 128, 1280) == 100
@test harmonic2hz(10, 20, 200, 1000) == 150

#Test conversion of time slices to seconds
@test timeslice2sec(10) == 10*windowstep/samplerate
@test timeslice2sec(10, 2, 1000) == 10/500

#Test songlength
@test songlength(syllables) == 13*windowstep/samplerate
@test songlength(syllables, 1, 1) == 13

#Test extraction of frequency pool
@test pitch_pool(syllables) == harmonic2hz.(vcat(map(s->s.harmonics, syllables)...))

#Test min and max pitch
@test minpitch(syllables) ==  (2+lowharmonic) * samplerate/windowlength
@test maxpitch(syllables) == (5+lowharmonic) * samplerate/windowlength

#TODO: write tests for pitch_distribution and sdpitch

#Test computing pitch standard deviation
@test SDpitch(syllables) == std(pitch_pool(syllables))

#Test computing a histogram of pitches
@test pitch_distribution(syllables) == fit(Histogram, pitch_pool(syllables))

#Test psong
@test psong(syllables, 1, 1) == 5/13

#Test syllable rate
@test syllrate(syllables) == 3/songlength(syllables)

#Test bandwidth computation
@test bandlimits(syllables) == (minpitch(syllables), maxpitch(syllables))


text:
# Automatically generated using Clang.jl

# Skipping MacroDefinition: AMGX_API __attribute__ ( ( visibility ( "default" ) ) )
# Skipping MacroDefinition: AMGX_SAFE_CALL ( rc ) \
#{ AMGX_RC err ; char msg [ 4096 ] ; switch ( err = ( rc ) ) { case AMGX_RC_OK : break ; default : fprintf ( stderr , "AMGX ERROR: file %s line %6d\n" , __FILE__ , __LINE__ ) ; AMGX_get_error_string ( err , msg , 4096 ) ; fprintf ( stderr , "AMGX ERROR: %s\n" , msg ) ; AMGX_abort ( NULL , 1 ) ; break ; } \
#}

@cenum AMGX_FLAGS::UInt32 begin
    SOLVE_STATS = 1
    GRID_STATS = 2
    CONFIG = 4
    PROFILE_STATS = 8
    VISDATA = 16
    RESIDUAL_HISTORY = 32
end

@cenum AMGX_RC::UInt32 begin
    AMGX_RC_OK = 0
    AMGX_RC_BAD_PARAMETERS = 1
    AMGX_RC_UNKNOWN = 2
    AMGX_RC_NOT_SUPPORTED_TARGET = 3
    AMGX_RC_NOT_SUPPORTED_BLOCKSIZE = 4
    AMGX_RC_CUDA_FAILURE = 5
    AMGX_RC_THRUST_FAILURE = 6
    AMGX_RC_NO_MEMORY = 7
    AMGX_RC_IO_ERROR = 8
    AMGX_RC_BAD_MODE = 9
    AMGX_RC_CORE = 10
    AMGX_RC_PLUGIN = 11
    AMGX_RC_BAD_CONFIGURATION = 12
    AMGX_RC_NOT_IMPLEMENTED = 13
    AMGX_RC_LICENSE_NOT_FOUND = 14
    AMGX_RC_INTERNAL = 15
end

@cenum AMGX_SOLVE_STATUS::UInt32 begin
    AMGX_SOLVE_SUCCESS = 0
    AMGX_SOLVE_FAILED = 1
    AMGX_SOLVE_DIVERGED = 2
    AMGX_SOLVE_NOT_CONVERGED = 2
end

@cenum AMGX_GET_PARAMS_DESC_FLAG::UInt32 begin
    AMGX_GET_PARAMS_DESC_JSON_TO_FILE = 0
    AMGX_GET_PARAMS_DESC_JSON_TO_STRING = 1
    AMGX_GET_PARAMS_DESC_TEXT_TO_FILE = 2
    AMGX_GET_PARAMS_DESC_TEXT_TO_STRING = 3
end

@cenum AMGX_DIST_PARTITION_INFO::UInt32 begin
    AMGX_DIST_PARTITION_VECTOR = 0
    AMGX_DIST_PARTITION_OFFSETS = 1
end

const AMGX_print_callback = Ptr{Cvoid}

struct AMGX_config_handle_struct
    AMGX_config_handle_dummy::UInt8
end

const AMGX_config_handle = Ptr{AMGX_config_handle_struct}

struct AMGX_resources_handle_struct
    AMGX_resources_handle_dummy::UInt8
end

const AMGX_resources_handle = Ptr{AMGX_resources_handle_struct}

struct AMGX_matrix_handle_struct
    AMGX_matrix_handle_dummy::UInt8
end

const AMGX_matrix_handle = Ptr{AMGX_matrix_handle_struct}

struct AMGX_vector_handle_struct
    AMGX_vector_handle_dummy::UInt8
end

const AMGX_vector_handle = Ptr{AMGX_vector_handle_struct}

struct AMGX_solver_handle_struct
    AMGX_solver_handle_dummy::UInt8
end

const AMGX_solver_handle = Ptr{AMGX_solver_handle_struct}

struct AMGX_distribution_handle_struct
    AMGX_distribution_handle_dummy::UInt8
end

const AMGX_distribution_handle = Ptr{AMGX_distribution_handle_struct}

# Skipping MacroDefinition: AMGX_ASSEMBLE_MODE ( memSpace , vecPrec , matPrec , indPrec ) \
#( memSpace * AMGX_MemorySpaceBase + vecPrec * AMGX_VecPrecisionBase + matPrec * AMGX_MatPrecisionBase + indPrec * AMGX_IndPrecisionBase \
#)
# Skipping MacroDefinition: AMGX_GET_MODE_VAL ( type , mode ) ( ( type ) ( ( ( mode ) / type ## Base ) % type ## Size ) )
# Skipping MacroDefinition: AMGX_SET_MODE_VAL ( type , mode , value ) ( ( AMGX_Mode ) ( ( mode ) + ( ( value ) - AMGX_GET_MODE_VAL ( type , mode ) ) * type ## Base ) )
# Skipping MacroDefinition: AMGX_FORALL_BUILDS_HOST ( codeLineMacro ) codeLineMacro ( AMGX_mode_hDDI ) codeLineMacro ( AMGX_mode_hDFI ) codeLineMacro ( AMGX_mode_hFFI )
# Skipping MacroDefinition: AMGX_FORINTVEC_BUILDS_HOST ( codeLineMacro ) codeLineMacro ( AMGX_mode_hIDI ) codeLineMacro ( AMGX_mode_hIFI )
# Skipping MacroDefinition: AMGX_FORALL_BUILDS_DEVICE ( codeLineMacro ) codeLineMacro ( AMGX_mode_dDDI ) codeLineMacro ( AMGX_mode_dDFI ) codeLineMacro ( AMGX_mode_dFFI )
# Skipping MacroDefinition: AMGX_FORINTVEC_BUILDS_DEVICE ( codeLineMacro ) codeLineMacro ( AMGX_mode_dIDI ) codeLineMacro ( AMGX_mode_dIFI )
# Skipping MacroDefinition: AMGX_FORCOMPLEX_BUILDS_DEVICE ( codeLineMacro ) codeLineMacro ( AMGX_mode_dZZI ) codeLineMacro ( AMGX_mode_dZCI ) codeLineMacro ( AMGX_mode_dCCI )
# Skipping MacroDefinition: AMGX_FORCOMPLEX_BUILDS_HOST ( codeLineMacro ) codeLineMacro ( AMGX_mode_hZZI ) codeLineMacro ( AMGX_mode_hZCI ) codeLineMacro ( AMGX_mode_hCCI )
# Skipping MacroDefinition: AMGX_FORALL_BUILDS ( codeLineMacro ) AMGX_FORALL_BUILDS_HOST ( codeLineMacro ) AMGX_FORALL_BUILDS_DEVICE ( codeLineMacro )
# Skipping MacroDefinition: AMGX_FORCOMPLEX_BUILDS ( codeLineMacro ) AMGX_FORCOMPLEX_BUILDS_DEVICE ( codeLineMacro ) AMGX_FORCOMPLEX_BUILDS_HOST ( codeLineMacro )
# Skipping MacroDefinition: AMGX_FORINTVEC_BUILDS ( codeLineMacro ) AMGX_FORINTVEC_BUILDS_HOST ( codeLineMacro ) AMGX_FORINTVEC_BUILDS_DEVICE ( codeLineMacro )

@cenum AMGX_MemorySpace::UInt32 begin
    AMGX_host = 0
    AMGX_device = 1
    AMGX_memorySpaceNum = 16
end

@cenum AMGX_ScalarPrecision::UInt32 begin
    AMGX_double = 0
    AMGX_float = 1
    AMGX_int = 2
    AMGX_doublecomplex = 3
    AMGX_complex = 4
    AMGX_usint = 5
    AMGX_uint = 6
    AMGX_uint64 = 7
    AMGX_int64 = 8
    AMGX_bool = 9
    AMGX_scalarPrecisionNum = 16
end

@cenum AMGX_VecPrecision::UInt32 begin
    AMGX_vecDouble = 0
    AMGX_vecFloat = 1
    AMGX_vecDoubleComplex = 3
    AMGX_vecComplex = 4
    AMGX_vecInt = 2
    AMGX_vecUSInt = 5
    AMGX_vecUInt = 6
    AMGX_vecUInt64 = 7
    AMGX_vecInt64 = 8
    AMGX_vecBool = 9
    AMGX_vecPrecisionNum = 16
    AMGX_VecPrecisionInst = 17
end

@cenum AMGX_MatPrecision::UInt32 begin
    AMGX_matDouble = 0
    AMGX_matFloat = 1
    AMGX_matDoubleComplex = 3
    AMGX_matComplex = 4
    AMGX_matInt = 2
    AMGX_matPrecisionNum = 16
    AMGX_MatPrecisionInst = 17
end

@cenum AMGX_IndPrecision::UInt32 begin
    AMGX_indInt = 2
    AMGX_indInt64 = 8
    AMGX_indPrecisionNum = 16
    AMGX_IndPrecisionInst = 17
end

@cenum AMGX_ModeNums::UInt32 begin
    AMGX_MemorySpaceBase = 1
    AMGX_MemorySpaceSize = 16
    AMGX_VecPrecisionBase = 16
    AMGX_VecPrecisionSize = 16
    AMGX_MatPrecisionBase = 256
    AMGX_MatPrecisionSize = 16
    AMGX_IndPrecisionBase = 4096
    AMGX_IndPrecisionSize = 16
end

@cenum AMGX_Mode::Int32 begin
    AMGX_unset = -1
    AMGX_modeRange = 65536
    AMGX_mode_hDDI = 8192
    AMGX_mode_hDFI = 8448
    AMGX_mode_hFFI = 8464
    AMGX_mode_dDDI = 8193
    AMGX_mode_dDFI = 8449
    AMGX_mode_dFFI = 8465
    AMGX_mode_hIDI = 8224
    AMGX_mode_hIFI = 8480
    AMGX_mode_dIDI = 8225
    AMGX_mode_dIFI = 8481
    AMGX_mode_hZZI = 9008
    AMGX_mode_hZCI = 9264
    AMGX_mode_hCCI = 9280
    AMGX_mode_dZZI = 9009
    AMGX_mode_dZCI = 9265
    AMGX_mode_dCCI = 9281
    AMGX_modeNum = 10
    AMGX_ModeInst = 11
end


text:
function t_pipe_creation()

N = 10	# variables
M = 25  # samples
A = rand(N,M)
A0 = j4pr.datacell(A)
A1 = j4pr.datacell(A, round.(rand(M)))
A2 = j4pr.datacell(A, round.(rand(2,M)))

W1 = j4pr.ohenc("binary")
W2 = j4pr.scaler!(Dict(1=>"mean"))
W3 = j4pr.functioncell((x)->x)

PT = [W1;W2]
PP=[W1 W2]
PS = W1+W2

# Simple cell checks
#print("Type checks for function cells before passing data... ")
Test.@test W1 isa j4pr.CellFunU && !(W1 isa j4pr.CellFunF) && !(W1 isa j4pr.CellFunT)
Test.@test W2 isa j4pr.CellFunU && !(W2 isa j4pr.CellFunF) && !(W2 isa j4pr.CellFunT)
Test.@test W3 isa j4pr.CellFunF && !(W3 isa j4pr.CellFunU) && !(W3 isa j4pr.CellFunT)

#println("PASSED")

#print("Type checks for function cells after passing data... ")
tmp = A0 |> W1
Test.@test tmp isa j4pr.CellFunT && !(tmp isa j4pr.CellFunF) && !(tmp isa j4pr.CellFunU)
tmp = A0 |> W2
Test.@test tmp isa j4pr.CellFunT && !(tmp isa j4pr.CellFunF) && !(tmp isa j4pr.CellFunU)
Test.@test A0 |> W3 isa j4pr.CellDataU
Test.@test A1 |> W3 isa j4pr.CellDataL
Test.@test A2 |> W3 isa j4pr.CellDataLL
#println("PASSED")

# Simple pipe checks
#print("Type checks for [simple] pipes before passing data... ")
Test.@test PT isa j4pr.PipeStackedU && !(PT isa j4pr.PipeStackedF) && !(PT isa j4pr.PipeStackedT)
Test.@test PP isa j4pr.PipeParallelU && !(PP isa j4pr.PipeParallelF) && !(PP isa j4pr.PipeParallelT)
Test.@test PS isa j4pr.PipeSerialU && !(PS isa j4pr.PipeSerialF) && !(PS isa j4pr.PipeSerialT)
#println("PASSED")

#print("Type checks for [simple] pipes after passing data... ")
tmp = A0 |> PT
Test.@test tmp isa j4pr.PipeStackedT && !(tmp isa j4pr.PipeStackedF) && !(tmp isa j4pr.PipeStackedU)
tmp = [A0|>W1; A1|>W2]
Test.@test tmp isa j4pr.PipeStackedT && !(tmp isa j4pr.PipeStackedF) && !(tmp isa j4pr.PipeStackedU)
tmp = A0 |> PP
Test.@test tmp isa j4pr.PipeParallelT && !(tmp isa j4pr.PipeParallelF) && !(tmp isa j4pr.PipeParallelU)
tmp = [A0|>W1 A1|>W2]
Test.@test tmp isa j4pr.PipeParallelT && !(tmp isa j4pr.PipeParallelF) && !(tmp isa j4pr.PipeParallelU)
tmp = A0 |> PS
Test.@test tmp isa j4pr.PipeSerialT && !(tmp isa j4pr.PipeSerialF) && !(tmp isa j4pr.PipeSerialU)
tmp = (A0|>W1)+(A0|>W2)
Test.@test tmp isa j4pr.PipeSerialT && !(tmp isa j4pr.PipeSerialF) && !(tmp isa j4pr.PipeSerialU)
#println("PASSED")

# Generic pipe checks
#print("Type checks for [generic] pipes before passing data... ")
PTG = [W2+W1;W2;W3]
PPG = [W2+W1 W2 W1]
PSG = (W2+W1)+[W2;W1]
Test.@test PTG isa j4pr.PipeStacked && !(PTG isa j4pr.PipeParallel) && !(PTG isa j4pr.PipeSerial)
Test.@test PPG isa j4pr.PipeParallel && !(PPG isa j4pr.PipeStacked) && !(PPG isa j4pr.PipeSerial)
Test.@test PSG isa j4pr.PipeSerial && !(PSG isa j4pr.PipeStacked) && !(PSG isa j4pr.PipeParallel)
tmp = [[W1;W2;W3]+W3 W1 [W1 W2]]
Test.@test tmp isa j4pr.PipeParallel && !(tmp isa j4pr.PipeStacked) && !(tmp isa j4pr.PipeSerial)
#println("PASSED")

#print("Type checks for [generic] pipes before passing data... ")
Test.@test A0 |> (A0 |> PTG) isa j4pr.CellDataU
Test.@test A0 |> PPG isa j4pr.PipeParallel
Test.@test A0 |> (A0|> PPG)  isa j4pr.CellDataU
Test.@test A0 |> (A0 |> PSG) isa j4pr.PipeSerial
Test.@test A0|> (A0 |> (A0 |> PSG)) isa j4pr.CellDataU
#println("PASSED")

end


text:
function mul_analytic!(τ::Array{R,1}, dx1::R, ie1::Int, xs1::Int) where {R <: AbstractFloat}
    for i1 = 1:ie1
        @inbounds τ[i1] *= sqrt(sum(((i1-xs1)*dx1)^2))
    end
end

function mul_analytic!(τ::Array{R,2}, dx1::R, dx2::R, ie1::Int, ie2::Int, xs1::Int, xs2::Int) where {R <: AbstractFloat}
    for i2 = 1:ie2
        for i1 = 1:ie1
            @inbounds τ[i1,i2] *= sqrt(sum(((i1-xs1)*dx1)^2+((i2-xs2)*dx2)^2))
        end
    end
end

function mul_analytic!(τ::Array{R,3}, dx1::R, dx2::R, dx3::R, ie1::Int, ie2::Int, ie3::Int, xs1::Int, xs2::Int, xs3::Int) where {R <: AbstractFloat}
    for i3 = 1:ie3
        for i2 = 1:ie2
            for i1 = 1:ie1
                @inbounds τ[i1,i2,i3] *= sqrt(sum(((i1-xs1)*dx1)^2+((i2-xs2)*dx2)^2+((i3-xs3)*dx3)^2))
            end
        end
    end
end

function grad_analytic(τ0::Array{R,1}, dx1::R, ie1::Int, xs1::Int) where {R <: AbstractFloat}
    ∇τ0 = [ones(size(τ0))]
    for i1 = 1:ie1
        @inbounds ∇τ0[1][i1] = dx1*(i1-xs1)/τ0[i1]
    end
    #set terms at source
    ∇τ0[1][xs1] = one(R)
    ∇τ0
end

function grad_analytic(τ0::Array{R,2}, dx1::R, dx2::R, ie1::Int, ie2::Int, xs1::Int, xs2::Int) where {R <: AbstractFloat}
    ∇τ0 = [ones(size(τ0)), ones(size(τ0))]
    for i2 = 1:ie2
        for i1 = 1:ie1
            @inbounds ∇τ0[1][i1,i2] = dx1*(i1-xs1)/τ0[i1,i2]
            @inbounds ∇τ0[2][i1,i2] = dx2*(i2-xs2)/τ0[i1,i2]
        end
    end
    ∇τ0[1][xs1, xs2] = convert(R, 1/sqrt(2))
    ∇τ0[2][xs1, xs2] = convert(R, 1/sqrt(2))
    ∇τ0
end

function grad_analytic(τ0::Array{R,3}, dx1::R, dx2::R, dx3::R, ie1::Int, ie2::Int, ie3::Int, xs1::Int, xs2::Int, xs3::Int) where {R <: AbstractFloat}
    ∇τ0 = [ones(size(τ0)), ones(size(τ0)), ones(size(τ0))]
    for i3 = 1:ie3
        for i2 = 1:ie2
            for i1 = 1:ie1
                @inbounds ∇τ0[1][i1,i2,i3] = dx1*(i1-xs1)/τ0[i1,i2,i3]
                @inbounds ∇τ0[2][i1,i2,i3] = dx2*(i2-xs2)/τ0[i1,i2,i3]
                @inbounds ∇τ0[3][i1,i2,i3] = dx3*(i3-xs3)/τ0[i1,i2,i3]
            end
        end
    end
    ∇τ0[1][xs1, xs2, xs3] = convert(R, 1/sqrt(3))
    ∇τ0[2][xs1, xs2, xs3] = convert(R, 1/sqrt(3))
    ∇τ0[3][xs1, xs2, xs3] = convert(R, 1/sqrt(3))
    ∇τ0
end


text:
#=
This file is auto-generated. Do not edit.
=#
"""
    mutable struct CombinedVIwithVZ <: VSControl
        kpv::Float64
        kiv::Float64
        kffv::Float64
        rv::Float64
        lv::Float64
        kpc::Float64
        kic::Float64
        kffi::Float64
        ωad::Float64
        kad::Float64
        ext::Dict{String, Any}
        states::Vector{Symbol}
        n_states::Int64
        internal::InfrastructureSystemsInternal
    end

Parameters of an inner loop controller using virtual impedance, voltage controller and current controller.

# Arguments
- `kpv::Float64`: voltage controller proportional gain, validation range: (0, nothing)
- `kiv::Float64`: voltage controller integral gain, validation range: (0, nothing)
- `kffv::Float64`: Binary variable to enable feed-forward gain of voltage., validation range: (0, nothing)
- `rv::Float64`: virtual resistance, validation range: (0, nothing)
- `lv::Float64`: virtual inductance, validation range: (0, nothing)
- `kpc::Float64`: current controller proportional gain, validation range: (0, nothing)
- `kic::Float64`: current controller integral gain, validation range: (0, nothing)
- `kffi::Float64`: Binary variable to enable feed-forward gain of current, validation range: (0, nothing)
- `ωad::Float64`: active damping filter cutoff frequency (rad/sec), validation range: (0, nothing)
- `kad::Float64`: active damping gain, validation range: (0, nothing)
- `ext::Dict{String, Any}`
- `states::Vector{Symbol}`
- `n_states::Int64`
- `internal::InfrastructureSystemsInternal`: power system internal reference, do not modify
"""
mutable struct CombinedVIwithVZ <: VSControl
    "voltage controller proportional gain"
    kpv::Float64
    "voltage controller integral gain"
    kiv::Float64
    "Binary variable to enable feed-forward gain of voltage."
    kffv::Float64
    "virtual resistance"
    rv::Float64
    "virtual inductance"
    lv::Float64
    "current controller proportional gain"
    kpc::Float64
    "current controller integral gain"
    kic::Float64
    "Binary variable to enable feed-forward gain of current"
    kffi::Float64
    "active damping filter cutoff frequency (rad/sec)"
    ωad::Float64
    "active damping gain"
    kad::Float64
    ext::Dict{String, Any}
    states::Vector{Symbol}
    n_states::Int64
    "power system internal reference, do not modify"
    internal::InfrastructureSystemsInternal
end

function CombinedVIwithVZ(kpv, kiv, kffv, rv, lv, kpc, kic, kffi, ωad, kad, ext=Dict{String, Any}(), )
    CombinedVIwithVZ(kpv, kiv, kffv, rv, lv, kpc, kic, kffi, ωad, kad, ext, [:ξ_d, :ξ_q, :γ_d, :γ_q, :ϕ_d, :ϕ_q], 6, InfrastructureSystemsInternal(), )
end

function CombinedVIwithVZ(; kpv, kiv, kffv, rv, lv, kpc, kic, kffi, ωad, kad, ext=Dict{String, Any}(), )
    CombinedVIwithVZ(kpv, kiv, kffv, rv, lv, kpc, kic, kffi, ωad, kad, ext, )
end

# Constructor for demo purposes; non-functional.
function CombinedVIwithVZ(::Nothing)
    CombinedVIwithVZ(;
        kpv=0,
        kiv=0,
        kffv=0,
        rv=0,
        lv=0,
        kpc=0,
        kic=0,
        kffi=0,
        ωad=0,
        kad=0,
        ext=Dict{String, Any}(),
    )
end

"""Get CombinedVIwithVZ kpv."""
get_kpv(value::CombinedVIwithVZ) = value.kpv
"""Get CombinedVIwithVZ kiv."""
get_kiv(value::CombinedVIwithVZ) = value.kiv
"""Get CombinedVIwithVZ kffv."""
get_kffv(value::CombinedVIwithVZ) = value.kffv
"""Get CombinedVIwithVZ rv."""
get_rv(value::CombinedVIwithVZ) = value.rv
"""Get CombinedVIwithVZ lv."""
get_lv(value::CombinedVIwithVZ) = value.lv
"""Get CombinedVIwithVZ kpc."""
get_kpc(value::CombinedVIwithVZ) = value.kpc
"""Get CombinedVIwithVZ kic."""
get_kic(value::CombinedVIwithVZ) = value.kic
"""Get CombinedVIwithVZ kffi."""
get_kffi(value::CombinedVIwithVZ) = value.kffi
"""Get CombinedVIwithVZ ωad."""
get_ωad(value::CombinedVIwithVZ) = value.ωad
"""Get CombinedVIwithVZ kad."""
get_kad(value::CombinedVIwithVZ) = value.kad
"""Get CombinedVIwithVZ ext."""
get_ext(value::CombinedVIwithVZ) = value.ext
"""Get CombinedVIwithVZ states."""
get_states(value::CombinedVIwithVZ) = value.states
"""Get CombinedVIwithVZ n_states."""
get_n_states(value::CombinedVIwithVZ) = value.n_states
"""Get CombinedVIwithVZ internal."""
get_internal(value::CombinedVIwithVZ) = value.internal


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder

name = "libglvnd"
version = v"1.1.0"

# Collection of sources required to build libglvnd
sources = [
    "https://github.com/NVIDIA/libglvnd/archive/v1.1.0.tar.gz" =>
    "49aebc4eccebd6baffc53852a15c9f76433dd57ab593e44ad5ba5f0c20c63259",

]

# Bash recipe for building across all platforms
script = raw"""
cd $WORKSPACE/srcdir
cd libglvnd-1.1.0/
apk add  libx11-dev libxext-dev glproto
./autogen.sh
CFLAGS=-I/usr/include LDFLAGS=-L/usr/lib ./configure --prefix=$prefix --host=$target
make -j16
make install

"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = [
    Linux(:x86_64, libc=:glibc),
    Linux(:x86_64, libc=:musl)
]

# The products that we will ensure are always built
products(prefix) = [
    LibraryProduct(prefix, "libOpenGL", :libopengl),
    LibraryProduct(prefix, "libGLESv2", :libgles2),
    LibraryProduct(prefix, "libGL", :libgl),
    LibraryProduct(prefix, "libGLESv1_CM", :libglesv1),
    LibraryProduct(prefix, "libGLX", :libglx),
    LibraryProduct(prefix, "libGLdispatch", :libgldispatch),
    LibraryProduct(prefix, "libEGL", :libegl)
]

# Dependencies that must be installed before this package can be built
dependencies = [

]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies)

max_stars_repo_name: barche/libglvndbuilder

max_issues_repo_name: barche/libglvndbuilder

max_forks_repo_name: barche/libglvndbuilder


max_stars_repo_name: gabriel-doriath-dohler/pjulia

max_issues_repo_name: gabriel-doriath-dohler/pjulia

max_forks_repo_name: gabriel-doriath-dohler/pjulia


text:
##############################################################################
#  function for conversion to pdf
##############################################################################

"""
Initializes `wkhtmltopdf` in graphics less mode `pdf_init(0)` or not
`pdf_init(1)`
"""
function pdf_init(usegraphics::Int)
  ccall((:wkhtmltopdf_init, libwkhtml),
        Int, (Int,), usegraphics)
end

"""
Closes `wkhtmltopdf`
"""
function pdf_deinit()
  ccall((:wkhtmltopdf_deinit, libwkhtml),
        Int, ())
end

### Global settings ###

"""
Sets the output parameters by passing pairs `"property" => "values"` (both should be String).

example:
```julia
ps = PdfSettings("out" => "/tmp/example.pdf",
                 "orientation" => "Landscape")

```

Parameters (see https://wkhtmltopdf.org/libwkhtmltox/pagesettings.html#pagePdfGlobal) :

  - *size.pageSize* The paper size of the output document, e.g. "A4".
  - *size.width* The with of the output document, e.g. "4cm".
  - *size.height* The height of the output document, e.g. "12in".
  - *orientation* The orientation of the output document, must be either "Landscape" or "Portrait".
  - *colorMode* Should the output be printed in color or gray scale, must be either "Color" or "Grayscale"
  - *resolution* Most likely has no effect.
  - *dpi* What dpi should we use when printing, e.g. "80".
  - *pageOffset* A number that is added to all page numbers when printing headers, footers and table of content.
  - *copies* How many copies should we print?. e.g. "2".
  - *collate* Should the copies be collated? Must be either "true" or "false".
  - *outline* Should a outline (table of content in the sidebar) be generated and put into the PDF? Must be either "true" or false".
  - *outlineDepth* The maximal depth of the outline, e.g. "4".
  - *dumpOutline* If not set to the empty string a XML representation of the outline is dumped to this file.
  - *out* The path of the output file, if "-" output is sent to stdout, if empty the output is stored in a buffer.
  - *documentTitle* The title of the PDF document.
  - *useCompression* Should we use loss less compression when creating the pdf file? Must be either "true" or "false".
  - *margin.top* Size of the top margin, e.g. "2cm"
  - *margin.bottom* Size of the bottom margin, e.g. "2cm"
  - *margin.left* Size of the left margin, e.g. "2cm"
  - *margin.right* Size of the right margin, e.g. "2cm"
  - *imageDPI* The maximal DPI to use for images in the pdf document.
  - *imageQuality* The jpeg compression factor to use when producing the pdf document, e.g. "92".
  - *load.cookieJar* Path of file used to load and store cookies.

"""
type PdfSettings
  ptr::Ptr{GlobalSettings}
end

# 0 arg case
PdfSettings() = PdfSettings(pdf_create_global_settings())

# >= 1 case
function PdfSettings(p1::Pair{String,String}, args...)
  ptr = pdf_create_global_settings()

  pdf_set_global_setting(ptr, p1.first, p1.second)
  for p in args
    isa(p, Pair{String,String}) || error("argument $p is not Pair{String,String}")
    pdf_set_global_setting(ptr, p.first, p.second)
  end

  PdfSettings(ptr)
end

function setindex!(settings::PdfSettings, value::String, property::String)
  pdf_set_global_setting(settings.ptr, property, value)
end

function getindex(settings::PdfSettings, property::String)
  pdf_get_global_setting(settings.ptr, property)
end

function pdf_create_global_settings()
  ccall((:wkhtmltopdf_create_global_settings, libwkhtml),
        Ptr{GlobalSettings}, ())
end

function pdf_get_global_setting(gs::Ptr{GlobalSettings}, property::String)
  cval = zeros(UInt8, 100)
  ccall((:wkhtmltopdf_get_global_setting, libwkhtml),
        Int,
        (Ptr{GlobalSettings}, Cstring, Cstring, Int),
        gs, convert(Cstring, pointer(property)),
            convert(Cstring, pointer(cval)), sizeof(cval)-1 )
  unsafe_string(pointer(cval))
end

function pdf_set_global_setting(gs::Ptr{GlobalSettings}, property::String, value::String)
  ccall((:wkhtmltopdf_set_global_setting, libwkhtml),
        Int,
        (Ptr{GlobalSettings}, Cstring, Cstring),
        gs,
        convert(Cstring, pointer(property)),
        convert(Cstring, pointer(value)) )
end

### Object settings ###

"""
Sets the object to be converted parameters by passing pairs `"property" => "values"` (both should be String).

example:
```julia
ps = PdfObject("out" => "page" => "c:/temp/example.html")
```

## Parameters (see https://wkhtmltopdf.org/libwkhtmltox/pagesettings.html#pagePdfGlobal) :

- **toc.useDottedLines** Should we use a dotted line when creating a table of content? Must be either "true" or "false".
- **toc.captionText** The caption to use when creating a table of content.
- **toc.forwardLinks** Should we create links from the table of content into the actual content? Must be either "true or "false.
- **toc.backLinks** Should we link back from the content to this table of content.
- **toc.indentation** The indentation used for every table of content level, e.g. "2em".
- **toc.fontScale** How much should we scale down the font for every toc level? E.g. "0.8"
- **page** The URL or path of the web page to convert, if "-" input is read from stdin.
- **header.\*** Header specific settings see Header and footer settings.
- **footer.\*** Footer specific settings see Header and footer settings.
- **useExternalLinks** Should external links in the HTML document be converted into external pdf links? Must be either "true" or "false.
- **useLocalLinks** Should internal links in the HTML document be converted into pdf references? Must be either "true" or "false"
- **replacements** TODO
- **produceForms** Should we turn HTML forms into PDF forms? Must be either "true" or file".
- **load.\*** Page specific settings related to loading content, see Object Specific loading settings.
- **web.\*** See Web page specific settings.
- **includeInOutline** Should the sections from this document be included in the outline and table of content?
- **pagesCount** Should we count the pages of this document, in the counter used for TOC, headers and footers?
- **tocXsl** If not empty this object is a table of content object, "page" is ignored and this xsl style sheet is used to convert the outline XML into a table of content.

##Web page specific settings

- **web.background** Should we print the background? Must be either "true" or "false".
- **web.loadImages** Should we load images? Must be either "true" or "false".
- **web.enableJavascript** Should we enable javascript? Must be either "true" or "false".
- **web.enableIntelligentShrinking** Should we enable intelligent shrinkng to fit more content on one page? Must be either "true" or "false". Has no effect for wkhtmltoimage.
- **web.minimumFontSize** The minimum font size allowed. E.g. "9"
- **web.printMediaType** Should the content be printed using the print media type instead of the screen media type. Must be either "true" or "false". Has no effect for wkhtmltoimage.
- **web.defaultEncoding** What encoding should we guess content is using if they do not specify it properly? E.g. "utf-8"
- **web.userStyleSheet** Url er path to a user specified style sheet.
- **web.enablePlugins** Should we enable NS plugins, must be either "true" or "false". Enabling this will have limited success.

##Object Specific loading settings

- **load.username** The user name to use when loging into a website, E.g. "bart"
- **load.password** The password to used when logging into a website, E.g. "elbarto"
- **load.jsdelay** The mount of time in milliseconds to wait after a page has done loading until it is actually printed. E.g. "1200". We will wait this amount of time or until, javascript calls window.print().
- **load.zoomFactor** How much should we zoom in on the content? E.g. "2.2".
- **load.customHeaders** TODO
- **load.repertCustomHeaders** Should the custom headers be sent all elements loaded instead of only the main page? Must be either "true" or "false".
- **load.cookies** TODO
- **load.post** TODO
- **load.blockLocalFileAccess** Disallow local and piped files to access other local files. Must be either "true" or "false".
- **load.stopSlowScript** Stop slow running javascript. Must be either "true" or "false".
- **load.debugJavascript** Forward javascript warnings and errors to the warning callback. Must be either "true" or "false".
- **load.loadErrorHandling** How should we handle obejcts that fail to load. Must be one of:
  - **"abort"** Abort the convertion process
  - **"skip"** Do not add the object to the final output
  - **"ignore"** Try to add the object to the final output.
- **load.proxy** String describing what proxy to use when loading the object.
- **load.runScript** TODO

##Header and footer settings

The same settings can be applied for headers and footers, here there are explained in terms of the header.

- **header.fontSize** The font size to use for the header, e.g. "13"
- **header.fontName** The name of the font to use for the header. e.g. "times"
- **header.left** The string to print in the left part of the header, note that some sequences are replaced in this string, see the wkhtmltopdf manual.
- **header.center** The text to print in the center part of the header.
- **header.right** The text to print in the right part of the header.
- **header.line** Whether a line should be printed under the header (either "true" or "false").
- **header.spacing** The amount of space to put between the header and the content, e.g. "1.8". Be aware that if this is too large the header will be printed outside the pdf document. This can be corrected with the margin.top setting.
- **header.htmlUrl** Url for a HTML document to use for the header.

"""
type PdfObject
  ptr::Ptr{ObjectSettings}
end

# 0 arg case
PdfObject() = PdfObject(pdf_create_object_settings())

# >= 1 case
function PdfObject(p1::Pair{String,String}, args...)
  obj = PdfObject(pdf_create_object_settings())

  pdf_set_object_setting(obj.ptr, p1.first, p1.second)
  for p in args
    isa(p, Pair{String,String}) || error("argument $p is not Pair{String,String}")
    pdf_set_object_setting(obj.ptr, p.first, p.second)
  end

  obj
end

function setindex!(settings::PdfObject, value::String, property::String)
  pdf_set_object_setting(settings.ptr, property, value)
end

function getindex(settings::PdfObject, property::String)
  pdf_get_object_setting(settings.ptr, property)
end

function pdf_create_object_settings()
  ccall((:wkhtmltopdf_create_object_settings, libwkhtml),
  Ptr{ObjectSettings}, ())
end

function pdf_set_object_setting(os::Ptr{ObjectSettings}, property::String, value::String)
  ccall( (:wkhtmltopdf_set_object_setting, libwkhtml),
        Int,
        (Ptr{ObjectSettings}, Cstring, Cstring),
        os,
        convert(Cstring, pointer(property)),
        convert(Cstring, pointer(value)) )
end

function pdf_get_object_setting(os::Ptr{ObjectSettings}, property::String)
  cval = zeros(UInt8, 100)
  ccall((:wkhtmltopdf_get_object_setting, libwkhtml),
        Int,
        (Ptr{ObjectSettings}, Cstring, Cstring, Int),
        os, convert(Cstring, pointer(property)),
            convert(Cstring, pointer(cval)), sizeof(cval)-1 )
  unsafe_string(pointer(cval))
end

### conversion ###

type PdfConverter
  ptr::Ptr{Converter}
end

function PdfConverter(settings::PdfSettings, args...)
  obj = PdfConverter(pdf_create_converter(settings.ptr))

  finalizer(obj, o -> pdf_destroy_converter(o.ptr))

  for p in args
    isa(p, PdfObject) || error("argument $p is not a PdfObject")
    pdf_add_object(obj.ptr, p.ptr, C_NULL)
  end

  obj
end

function push!(conv::PdfConverter, object::PdfObject)
  pdf_add_object(conv.ptr, object.ptr, C_NULL)
end

function run(conv::PdfConverter)
  pdf_wkconvert(conv.ptr)
end

function pdf_create_converter(gs::Ptr{GlobalSettings})
  ccall((:wkhtmltopdf_create_converter, libwkhtml),
        Ptr{Converter},
        (Ptr{GlobalSettings},),
        gs )
end

function pdf_destroy_converter(conv::Ptr{Converter})
  ccall((:wkhtmltopdf_destroy_converter, libwkhtml),
        Void,
        (Ptr{Converter},),
        conv )
end

function pdf_wkconvert(conv::Ptr{Converter})
  ccall((:wkhtmltopdf_convert, libwkhtml),
        Int, (Ptr{Converter},), conv )
end

function pdf_add_object(conv::Ptr{Converter}, os::Ptr{ObjectSettings},
                    data::Union{String, Ptr{Void}})
  ccall((:wkhtmltopdf_add_object, libwkhtml),
        Void,
        (Ptr{Converter}, Ptr{ObjectSettings}, Cstring),
        conv, os,
        isa(data, String) ? convert(Cstring, pointer(data)) : data)
end


text:
M5 = Posit{5, 0}

#begin comprehensive testing of conversion from Float64 -> M5
@test M5(0b10000) == M5(Inf)
@test M5(0b10001) == M5(-8.0)
@test M5(0b10010) == M5(-4.0)
@test M5(0b10011) == M5(-3.0)
@test M5(0b10100) == M5(-2.0)
@test M5(0b10101) == M5(-1.75)
@test M5(0b10110) == M5(-1.5)
@test M5(0b10111) == M5(-1.25)
@test M5(0b11000) == M5(-1.0)
@test M5(0b11001) == M5(-0.875)
@test M5(0b11010) == M5(-0.75)
@test M5(0b11011) == M5(-0.625)
@test M5(0b11100) == M5(-0.5)
@test M5(0b11101) == M5(-0.375)
@test M5(0b11110) == M5(-0.25)
@test M5(0b11111) == M5(-0.125)
@test M5(0b00000) == M5(0.0)
@test M5(0b00001) == M5(0.125)
@test M5(0b00010) == M5(0.25)
@test M5(0b00011) == M5(0.375)
@test M5(0b00100) == M5(0.5)
@test M5(0b00101) == M5(0.625)
@test M5(0b00110) == M5(0.75)
@test M5(0b00111) == M5(0.875)
@test M5(0b01000) == M5(1.0)
@test M5(0b01001) == M5(1.25)
@test M5(0b01010) == M5(1.5)
@test M5(0b01011) == M5(1.75)
@test M5(0b01100) == M5(2.0)
@test M5(0b01101) == M5(3.0)
@test M5(0b01110) == M5(4.0)
@test M5(0b01111) == M5(8.0)

#test overflowing.
@test M5(0b01111) == M5(10.0)
@test M5(0b01111) == M5(16.0)
@test M5(0b01111) == M5(12345678.9)
@test M5(0b00001) == M5(0.0001)

#test h-layer stuff
@test "10000" == bits(M5(Inf))
@test "10001" == bits(M5(-8.0))
@test "10010" == bits(M5(-4.0))
@test "10011" == bits(M5(-3.0))
@test "10100" == bits(M5(-2.0))
@test "10101" == bits(M5(-1.75))
@test "10110" == bits(M5(-1.5))
@test "10111" == bits(M5(-1.25))
@test "11000" == bits(M5(-1.0))
@test "11001" == bits(M5(-0.875))
@test "11010" == bits(M5(-0.75))
@test "11011" == bits(M5(-0.625))
@test "11100" == bits(M5(-0.5))
@test "11101" == bits(M5(-0.375))
@test "11110" == bits(M5(-0.25))
@test "11111" == bits(M5(-0.125))
@test "00000" == bits(M5(0.0))
@test "00001" == bits(M5(0.125))
@test "00010" == bits(M5(0.25))
@test "00011" == bits(M5(0.375))
@test "00100" == bits(M5(0.5))
@test "00101" == bits(M5(0.625))
@test "00110" == bits(M5(0.75))
@test "00111" == bits(M5(0.875))
@test "01000" == bits(M5(1.0))
@test "01001" == bits(M5(1.25))
@test "01010" == bits(M5(1.5))
@test "01011" == bits(M5(1.75))
@test "01100" == bits(M5(2.0))
@test "01101" == bits(M5(3.0))
@test "01110" == bits(M5(4.0))
@test "01111" == bits(M5(8.0))
#test going too far.

#test build_numeric

#test build_arithmetic
@test M5(3.0)  == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 1, 0xC000_0000_0000_0000)
@test M5(2.0)  == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 1, 0x8000_0000_0000_0000)
@test M5(1.5)  == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 0, 0xC000_0000_0000_0000)
@test M5(1.0)  == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 0, 0x8000_0000_0000_0000)
@test M5(0.75) == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 0, 0x6000_0000_0000_0000)
@test M5(0.5)  == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 0, 0x4000_0000_0000_0000)
@test M5(0.25) == SigmoidNumbers.build_arithmetic( SigmoidNumbers.Sigmoid{5,0,:guess}, false, 0, 0x2000_0000_0000_0000)
@test M5(-0.25) == SigmoidNumbers.build_arithmetic(SigmoidNumbers.Sigmoid{5,0,:guess}, true, 0, 0x2000_0000_0000_0000)
@test M5(-1.5)  == SigmoidNumbers.build_arithmetic(SigmoidNumbers.Sigmoid{5,0,:guess}, true, 0, 0xC000_0000_0000_0000)

#test cross-conversions.
for tile in M5
  @test tile == M5(Float64(tile))
end

max_stars_repo_name: ityonemo/SigmoidNumbers

max_issues_repo_name: ityonemo/SigmoidNumbers

max_forks_repo_name: ityonemo/SigmoidNumbers


text:
# * Spherical tensors

"""
    SphericalTensor(k)

Construct a spherical tensor of rank `k`.
"""
struct SphericalTensor{k} <: Tensor{k,'C'} end

"""
    system(::Type{SphericalTensor})

A spherical tensor only acts on the coordinates ``\\theta`` and
``\\phi``.
"""
system(::Type{<:SphericalTensor}) = OrbitalAngularMomentumSubSystem()

@tensor(SphericalTensor{k} where k) do
    ℓ′ ∈ abs(ℓ - k):2:(ℓ+k)

    raw"""
    rme(ℓ′,𝐂̂ᵏ,ℓ)

Calculate the reduced matrix element of the spherical tensor of rank
`k`:

```math
\begin{aligned}
\redmatrixel{\ell'}{\tensor{C}^{(k)}}{\ell}
&=
\angroot{\ell}
C_{\ell 0;k,0}^{\ell'0} =
(-)^{\ell-k}
\angroot{\ell\ell'}
\wignerthreej{\ell&k&\ell'\\0&0&0}.
\end{aligned}
\tag{V13.2.107}
```
"""
    ∏(ℓ)*clebschgordan(ℓ,0,k,0,ℓ′,0)
end

"""
    ranks(a, ::Type{SphericalTensor}, b)

Return which tensor ranks for spherical tensors that fulfill the
triangle condition between spin-orbitals `a` and `b`.
"""
ranks(a::SpinOrbital, ::Type{SphericalTensor}, b::SpinOrbital) =
    triangle_range(a.orb.ℓ, b.orb.ℓ)

# * Dipole tensors

"""
    Dipole()

Construct a dipole tensor
"""
struct Dipole <: Tensor{1,'D'} end

"""
    system(::Type{Dipole})

A dipole tensor only acts on the coordinates ``r``, ``\\theta`` and
``\\phi``.
"""
system(::Type{Dipole}) = SpatialSubSystem()

@doc raw"""
    RadialMatrixElement()

This represents the matrix element of the radial component of the
dipole operator:

```math
\expect{r} =
\int_0^\infty\diff{r}r^2
\conj{\Psi}_{n'\ell'}(r)
r
\Psi_{n\ell}(r)
```
"""
struct RadialMatrixElement <: OneBodyOperator end

Base.show(io::IO, ::RadialMatrixElement) = write(io, "r")

@tensor(Dipole) do
    begin
        n′ ~ n # The dipole couples orbitals of different n, but
               # there is no selection rule.
        ℓ′ == ℓ ± 1
    end

    raw"""
    rme((n′,ℓ′), ::Dipole, (n,ℓ))

Computes the reduced matrix element of `𝐃` in terms of
[`RadialMatrixElement`](@ref).
"""
    rme(ℓ′, SphericalTensor(1), ℓ)*RadialMatrixElement()
end

module Dipoles
import ..cartesian_tensor_component, ..SphericalTensor, ..Dipole

"""
    𝐫̂

The angular part of the dipole operator; the elements correspond to
`[x,y,z]`, i.e. the Cartesian tensor components. Can be entered as
`\\bfr\\hat`.

# Examples

```jldoctest
julia> using AngularMomentumAlgebra.Dipoles

julia> z = 𝐫̂[3]
𝐂̂⁽¹⁾₀

julia> dot(SpinOrbital(o"2s", 0, half(1)), z, SpinOrbital(o"2p", 0, half(1)))
0.5773502691896256
```

"""
const 𝐫̂ = [cartesian_tensor_component(SphericalTensor(1), c)
           for c in [:x, :y, :z]]

"""
    𝐫

The dipole operator; the elements correspond to `[x,y,z]`, i.e. the
Cartesian tensor components. Can be entered as `\\bfr`.

# Examples

```jldoctest
julia> using AngularMomentumAlgebra.Dipoles

julia> z = 𝐫[3]
𝐃̂⁽¹⁾₀

julia> dot(SpinOrbital(o"1s", 0, half(1)), z, SpinOrbital(o"2p", 0, half(1)))
0.57735r

julia> dot(SpinOrbital(o"2s", 0, half(1)), z, SpinOrbital(o"2p", 0, half(1)))
0.57735r

julia> dot(SpinOrbital(o"2p", 0, half(1)), z, SpinOrbital(o"3d", 0, half(1)))
0.516398r
```
"""
const 𝐫 = [cartesian_tensor_component(Dipole(), c)
           for c in [:x, :y, :z]]
export 𝐫̂, 𝐫
end

export SphericalTensor, Dipole, rme


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct NetworkInterfaceIPConfigurationPropertiesFormat <: SwaggerModel
    applicationGatewayBackendAddressPools::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayBackendAddressPool} } # spec name: applicationGatewayBackendAddressPools
    loadBalancerBackendAddressPools::Any # spec type: Union{ Nothing, Vector{BackendAddressPool} } # spec name: loadBalancerBackendAddressPools
    loadBalancerInboundNatRules::Any # spec type: Union{ Nothing, Vector{InboundNatRule} } # spec name: loadBalancerInboundNatRules
    privateIPAddress::Any # spec type: Union{ Nothing, String } # spec name: privateIPAddress
    privateIPAllocationMethod::Any # spec type: Union{ Nothing, String } # spec name: privateIPAllocationMethod
    privateIPAddressVersion::Any # spec type: Union{ Nothing, String } # spec name: privateIPAddressVersion
    subnet::Any # spec type: Union{ Nothing, Subnet } # spec name: subnet
    primary::Any # spec type: Union{ Nothing, Bool } # spec name: primary
    publicIPAddress::Any # spec type: Union{ Nothing, PublicIPAddress } # spec name: publicIPAddress
    provisioningState::Any # spec type: Union{ Nothing, String } # spec name: provisioningState

    function NetworkInterfaceIPConfigurationPropertiesFormat(;applicationGatewayBackendAddressPools=nothing, loadBalancerBackendAddressPools=nothing, loadBalancerInboundNatRules=nothing, privateIPAddress=nothing, privateIPAllocationMethod=nothing, privateIPAddressVersion=nothing, subnet=nothing, primary=nothing, publicIPAddress=nothing, provisioningState=nothing)
        o = new()
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("applicationGatewayBackendAddressPools"), applicationGatewayBackendAddressPools)
        setfield!(o, Symbol("applicationGatewayBackendAddressPools"), applicationGatewayBackendAddressPools)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("loadBalancerBackendAddressPools"), loadBalancerBackendAddressPools)
        setfield!(o, Symbol("loadBalancerBackendAddressPools"), loadBalancerBackendAddressPools)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("loadBalancerInboundNatRules"), loadBalancerInboundNatRules)
        setfield!(o, Symbol("loadBalancerInboundNatRules"), loadBalancerInboundNatRules)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("privateIPAddress"), privateIPAddress)
        setfield!(o, Symbol("privateIPAddress"), privateIPAddress)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("privateIPAllocationMethod"), privateIPAllocationMethod)
        setfield!(o, Symbol("privateIPAllocationMethod"), privateIPAllocationMethod)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("privateIPAddressVersion"), privateIPAddressVersion)
        setfield!(o, Symbol("privateIPAddressVersion"), privateIPAddressVersion)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("subnet"), subnet)
        setfield!(o, Symbol("subnet"), subnet)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("primary"), primary)
        setfield!(o, Symbol("primary"), primary)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("publicIPAddress"), publicIPAddress)
        setfield!(o, Symbol("publicIPAddress"), publicIPAddress)
        validate_property(NetworkInterfaceIPConfigurationPropertiesFormat, Symbol("provisioningState"), provisioningState)
        setfield!(o, Symbol("provisioningState"), provisioningState)
        o
    end
end # type NetworkInterfaceIPConfigurationPropertiesFormat

const _property_map_NetworkInterfaceIPConfigurationPropertiesFormat = Dict{Symbol,Symbol}(Symbol("applicationGatewayBackendAddressPools")=>Symbol("applicationGatewayBackendAddressPools"), Symbol("loadBalancerBackendAddressPools")=>Symbol("loadBalancerBackendAddressPools"), Symbol("loadBalancerInboundNatRules")=>Symbol("loadBalancerInboundNatRules"), Symbol("privateIPAddress")=>Symbol("privateIPAddress"), Symbol("privateIPAllocationMethod")=>Symbol("privateIPAllocationMethod"), Symbol("privateIPAddressVersion")=>Symbol("privateIPAddressVersion"), Symbol("subnet")=>Symbol("subnet"), Symbol("primary")=>Symbol("primary"), Symbol("publicIPAddress")=>Symbol("publicIPAddress"), Symbol("provisioningState")=>Symbol("provisioningState"))
const _property_types_NetworkInterfaceIPConfigurationPropertiesFormat = Dict{Symbol,String}(Symbol("applicationGatewayBackendAddressPools")=>"Vector{ApplicationGatewayBackendAddressPool}", Symbol("loadBalancerBackendAddressPools")=>"Vector{BackendAddressPool}", Symbol("loadBalancerInboundNatRules")=>"Vector{InboundNatRule}", Symbol("privateIPAddress")=>"String", Symbol("privateIPAllocationMethod")=>"String", Symbol("privateIPAddressVersion")=>"String", Symbol("subnet")=>"Subnet", Symbol("primary")=>"Bool", Symbol("publicIPAddress")=>"PublicIPAddress", Symbol("provisioningState")=>"String")
Base.propertynames(::Type{ NetworkInterfaceIPConfigurationPropertiesFormat }) = collect(keys(_property_map_NetworkInterfaceIPConfigurationPropertiesFormat))
Swagger.property_type(::Type{ NetworkInterfaceIPConfigurationPropertiesFormat }, name::Symbol) = Union{Nothing,eval(Meta.parse(_property_types_NetworkInterfaceIPConfigurationPropertiesFormat[name]))}
Swagger.field_name(::Type{ NetworkInterfaceIPConfigurationPropertiesFormat }, property_name::Symbol) =  _property_map_NetworkInterfaceIPConfigurationPropertiesFormat[property_name]

const _allowed_NetworkInterfaceIPConfigurationPropertiesFormat_privateIPAllocationMethod = ["Static", "Dynamic"]

const _allowed_NetworkInterfaceIPConfigurationPropertiesFormat_privateIPAddressVersion = ["IPv4", "IPv6"]

function check_required(o::NetworkInterfaceIPConfigurationPropertiesFormat)
    true
end

function validate_property(::Type{ NetworkInterfaceIPConfigurationPropertiesFormat }, name::Symbol, val)
    if name === Symbol("privateIPAllocationMethod")
        Swagger.validate_param(name, "NetworkInterfaceIPConfigurationPropertiesFormat", :enum, val, _allowed_NetworkInterfaceIPConfigurationPropertiesFormat_privateIPAllocationMethod)
    end
    if name === Symbol("privateIPAddressVersion")
        Swagger.validate_param(name, "NetworkInterfaceIPConfigurationPropertiesFormat", :enum, val, _allowed_NetworkInterfaceIPConfigurationPropertiesFormat_privateIPAddressVersion)
    end
end


text:
using Base.Test

using DocOpt  # import docopt method
import DocOpt:
    DocOptExit,
    DocOptLanguageError,
    # patterns
    Option,
    Argument,
    Command,
    Required,
    Optional,
    OneOrMore,
    Either,
    OptionsShortcut,
    # internal methods (only common ones)
    patternmatch,
    fix,
    fix_identities

@testset "pattern_flat" begin
    flat = DocOpt.flat
    @test flat(Required([OneOrMore([Argument("N")]),
                         Option("-a"),
                         Argument("M")])) ==
        [Argument("N"), Option("-a"), Argument("M")]
    @test flat(Required([Optional([OptionsShortcut()]),
                         Optional([Option("-a", nothing)])]),
               [OptionsShortcut]) ==
        [OptionsShortcut()]
end

@testset "option" begin
    @test Option("-h") == Option("-h", nothing, 0, false)
    @test Option("--help") == Option(nothing, "--help", 0, false)
    @test Option("-h --help") == Option("-h", "--help", 0, false)
    @test Option("-h, --help") == Option("-h", "--help", 0, false)

    @test Option("-h TOPIC") == Option("-h", nothing, 1, nothing)
    @test Option("--help TOPIC") == Option(nothing, "--help", 1, nothing)
    @test Option("-h TOPIC --help TOPIC") == Option("-h", "--help", 1, nothing)
    @test Option("-h TOPIC, --help TOPIC") == Option("-h", "--help", 1, nothing)
    @test Option("-h TOPIC, --help=TOPIC") == Option("-h", "--help", 1, nothing)

    @test Option("-h  Description...") == Option("-h", nothing, 0, false)
    @test Option("-h --help  Description...") == Option("-h", "--help", 0, false)
    @test Option("-h TOPIC  Description...") == Option("-h", nothing, 1, nothing)

    @test Option("     -h") == Option("-h", nothing, 0, false)

    @test Option("-h TOPIC  Description... [default: 2]") == Option("-h", nothing, 1, "2")
    @test Option("-h TOPIC  Description... [default: topic-1]") == Option("-h", nothing, 1, "topic-1")
    @test Option("--help=TOPIC  ... [default: 3.14]") ==  Option(nothing, "--help", 1, "3.14")
    @test Option("-h, --help=DIR  ... [default: ./]") ==  Option("-h", "--help", 1, "./")
    @test Option("-h TOPIC  Descripton... [dEfAuLt: 2]") == Option("-h", nothing, 1, "2")
end

@testset "option_name" begin
    name = DocOpt.name
    @test name(Option("-h", nothing)) == "-h"
    @test name(Option("-h", "--help")) == "--help"
    @test name(Option(nothing, "--help")) == "--help"
end

@testset "commands" begin
    @test docopt("Usage: prog add", "add") == Dict("add" => true)
    @test docopt("Usage: prog [add]", "") == Dict("add" => false)
    @test docopt("Usage: prog [add]", "add") == Dict("add" => true)
    @test docopt("Usage: prog (add|rm)", "add") == Dict("add" => true, "rm" => false)
    @test docopt("Usage: prog (add|rm)", "rm") == Dict("add" => false, "rm" => true)
    @test docopt("Usage: prog a b", "a b") == Dict("a" => true, "b" => true)

    @test_throws DocOptExit docopt("Usage: prog a b", "b a"; exit_on_error=false)
end

@testset "formal_usage" begin
    doc = """
    Usage: prog [-hv] ARG
           prog N M

    prog is a program."""
    usage, = DocOpt.parse_section("usage:", doc)
    @test usage == "Usage: prog [-hv] ARG\n       prog N M"
    @test DocOpt.formal_usage(usage) == "( [-hv] ARG ) | ( N M )"
end

@testset "parse_argv" begin
    o = [Option("-h"), Option("-v", "--verbose"), Option("-f", "--file", 1)]
    ts = s -> DocOpt.Tokens(s, DocOptExit)
    parse_argv = DocOpt.parse_argv
    @test parse_argv(ts(""), o) == []
    @test parse_argv(ts("-h"), o) == [Option("-h", nothing, 0, true)]
    @test parse_argv(ts("-h --verbose"), o) == [Option("-h", nothing, 0, true), Option("-v", "--verbose", 0, true)]
    @test parse_argv(ts("-h --file f.txt"), o) == [Option("-h", nothing, 0, true), Option("-f", "--file", 1, "f.txt")]
    @test parse_argv(ts("-h --file f.txt arg"), o) == [
        Option("-h", nothing, 0, true),
        Option("-f", "--file", 1, "f.txt"),
        Argument(nothing, "arg")
    ]
    @test parse_argv(ts("-h --file f.txt arg arg2"), o) == [
        Option("-h", nothing, 0, true),
        Option("-f", "--file", 1, "f.txt"),
        Argument(nothing, "arg"),
        Argument(nothing, "arg2")
    ]
    @test parse_argv(ts("-h arg -- -v"), o) == [
        Option("-h", nothing, 0, true),
        Argument(nothing, "arg"),
        Argument(nothing, "--"),
        Argument(nothing, "-v")
    ]
end

@testset "parse_pattern" begin
    o = [Option("-h"), Option("-v", "--verbose", 0, false), Option("-f", "--file", 1, nothing)]
    parse_pattern = DocOpt.parse_pattern
    @test parse_pattern("[ -h ]", o) == Required([Optional([Option("-h")])])
    @test parse_pattern("[ ARG ...]", o) == Required([Optional([OneOrMore([Argument("ARG")])])])
    @test parse_pattern("[ -h | -v ]", o) == Required([Optional([Either([Option("-h"),
                                                                         Option("-v", "--verbose")])])])
    @test parse_pattern("( -h | -v [ --file <f> ] )", o) ==
        Required([Required([
            Either([Option("-h", nothing, 0, false),
                    Required([Option("-v", "--verbose", 0, false),
                              Optional([Option("-f", "--file", 1, nothing)])])])])])
    @test parse_pattern("(-h|-v[--file=<f>]N...)", o) ==
        Required([Required([Either([Option("-h"),
                                    Required([Option("-v", "--verbose"),
                                              Optional([Option("-f", "--file", 1, nothing)]),
                                              OneOrMore([Argument("N")])])])])])
    @test parse_pattern("(N [M | (K | L)] | O P)", []) ==
        Required([Required([Either([Required([Argument("N"),
                                              Optional([Either([Argument("M"),
                                                                Required([Either([Argument("K"),
                                                                                Argument("L")])])])])]),
                                    Required([Argument("O"),
                                              Argument("P")])])])])
    @test parse_pattern("[ -h ] [N]", o) ==
        Required([Optional([Option("-h")]),
                  Optional([Argument("N")])])
    @test parse_pattern("[options]", o) == Required([Optional([OptionsShortcut()])])
    @test parse_pattern("[options] A", o) ==
        Required([Optional([OptionsShortcut()]),
                  Argument("A")])
    @test parse_pattern("-v [options]", o) ==
        Required([Option("-v", "--verbose", 0, false),
                  Optional([OptionsShortcut()])])
    @test parse_pattern("ADD", o) == Required([Argument("ADD")])
    @test parse_pattern("<add>", o) == Required([Argument("<add>")])
    @test parse_pattern("add", o) == Required([Command("add")])
end

@testset "option_match" begin
    @test patternmatch(Option("-a", nothing, 0, false), [Option("-a", nothing, 0, true)]) ==
        (true, [], [Option("-a", nothing, 0, true)])
    @test patternmatch(Option("-a", nothing, 0, false), [Option("-x", nothing, 0, false)]) ==
        (false, [Option("-x", nothing, 0, false)], [])
    @test patternmatch(Option("-a", nothing, 0, false), [Argument("N")]) ==
        (false, [Argument("N")], [])
    @test patternmatch(Option("-a", nothing, 0, false), [Option("-x", nothing, 0, false),
                                                         Option("-a", nothing, 0, false),
                                                         Argument("N")]) ==
        (true, [Option("-x", nothing, 0, false), Argument("N")], [Option("-a")])
    @test patternmatch(Option("-a", nothing, 0, false), [Option("-a", nothing, 0, true),
                                                         Option("-a", nothing, 0, false)]) ==
        (true, [Option("-a", nothing, 0, false)], [Option("-a", nothing, 0, true)])
end

@testset "argument_match" begin
    @test patternmatch(Argument("N"), [Argument(nothing, 9)]) ==
        (true, [], [Argument("N", 9)])
    @test patternmatch(Argument("N"), [Option("-x")]) ==
        (false, [Option("-x", nothing, 0, false)], [])
    @test patternmatch(Argument("N"), [Option("-x"), Option("-a"), Argument(nothing, 5)]) ==
        (true, [Option("-x"), Option("-a")], [Argument("N", 5)])
    @test patternmatch(Argument("N"), [Argument(nothing, 9), Argument(nothing, 0)]) ==
        (true, [Argument(nothing, 0)], [Argument("N", 9)])
end

@testset "command_match" begin
    @test patternmatch(Command("c"), [Argument(nothing, "c")]) ==
        (true, [], [Command("c", true)])
    @test patternmatch(Command("c"), [Option("-x")]) ==
        (false, [Option("-x")], [])
    @test patternmatch(Command("c"), [Option("-x"), Option("-a"), Argument(nothing, "c")]) ==
        (true, [Option("-x"), Option("-a")], [Command("c", true)])
    @test patternmatch(Either([Command("add", false), Command("rm", false)]), [Argument(nothing, "rm")]) ==
        (true, [], [Command("rm", true)])
end

@testset "optional_match" begin
    @test patternmatch(Optional([Option("-a")]), [Option("-a")]) ==
        (true, [], [Option("-a")])
    @test patternmatch(Optional([Option("-a")]), []) ==
        (true, [], [])
    @test patternmatch(Optional([Option("-a")]), [Option("-x")]) ==
        (true, [Option("-x")], [])
    @test patternmatch(Optional([Option("-a"), Option("-b")]), [Option("-a")]) ==
        (true, [], [Option("-a")])
    @test patternmatch(Optional([Option("-a"), Option("-b")]), [Option("-b")]) ==
        (true, [], [Option("-b")])
    @test patternmatch(Optional([Option("-a"), Option("-b")]), [Option("-x")]) ==
        (true, [Option("-x")], [])
    @test patternmatch(Optional([Argument("N")]), [Argument(nothing, 9)]) ==
        (true, [], [Argument("N", 9)])
    @test patternmatch(Optional([Option("-a"), Option("-b")]), [Option("-b"), Option("-x"), Option("-a")]) ==
        (true, [Option("-x")], [Option("-a"), Option("-b")])
end

@testset "required_match" begin
    @test patternmatch(Required([Option("-a")]), [Option("-a")]) ==
        (true, [], [Option("-a")])
    @test patternmatch(Required([Option("-a")]), []) ==
        (false, [], [])
    @test patternmatch(Required([Option("-a")]), [Option("-x")]) ==
        (false, [Option("-x")], [])
    @test patternmatch(Required([Option("-a"), Option("-b")]), [Option("-a")]) ==
        (false, [Option("-a")], [])
end

@testset "either_match" begin
    @test patternmatch(Either([Option("-a", nothing, 0, nothing), Option("-b", nothing, 0, nothing)]), [Option("-a", nothing, 0, nothing)]) ==
        (true, [], [Option("-a", nothing, 0, nothing)])
    @test patternmatch(Either([Option("-a", nothing, 0, nothing), Option("-b", nothing, 0, nothing)]), [Option("-a", nothing, 0, nothing), Option("-b", nothing, 0, nothing)]) ==
        (true, [Option("-b", nothing, 0, nothing)], [Option("-a", nothing, 0, nothing)])
    @test patternmatch(Either([Option("-a", nothing, 0, nothing), Option("-b", nothing, 0, nothing)]), [Option("-x", nothing, 0, nothing)]) ==
        (false, [Option("-x", nothing, 0, nothing)], [])
    @test patternmatch(Either([Option("-a", nothing, 0, nothing), Option("-b", nothing, 0, nothing), Option("-c", nothing, 0, nothing)]), [Option("-x", nothing, 0, nothing), Option("-b", nothing, 0, nothing)]) ==
        (true, [Option("-x", nothing, 0, nothing)], [Option("-b", nothing, 0, nothing)])
    @test patternmatch(Either([Argument("M"),
                               Required([Argument("N"), Argument("M")])]),
                       [Argument(nothing, 1), Argument(nothing, 2)]) ==
        (true, [], [Argument("N", 1), Argument("M", 2)])
end

@testset "one_or_more_match" begin
    @test patternmatch(OneOrMore([Argument("N")]), [Argument(nothing, 9)]) ==
        (true, [], [Argument("N", 9)])
    @test patternmatch(OneOrMore([Argument("N")]), []) ==
        (false, [], [])
    @test patternmatch(OneOrMore([Argument("N")]), [Option("-x", nothing, 0, nothing)]) ==
        (false, [Option("-x", nothing, 0, nothing)], [])
    @test patternmatch(OneOrMore([Argument("N")]), [Argument(nothing, 9), Argument(nothing, 8)]) ==
        (true, [], [Argument("N", 9), Argument("N", 8)])
    @test patternmatch(OneOrMore([Argument("N")]), [Argument(nothing, 9), Option("-x", nothing, 0, nothing), Argument(nothing, 8)]) ==
        (true, [Option("-x", nothing, 0, nothing)], [Argument("N", 9), Argument("N", 8)])
    @test patternmatch(OneOrMore([Option("-a")]), [Option("-a"), Argument(nothing, 8), Option("-a")]) ==
        (true, [Argument(nothing, 8)], [Option("-a"), Option("-a")])
    @test patternmatch(OneOrMore([Option("-a")]), [Argument(nothing, 8), Option("-x")]) ==
        (false, [Argument(nothing, 8), Option("-x")], [])
    @test patternmatch(OneOrMore([Required([Option("-a"), Argument("N")])]), [Option("-a"), Argument(nothing, 1), Option("-x"), Option("-a"), Argument(nothing, 2)]) ==
        (true, [Option("-x")], [Option("-a"), Argument("N", 1), Option("-a"), Argument("N", 2)])
    @test patternmatch(OneOrMore([Optional([Argument("N")])]), [Argument(nothing, 9)]) ==
        (true, [], [Argument("N", 9)])
end

@testset "list_argument_match" begin
    @test patternmatch(fix(Required([Argument("N"), Argument("N")])),
                       [Argument(nothing, "1"), Argument(nothing, "2")]) ==
        (true, [], [Argument("N", ["1", "2"])])
    @test patternmatch(fix(OneOrMore([Argument("N")])),
                       [Argument(nothing, "1"), Argument(nothing, "2"), Argument(nothing, "3")]) ==
        (true, [], [Argument("N", ["1", "2", "3"])])
    @test patternmatch(fix(Required([Argument("N"), OneOrMore([Argument("N")])])),
                       [Argument(nothing, "1"), Argument(nothing, "2"), Argument(nothing, "3")]) ==
        (true, [], [Argument("N", ["1", "2", "3"])])
    @test patternmatch(fix(Required([Argument("N"), Required([Argument("N")])])),
                       [Argument(nothing, "1"), Argument(nothing, "2")]) ==
        (true, [], [Argument("N", ["1", "2"])])
end

@testset "basic_pattern_matching" begin
    # ( -a N [ -x Z ] )
    pattern = Required([Option("-a"), Argument("N"),
                        Optional([Option("-x"), Argument("Z")])])

    # -a N
    @test patternmatch(pattern, [Option("-a"), Argument(nothing, 9)]) ==
        (true, [], [Option("-a"), Argument("N", 9)])

    # -a -x N Z
    @test patternmatch(pattern, [Option("-a"), Option("-x"),
                                 Argument(nothing, 9), Argument(nothing, 5)]) ==
        (true, [], [Option("-a"), Argument("N", 9), Option("-x"), Argument("Z", 5)])

    # -x N Z
    @test patternmatch(pattern, [Option("-x"), Argument(nothing, 9), Argument(nothing, 5)]) ==
        (false, [Option("-x"), Argument(nothing, 9), Argument(nothing, 5)], [])
end

@testset "pattern_either" begin
    transform = DocOpt.transform
    @test transform(Option("-a")) == Either([Required([Option("-a")])])
    @test transform(Argument("A")) == Either([Required([Argument("A")])])
    @test transform(Required([Either([Option("-a"), Option("-b")]),
                              Option("-c")])) ==
        Either([Required([Option("-a"), Option("-c")]),
                Required([Option("-b"), Option("-c")])])
    @test transform(Optional([Option("-a"), Either([Option("-b"), Option("-c")])])) ==
        Either([Required([Option("-b"), Option("-a")]),
                Required([Option("-c"), Option("-a")])])
    @test transform(Either([Option("-x"), Either([Option("-y"), Option("-z")])])) ==
        Either([Required([Option("-x")]),
                Required([Option("-y")]),
                Required([Option("-z")])])
    @test transform(OneOrMore([Argument("N"), Argument("M")])) ==
        Either([Required([Argument("N"), Argument("M"),
                          Argument("N"), Argument("M")])])
end

@testset "pattern_fix_repeating_arguments" begin
    fix_repeating_arguments = DocOpt.fix_repeating_arguments
    @test fix_repeating_arguments(Option("-a")) == Option("-a")
    @test fix_repeating_arguments(Argument("N", nothing)) == Argument("N", nothing)
    @test fix_repeating_arguments(Required([Argument("N"), Argument("N")])) ==
        Required([Argument("N", []), Argument("N", [])])
    @test fix(Either([Argument("N"), OneOrMore([Argument("N")])])) ==
        Either([Argument("N", []), OneOrMore([Argument("N", [])])])
end

@testset "set" begin
    @test Argument("N") == Argument("N")
    @test Set([Argument("N"), Argument("N")]) == Set([Argument("N")])
end

@testset "pattern_fix_identities_1" begin
    pattern = Required([Argument("N"), Argument("N")])
    @test pattern.children[1] == pattern.children[2]
    @test pattern.children[1] !== pattern.children[2]
    fix_identities(pattern)
    @test pattern.children[1] === pattern.children[2]
end

@testset "pattern_fix_identities_2" begin
    pattern = Required([Optional([Argument("X"), Argument("N")]), Argument("N")])
    @test pattern.children[1].children[2] == pattern.children[2]
    @test pattern.children[1].children[2] !== pattern.children[2]
    fix_identities(pattern)
    @test pattern.children[1].children[2] === pattern.children[2]
end

@testset "long_options_error_handling" begin
    @test_throws DocOptExit docopt("Usage: prog", "--non-existent"; exit_on_error=false)
    @test_throws DocOptExit docopt("Usage: prog [--version --verbose]\nOptions: --version\n --verbose", "--ver"; exit_on_error=false)

    @test_throws DocOptLanguageError docopt("Usage: prog --long\nOptions: --long ARG"; exit_on_error=false)

    @test_throws DocOptExit docopt("Usage: prog --long ARG\nOptions: --long ARG", "--long"; exit_on_error=false)

    @test_throws DocOptLanguageError docopt("Usage: prog --long=ARG\nOptions: --long"; exit_on_error=false)

    @test_throws DocOptExit docopt("Usage: prog --long\nOptions: --long", "--long=ARG"; exit_on_error=false)
end

@testset "short_options_error_handling" begin
    @test_throws DocOptLanguageError docopt("Usage: prog -x\nOptions: -x  this\n -x  that"; exit_on_error=false)
    @test_throws DocOptExit docopt("Usage: prog", "-x"; exit_on_error=false)
    @test_throws DocOptLanguageError docopt("Usage: prog -o\nOptions: -o ARG"; exit_on_error=false)
    @test_throws DocOptExit docopt("Usage: prog -o ARG\nOptions: -o ARG", "-o"; exit_on_error=false)
end

@testset "matching_paren" begin
    @test_throws DocOptLanguageError docopt("Usage: prog [a [b]"; exit_on_error=false)
    # DocOptLanguageError
    #@test_throws DocOptLanguageError docopt("Usage: prog [a [b] ] c)"; exit_on_error=false)
end

@testset "allow_double_dash" begin
    @test docopt("usage: prog [-o] [--] <arg>\nkptions: -o", "-- -o") ==
        Dict("-o" => false, "<arg>" => "-o", "--" => true)
    @test docopt("usage: prog [-o] [--] <arg>\nkptions: -o", "-o 1") ==
        Dict("-o" => true, "<arg>" => "1", "--" => false)
    @test_throws DocOptExit docopt("usage: prog [-o] <arg>\noptions:-o", "-- -o"; exit_on_error=false)
end

@testset "docopt" begin
    doc = """Usage: prog [-v] A

             Options: -v  Be verbose."""

    @test docopt(doc, "arg") == Dict("-v" => false, "A" => "arg")
    @test docopt(doc, "-v arg") == Dict("-v" => true, "A" => "arg")

    doc = """Usage: prog [-vqr] [FILE]
              prog INPUT OUTPUT
              prog --help

    Options:
      -v  print status messages
      -q  report only file names
      -r  show all occurrences of the same error
      --help

    """

    a = docopt(doc, "-v file.jl")
    @test a == Dict("-v" => true, "-q" => false, "-r" => false, "--help" => false,
                        "FILE" => "file.jl", "INPUT" => nothing, "OUTPUT" => nothing)

    a = docopt(doc, "-v")
    @test a == Dict("-v" => true, "-q" => false, "-r" => false, "--help" => false,
                        "FILE" => nothing, "INPUT" => nothing, "OUTPUT" => nothing)

    @test_throws DocOptExit docopt(doc, "-v input.jl output.jl"; exit_on_error=false)
    @test_throws DocOptExit docopt(doc, "--fake"; exit_on_error=false)

    # SystemExit (in Python)
    #@test_throws Exception docopt(doc, "--hel"; exit_on_error=false)
end

@testset "language_errors" begin
    @test_throws DocOptLanguageError docopt("no usage with colon here"; exit_on_error=false)
    @test_throws DocOptLanguageError docopt("usage: here \n\n and again usage: here"; exit_on_error=false)
end

@testset "issue_40" begin
    # SystemExit (in Python)
    # NOTE: This test really exits the program and the rest of the tests will be ignored!
    #@test_throws docopt("usage: prog --help-commands | --help", "--help")
    @test docopt("usage: prog --aabb | --aa", "--aa") == Dict("--aabb" => false, "--aa" => true)
end

@testset "count_multiple_flags" begin
    @test docopt("usage: prog [-v]", "-v") == Dict("-v" => true)
    @test docopt("usage: prog [-vv]", "") == Dict("-v" => 0)
    @test docopt("usage: prog [-vv]", "-v") == Dict("-v" => 1)
    @test docopt("usage: prog [-vv]", "-vv") == Dict("-v" => 2)
    @test_throws DocOptExit docopt("usage: prog [-vv]", "-vvv"; exit_on_error=false)
    @test docopt("usage: prog [-v | -vv | -vvv]", "-vvv") == Dict("-v" => 3)
    @test docopt("usage: prog -v...", "-vvvvvv") == Dict("-v" => 6)
    @test docopt("usage: prog [--ver --ver]", "--ver --ver") == Dict("--ver" => 2)
end

@testset "any_options_parameter" begin
    doc = "usage: prog [options]"
    @test_throws DocOptExit docopt(doc, "-foo --bar --spam=eggs"; exit_on_error=false)
    @test_throws DocOptExit docopt(doc, "--foo --bar --bar"; exit_on_error=false)
    @test_throws DocOptExit docopt(doc, "--bar --bar --bar -ffff"; exit_on_error=false)
    @test_throws DocOptExit docopt(doc, "--long=arg, --long=another"; exit_on_error=false)
end

@testset "default_value_for_positional_arguments" begin
    doc = """Usage: prog [--data=<data>...]\n
             Options:
             \t-d --data=<arg>    Input data [default: x]
          """
    a = docopt(doc, "")
    @test a == Dict("--data" => ["x"])

    doc = """Usage: prog [--data=<data>...]\n
             Options:
             \t-d --data=<arg>    Input data [default: x y]
          """
    a = docopt(doc, "")
    @test a == Dict("--data" => ["x", "y"])

    a = docopt(doc, "--data=this")
    @test a == Dict("--data" => ["this"])
end

@testset "issue_59" begin
    @test docopt("usage: prog --long=<a>", "--long=") == Dict("--long" => "")
    @test docopt("""usage: prog -l <a>
                    options: -l <a>""", ["-l", ""]) == Dict("-l" => "")
end

@testset "options_first" begin
    doc = "usage: prog [--opt] [<args>...]"
    @test docopt(doc, "--opt this that") ==
        Dict("--opt" => true, "<args>" => ["this", "that"])
    @test docopt(doc, "this that --opt") ==
        Dict("--opt" => true, "<args>" => ["this", "that"])
    @test docopt(doc, "this that --opt"; options_first=true) ==
        Dict("--opt" => false, "<args>" => ["this", "that", "--opt"])
end

@testset "issue_68_options_shortcut_does_not_include_options_in_usage_pattern" begin
    args = docopt("usage: prog [-ab] [options]\noptions: -x\n -y", "-ax")
    @test args["-a"] === true
    @test args["-b"] === false
    @test args["-x"] === true
    @test args["-y"] === false
end

@testset "issue_65_evaluate_argv_when_called_not_when_imported" begin
    if !isempty(ARGS)
        throw(DomainError("ARGS should be empty"))
    end
    doc = "usage: prog [-ab]"
    push!(ARGS, "-a")
    @test docopt(doc) == Dict("-a" => true, "-b" => false)
    empty!(ARGS)
    push!(ARGS, "-b")
    @test docopt(doc) == Dict("-a" => false, "-b" => true)
end

@testset "issue_71_double_dash_is_not_a_valid_option_argument" begin
    @test_throws DocOptExit docopt("usage: prog [--long=LEVEL] [--] <args>...", "--log -- 1 2"; exit_on_error=false)
    @test_throws DocOptExit docopt("""usage: prog [-l LEVEL] [--] <args>...
                                      options: -l LEVEL""", "-l -- 1 2"; exit_on_error=false)
end

@testset "parse_section" begin
    usage = """usage: this

    usage:hai
    usage: this that

    usage: foo
           bar

    PROGRAM USAGE:
     foo
     bar
    usage:
    \ttoo
    \ttar
    Usage: eggs spam
    BAZZ
    usage: pit stop"""
    parse_section = DocOpt.parse_section

    @test isempty(parse_section("usage:", "foo bar fizz buzz"))
    @test parse_section("usage:", "usage: prog") == ["usage: prog"]
    @test parse_section("usage:", "usage: -x\n -y") == ["usage: -x\n -y"]

    @test parse_section("usage:", usage)[1] == "usage: this"
    @test parse_section("usage:", usage)[2] == "usage:hai"
    @test parse_section("usage:", usage)[3] == "usage: this that"
    @test parse_section("usage:", usage)[4] == "usage: foo\n       bar"
    @test parse_section("usage:", usage)[5] == "PROGRAM USAGE:\n foo\n bar"
    #@show parse_section("usage:", usage)[6]  # julia expands tab characters (why?)
    #@test parse_section("usage:", usage)[6] == "usage:\n\ttoo\n\ttar"
    @test parse_section("usage:", usage)[7] == "Usage: eggs spam"
    @test parse_section("usage:", usage)[8] == "usage: pit stop"
end


text:
# Copyright © 2021 Alexander L. Hayes

using Documenter

makedocs(sitename="ExportPublic.jl")


text:
using Test
using CompilerPluginTools
using MLStyle

f = @λ begin
    Expr(:(=), SlotNumber(x), _) => x
    ReturnNode(SSAValue(x)) => x
    NewSSAValue(x) => x
    Argument(x) => x
    Const(x) => x
    QuoteNode(x) => x
    _ => false
end

ex = ReturnNode(SSAValue(1))
@test f(ex) == 1

ex = NewSSAValue(2)
@test f(ex) == 2

ex = Expr(:(=), SlotNumber(3), :(Base.Math.abs($(SlotNumber(2)))))
@test f(ex) == 3
@test f(Argument(4)) == 4
@test f(Const(1.1)) == 1.1
@test f(QuoteNode(2)) == 2

dummy(x) = 2x

@testset "Core bootstrap forward" begin
    ir, _ = code_ircode(dummy, Tuple{Float64})[1]
    ir[SSAValue(2)]
    ic = IncrementalCompact(ir)
    (_, idx), stmt = first(ic)
    @test idx == 1
    ic[1]
end


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

using Markdown
using InteractiveUtils

# ╔═╡ 970efd92-5c85-11eb-180e-d508223139fe
begin
	using ReinforcementLearning
	using Flux
	using Statistics
	using Plots
end

# ╔═╡ e939f502-5c8c-11eb-3e40-1386be4610c3
begin
	using Distributions

	const N_SERVERS = 10
	const PRIORITIES = [1.0, 2.0, 4.0, 8.0]
	const FREE_PROB = 0.06
	const ACCEPT_REJECT = (:accept, :reject)
	const CUSTOMERS = 1:length(PRIORITIES)

	const TRANSFORMER = LinearIndices((0:N_SERVERS, CUSTOMERS))

	Base.@kwdef mutable struct AccessControlEnv <: AbstractEnv
		n_servers::Int = 10
		n_free_servers::Int = 0
		customer::Int = rand(CUSTOMERS)
		reward::Float64 = 0.0
	end

	RLBase.state_space(env::AccessControlEnv) = Base.OneTo(length(TRANSFORMER))
	RLBase.action_space(env::AccessControlEnv) = Base.OneTo(2)

	function (env::AccessControlEnv)(a)
		action, reward = ACCEPT_REJECT[a], 0.0
		if env.n_free_servers > 0 && action == :accept
			env.n_free_servers -= 1
			reward = PRIORITIES[env.customer]
		end

		env.n_free_servers += rand(Binomial(env.n_servers - env.n_free_servers, FREE_PROB))
		env.customer = rand(CUSTOMERS)
		env.reward = reward

		nothing
	end

	RLBase.reward(env::AccessControlEnv) = env.reward
	RLBase.is_terminated(env::AccessControlEnv) = false
	RLBase.state(env::AccessControlEnv) = TRANSFORMER[CartesianIndex(env.n_free_servers + 1, env.customer)]

	function RLBase.reset!(env::AccessControlEnv)
		env.n_free_servers = env.n_servers
		env.customer = rand(CUSTOMERS)
		env.reward = 0.0
		nothing
	end
end

# ╔═╡ 01d9380a-5c85-11eb-1463-b1373c6cfe72
md"""
# Chapter 10.3 Access Control

In Chapter 10.3, an algorithm of **Differential semi-gradient Sarsa for estimating q̂ ≈ q⋆**. This one is not included in `ReinforcementLearning.jl`. Here we'll use it as an example to demonstrate how easy it is to extend components in `ReinforcementLearning.jl`.
"""

# ╔═╡ 40f4eae6-5c87-11eb-1978-c9efd63427e9
md"""
## Implement the DifferentialTDLearner

First let's define a `DifferentialTDLearner`. It will be used to estimate Q values. So we have to implement `(L::DifferentialTDLearner)(env::AbstractEnv)`, which simply forward the current `state` to the inner `approximator`.
"""

# ╔═╡ 30eb366e-5c87-11eb-12ad-09087fc4d788
Base.@kwdef mutable struct DifferentialTDLearner{A<:AbstractApproximator} <: AbstractLearner
    approximator::A
    β::Float64
    R̄::Float64 = 0.0
end

# ╔═╡ 3f4df30e-5c87-11eb-290d-7b596c651f71
(L::DifferentialTDLearner)(env::AbstractEnv) = L.approximator(state(env))

# ╔═╡ 9c550740-5c87-11eb-11f1-63afc18d1229
md"""
Now based on the definition of this algorithm on the book， we can implement the updating logic as follows:
"""

# ╔═╡ a223544c-5c87-11eb-1728-8f83730232e7
function RLBase.update!(L::DifferentialTDLearner, transition::Tuple)
    s, a, r, t, s′, a′ = transition
    β, Q = L.β, L.approximator
    δ = r - L.R̄ + (1-t)*Q(s′, a′) - Q(s,a)
    L.R̄ += β* δ
    update!(Q, (s,a) => -δ)
end

# ╔═╡ 17a1328e-5c88-11eb-3603-01c70fd05502
md"""
Next, we dispatch some runtime logic to our specific learner to make sure the above `update!` function is called at the right time.
"""

# ╔═╡ 3dfbe3b6-5c88-11eb-291b-45a716887e3c
begin
	function RLBase.update!(
		p::DifferentialTDLearner,
		t::AbstractTrajectory,
		e::AbstractEnv,
		s::PreActStage,
	)
		if length(t[:terminal]) > 0
			update!(
				p,
				(
					t[:state][end-1],
					t[:action][end-1],
					t[:reward][end],
					t[:terminal][end],
					t[:state][end],
					t[:action][end]
				)
			)
		end
	end

	function RLBase.update!(
		p::DifferentialTDLearner,
		t::AbstractTrajectory,
		e::AbstractEnv,
		s::PostEpisodeStage,
	)
		update!(
			p,
			(
				t[:state][end-1],
				t[:action][end-1],
				t[:reward][end],
				t[:terminal][end],
				t[:state][end],
				t[:action][end]
			)
		)
	end
end

# ╔═╡ 435d632a-5c88-11eb-314b-c1c580f35b70
md"""
The above function specifies that we only update the `DifferentialTDLearnerTDLearner` at the `PreActStage` and the `PostEpisodeStage`. Also note that we don't need to push all the transitions into the trajectory at each step. So we can `empty!` it at the start of an episode:
"""

# ╔═╡ 171efdc4-5c8c-11eb-3aa1-d5904fa31fbe
function RLBase.update!(
    t::AbstractTrajectory,
    ::QBasedPolicy{<:DifferentialTDLearner},
    ::AbstractEnv,
    ::PreEpisodeStage
)
    empty!(t)
end

# ╔═╡ 35efbb7e-5c8c-11eb-36b0-3ffc1355bf59
md"""
## Access Control Environment

Before evaluating the learner implemented above, we have to first define the environment.
"""

# ╔═╡ ffa3b58a-5c8c-11eb-3339-cbd7f96a0164
world = AccessControlEnv()

# ╔═╡ 178e097a-5c8d-11eb-24f2-f3a64cfa7bd8
NS = length(state_space(world))

# ╔═╡ 1ef2ece2-5c8d-11eb-22ce-c746cd951bf2
NA = length(action_space(world))

# ╔═╡ 144c10fe-5c8d-11eb-222f-95c694c1cae6
agent = Agent(
    policy=QBasedPolicy(
        learner=DifferentialTDLearner(
            approximator=TabularQApproximator(
				;n_state=NS,
				n_action=NA,
				opt=Descent(0.01)
				),
            β=0.01,
        ),
        explorer=EpsilonGreedyExplorer(0.1)
    ),
    trajectory=VectorSARTTrajectory()
)

# ╔═╡ 32d8b7a2-5c8d-11eb-15c7-d72a637c7374
run(agent, world, StopAfterStep(2*10^6; is_show_progress=false))

# ╔═╡ 3bdff022-5c8d-11eb-37ff-355f604d3f56
begin

	p = plot(legend=:bottomright)
	for i in 1:length(PRIORITIES)
		plot!(
			[agent.policy.learner.approximator(TRANSFORMER[(CartesianIndex(n+1, i))]) |> maximum
				for n in 1:N_SERVERS],
			label="priority = $(PRIORITIES[i])")
	end
	p
end

# ╔═╡ Cell order:
# ╟─01d9380a-5c85-11eb-1463-b1373c6cfe72
# ╠═970efd92-5c85-11eb-180e-d508223139fe
# ╟─40f4eae6-5c87-11eb-1978-c9efd63427e9
# ╠═30eb366e-5c87-11eb-12ad-09087fc4d788
# ╠═3f4df30e-5c87-11eb-290d-7b596c651f71
# ╟─9c550740-5c87-11eb-11f1-63afc18d1229
# ╠═a223544c-5c87-11eb-1728-8f83730232e7
# ╟─17a1328e-5c88-11eb-3603-01c70fd05502
# ╠═3dfbe3b6-5c88-11eb-291b-45a716887e3c
# ╟─435d632a-5c88-11eb-314b-c1c580f35b70
# ╠═171efdc4-5c8c-11eb-3aa1-d5904fa31fbe
# ╟─35efbb7e-5c8c-11eb-36b0-3ffc1355bf59
# ╠═e939f502-5c8c-11eb-3e40-1386be4610c3
# ╠═ffa3b58a-5c8c-11eb-3339-cbd7f96a0164
# ╠═178e097a-5c8d-11eb-24f2-f3a64cfa7bd8
# ╠═1ef2ece2-5c8d-11eb-22ce-c746cd951bf2
# ╠═144c10fe-5c8d-11eb-222f-95c694c1cae6
# ╠═32d8b7a2-5c8d-11eb-15c7-d72a637c7374
# ╠═3bdff022-5c8d-11eb-37ff-355f604d3f56


text:
using ..Concepts
import Random
import Distributions

struct FixedRankMatrix{T<:UnivariateDistributions} <: AbstractFixedRankMatrix
    dist::T
    rank::Optional{Integer}
    draw
    @abstract_instance
    function FixedRankMatrix{T}() where T<:UnivariateDistributions
        #@debug "abstract constructor of FixedRankMatrix"
        return new{T}()
    end

    function FixedRankMatrix{T}(dist::T;rank::Optional{Integer}=nothing) where T<:UnivariateDistributions
        return new{T}(dist,rank)
    end
end

const FixedRankMatrix(dist::T;rank::Optional{Integer}=nothing) where T<:UnivariateDistributions =
    begin
    isnothing(rank) ? FixedRankMatrix{T}(dist) : FixedRankMatrix{T}(dist,rank=rank)
    end

@overload
function Concepts.provide(object::FixedRankMatrix{T};row::Integer=10,col::Integer=10) where T<:UnivariateDistributions
    return rand(object,row,col)

end

function GaussianMatrix(row::Integer,col::Integer;
                     rank::Optional{Integer}=nothing,
                     μ::T=0, σ::T=1) where T<:Real
    if isnothing(rank)
        return rand(Distributions.Gaussian(μ,σ),row,col)
    end
    return rand(FixedRankMatrix(Distributions.Gaussian(μ,σ),rank=rank),row,col)
end

function PoissonMatrix(row::Integer,col::Integer;
                       rank::Optional{Integer}=nothing,
                       λ = 5) where T<:Real
    if isnothing(rank)
        return rand(Distributions.Poisson(λ),row,col)
    end
    return rand(FixedRankMatrix(Distributions.Poisson(λ),rank=rank),row,col)
end

function BernoulliMatrix(row::Integer,col::Integer;
                         rank::Optional{Integer}=nothing,
                         p = 0.5) where T<:Real
    if isnothing(rank)
        return rand(Distributions.Bernoulli(p),row,col)
    end
    return rand(FixedRankMatrix(Distributions.Bernoulli(p),rank=rank),row,col)
end

function GammaMatrix(row::Integer,col::Integer;
                     rank::Optional{Integer}=nothing,
                     α=5,θ=0.5) where T<:Real
    if isnothing(rank)
        return rand(Distributions.Gamma(α,θ),row,col)
    end
    return rand(FixedRankMatrix(Distributions.Gamma(α,θ),rank=rank),row,col)
end

@overload
function Random.rand(object::FixedRankMatrix{T},row::Integer,col::Integer) where T<:UnivariateDistributions
    used_rank = nothing
    if isnothing(object.rank)
        @warn "Rank is not specified. Using formula: rank= ⌊0.3 * (row ∧ col)⌋"
        used_rank = Int(0.3 * floor(min(row,col)))
    elseif object.rank > max(row,col)
        used_rank = min(row,col)
    else
        used_rank = object.rank
    end
    ensure_feasible(row,col,used_rank);
    base_matrix = Random.rand(object.dist,row,used_rank)
    redundant_matrix = base_matrix[:,StatsBase.sample(1:used_rank,col-used_rank)];
    return hcat(base_matrix,redundant_matrix) * 1.0;
end

@overload
function Random.rand(mixed_dists::Vector{Tuple{T,I,I}}) where {T<:FixedRankMatrix{<:UnivariateDistributions}, I<: Integer}
    #ensure_feasible(mixed_dists)
    # TODO: Make a ensure feasible function
    gen_mat = mapreduce(x -> rand(x[1],x[2],x[3]),(x,y)->hcat(x,y),mixed_dists);
    return gen_mat;
end

function ensure_feasible(row::T,col::T,rank::T) where T<:Integer
        if col <0 || row <0
            throw(DomainError("The dimension of the matrix should be positive integers."))
        end
        if rank <= 0 || rank > min(row,col)
            throw(DomainError("The rank of the matrix should be a positive integer less than min(row,col)"))
        end
end

"""
Generate a random matrix of given rank with distribution of 'dist' of given size (rol,col) from user input.

Precondition(s):
1. The distribution has to be an element from the "Distributions.jl" and of subtype "Univariate".
"""

# function rand(dist::T,row::I,col::I;target_rank::I) where {T<:UnivariateDistributions,I<:Integer}
#     ensure_feasible(row,col,target_rank);
#     base_matrix = Random.rand(dist,row,target_rank)
#     redundant_matrix = base_matrix[:,StatsBase.sample(1:target_rank,col-target_rank)];
#     return hcat(base_matrix,redundant_matrix) * 1.0;
# end

"""
Generate a random matrix of consisting multiple types of distributions.

Precondition(s):
1. length(mixed_dists) has to be >= 1.
"""
# function rand(mixed_dists::Vector{Tuple{T,Pair{I,I},I}}) where {T<:UnivariateDistributions,I<:Integer}
#     _ensure_feasible(mixed_dists)
#     gen_mat = mapreduce(x -> rand(x[1],x[2].first,x[2].second;target_rank = x[3]),(x,y)->hcat(x,y),mixed_dists);
#     return gen_mat;
# end

# end