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

using Markdown
using InteractiveUtils

# ╔═╡ 0b91d166-fdaa-11ea-3dac-ebd4d51a729f
using Pkg, DrWatson

# ╔═╡ 0b92178e-fdaa-11ea-3be6-27667afc3797
begin
	#@quickactivate "StatisticalRethinkingStan"
	using StanSample
	using StatisticalRethinking
end

# ╔═╡ bd517e12-fda8-11ea-2835-77cfacec77f7
md"## Clip-05-38s.jl"

# ╔═╡ d95b1330-6d3c-11eb-0fea-0771c632bafb
begin
	df = CSV.read(sr_datadir("milk.csv"), DataFrame; delim=';');
	df = filter(row -> !(row[:neocortex_perc] == "NA"), df);
	df[!, :neocortex_perc] = parse.(Float64, df[:, :neocortex_perc])
	df[!, :lmass] = log.(df[:, :mass])
	scale!(df, [:kcal_per_g, :neocortex_perc, :lmass])
	data = (N = size(df, 1), M = df[!, :lmass_s],
		K = df[!, :kcal_per_g_s], NC = df[!, :neocortex_perc_s]);
end;

# ╔═╡ 4e59a4d0-6d3d-11eb-1017-6fdad80c1702
stan5_5 = "
data {
 int < lower = 1 > N; // Sample size
 vector[N] K; // Outcome
 vector[N] NC; // Predictor
}

parameters {
 real a; // Intercept
 real bN; // Slope (regression coefficients)
 real < lower = 0 > sigma;    // Error SD
}

model {
  vector[N] mu;               // mu is a vector
  a ~ normal(0, 0.2);           //Priors
  bN ~ normal(0, 0.5);
  sigma ~ exponential(1);
  mu = a + bN * NC;
  K ~ normal(mu , sigma);     // Likelihood
}
";

# ╔═╡ 4e59ded0-6d3d-11eb-33e9-ebe8d1541013
begin
	m5_5s = SampleModel("m5.5", stan5_5)
	rc5_5s = stan_sample(m5_5s; data)
end;

# ╔═╡ 52b02cea-6d3d-11eb-182c-c7850d2d587c
stan5_6 = "
data {
 int < lower = 1 > N; // Sample size
 vector[N] K; // Outcome
 vector[N] M; // Predictor
}

parameters {
 real a; // Intercept
 real bM; // Slope (regression coefficients)
 real < lower = 0 > sigma;    // Error SD
}

model {
  vector[N] mu;               // mu is a vector
  a ~ normal(0, 0.2);           //Priors
  bM ~ normal(0, 0.5);
  sigma ~ exponential(1);
  mu = a + bM * M;
  K ~ normal(mu , sigma);     // Likelihood
}
";

# ╔═╡ 84ff396e-6d3d-11eb-03bd-21dde805868a
begin
	m5_6s = SampleModel("m5.6", stan5_6);
	rc5_6s = stan_sample(m5_6s; data)
end;

# ╔═╡ 0ba1c21a-fdaa-11ea-009d-5dcaf34749be
stan5_7 = "
data {
 int < lower = 1 > N; // Sample size
 vector[N] K; // Outcome
 vector[N] NC; // Predictor
 vector[N] M; // Predictor
}

parameters {
 real a; // Intercept
 real bM; // Slope (regression coefficients)
 real bN; // Slope (regression coefficients)
 real < lower = 0 > sigma;    // Error SD
}

model {
  vector[N] mu;               // mu is a vector
  a ~ normal(0, 0.2);           //Priors
  bN ~ normal(0, 0.5);
  bM ~ normal(0, 0.5);
  sigma ~ exponential(1);
  mu = a + bM * M + bN * NC;
  K ~ normal(mu , sigma);     // Likelihood
}
";

# ╔═╡ 0bacf8a6-fdaa-11ea-2c4e-ed3ec21de17e
begin
	m5_7s = SampleModel("m5.7", stan5_7)
	rc5_7s = stan_sample(m5_7s; data)
end;

# ╔═╡ 0bc2f976-fdaa-11ea-0212-29e5fd84c264
if success(rc5_5s) && success(rc5_6s) && success(rc5_7s)
	(s1, p1) = plot_model_coef([m5_5s, m5_6s, m5_7s], [:a, :bN, :bM];
		title="Masked relationships: bN & bM Normal estimates")
	p1
end

# ╔═╡ e74a9ef6-00eb-11eb-3520-a75d0472d1d9
s1

# ╔═╡ 0bce9330-fdaa-11ea-03be-395a30d110ea
md"## End of clip-05-38s.jl"

# ╔═╡ Cell order:
# ╟─bd517e12-fda8-11ea-2835-77cfacec77f7
# ╠═0b91d166-fdaa-11ea-3dac-ebd4d51a729f
# ╠═0b92178e-fdaa-11ea-3be6-27667afc3797
# ╠═d95b1330-6d3c-11eb-0fea-0771c632bafb
# ╠═4e59a4d0-6d3d-11eb-1017-6fdad80c1702
# ╠═4e59ded0-6d3d-11eb-33e9-ebe8d1541013
# ╠═52b02cea-6d3d-11eb-182c-c7850d2d587c
# ╠═84ff396e-6d3d-11eb-03bd-21dde805868a
# ╠═0ba1c21a-fdaa-11ea-009d-5dcaf34749be
# ╠═0bacf8a6-fdaa-11ea-2c4e-ed3ec21de17e
# ╠═0bc2f976-fdaa-11ea-0212-29e5fd84c264
# ╠═e74a9ef6-00eb-11eb-3520-a75d0472d1d9
# ╟─0bce9330-fdaa-11ea-03be-395a30d110ea


text:
macro log(ex)
  :(begin
    local starttime = time()
    local result = $(esc(ex))
    println("Computed $result in $(time()-starttime)s")
  end)
end

starttime = 5000            # Just to illustrate hygiene
@log det(eye(starttime))    # Will make a 5000x5000 matrix
@assert starttime == 5000   # Not destroyed by the macro!

ext: jl


text:
"""
Method used for handling complementarity constraints `s[i] ⋅ λ[i] = 0`
Must implement:
```
add_complementarity_constraint(m, cm::ComplementarityMethod, s, λ)
```
"""
abstract type ComplementarityMethod end

"""
Handle complementarity constraints with
Special Ordered Sets of type 1
"""
struct SOS1Complementarity <: ComplementarityMethod end

struct BoundComplementarity{MD,MP} <: ComplementarityMethod
    Md::MD
    Mp::MP
    function BoundComplementarity(md::MD, mp::MP) where {MD <: Union{AbstractVector,Real}, MP <: Union{AbstractVector,Real}}
        return new{MD,MP}(md,mp)
    end
end

"""
Add complementarity constraints to the JuMP model `m` for each pair
`(s[i],λ[i])` with the corresponding complementarity method.
```
add_complementarity_constraint(m, cm::ComplementarityMethod, s, λ, y, σ)
```
"""
function add_complementarity_constraint end

"""
    add_complementarity_constraint(m, ::SOS1Complementarity, s, λ, y, σ)

Implements complementarity constraints using special ordered sets 1 (SOS1).
"""
function add_complementarity_constraint(m, ::SOS1Complementarity, s, λ, y, σ)
    @constraint(m, rhs_sos_constraints[i=eachindex(s)], [λ[i], s[i]] in MOI.SOS1([0.4, 0.6]))
    @constraint(m, nonnegative_sos_constraints[j=eachindex(y)], [σ[j], y[j]] in MOI.SOS1([0.4, 0.6]))
    return nothing
end

"""
Implements complementarity constraints using big-M type constraints
Introduces binary variables:
```
active_constraint[i] == 0 <=> λ[i] == 0
active_constraint[i] == 1 <=> s[i] == 0
variable_bound[j] == 0 <=> σ[j] == 0
variable_bound[j] == 1 <=> y[j] == 0
```
"""
function add_complementarity_constraint(m, bc::BoundComplementarity, s, λ, y, σ)
    ml = length(s)
    nl = length(y)
    @variable(m, active_constraint[1:ml], Bin)
    @variable(m, variable_bound[1:ml], Bin)
    add_bigm_primalbounds(m, bc, active_constraint, variable_bound, s, y)
    add_bigm_dualbounds(m, bc, active_constraint, variable_bound, λ, σ)
    return (active_constraint, variable_bound)
end

"""
Add primal bounds with one bound for each element
"""
function add_bigm_primalbounds(m, bc::BoundComplementarity{MD,MP}, active_constraint, variable_bound, s, y) where {MD,MP<:AbstractVector{<:Real}}
    ml = length(s)
    length(bc.Mp) == ml + length(y) || throw(DimensionMismatch("Primal bound vector"))
    @constraint(m, [i=1:ml],
        s[i] <= bc.Mp[i] * (1. - active_constraint[i])
    )
    @constraint(m, [j=eachindex(y)],
        y[j] <= bc.Mp[j+ml] * (1. - variable_bound[j])
    )
    return nothing
end

"""
Add primal bounds with the same bound for all elements
"""
function add_bigm_primalbounds(m, bc::BoundComplementarity{MD,MP}, active_constraint, variable_bound, s, y) where {MD,MP<:Real}
    @constraint(m, [i=eachindex(s)],
        s[i] <= bc.Mp * (1. - active_constraint[i])
    )
    @constraint(m, [j=eachindex(y)],
        y[j] <= bc.Mp * (1. - variable_bound[j])
    )
    return nothing
end

"""
Add dual bounds with one bound for each element
"""
function add_bigm_dualbounds(m, bc::BoundComplementarity{MD,<:Any}, active_constraint, variable_bound, λ, σ) where {MD<:AbstractVector{<:Real}}
    ml = length(λ)
    length(bc.Md) == ml + length(σ) || throw(DimensionMismatch("Dual bound vector"))
    @constraint(m, [i=1:ml],
        λ[i] <= bc.Md[i] * active_constraint[i]
    )
    @constraint(m, [j=1:length(σ)],
        σ[j] <= bc.Md[ml+j] * variable_bound[j]
    )
    return nothing
end

"""
Add dual bounds with the same bound for all elements
"""
function add_bigm_dualbounds(m, bc::BoundComplementarity{MD,<:Any}, active_constraint, variable_bound, λ, σ) where {MD<:Real}
    @constraint(m, [i=1:length(λ)],
        λ[i] <= bc.Md * active_constraint[i]
    )
    @constraint(m, [j=1:length(σ)],
        σ[j] <= bc.Md * variable_bound[j]
    )
    return nothing
end


text:
using Test
using KeboolaConnectionComponent
import JSON

function createconfig(data)
    path = mktempdir();
    ENV["KBC_DATADIR"] = path
    open(path * "/config.json", "w") do file
        JSON.print(file, data, 4)
    end
    path
end

function getconfigdata()
    Dict(
        "storage" => Dict(
            "input" => Dict(
                "tables" => [
                    Dict(
                        "source" => "in.c-main.data",
                        "destination" => "sample.csv"
                    )
                ]
            ),
            "output" => Dict(
                "tables" => [
                    Dict(
                        "source" => "sample.csv",
                        "destination" => "out.c-main.data"
                    )
                ]
            )
        ),
        "parameters" => Dict(
            "packages" => ["matrix"],
            "script" => ["this is a syntax error"]
        )
    )
end

@testset "datadir" begin
    @test KeboolaConnectionComponent.datadir() == "/data/"

    ENV["KBC_DATADIR"] = "/my-data"
    @test KeboolaConnectionComponent.datadir() == "/my-data/"
    delete!(ENV, "KBC_DATADIR")

    ENV["KBC_DATADIR"] = "/my-data/"
    @test KeboolaConnectionComponent.datadir() == "/my-data/"
    delete!(ENV, "KBC_DATADIR")
end

@testset "config.file" begin
    path = createconfig(Dict("a" => "b"))
    ENV["KBC_DATADIR"] = path
    @test KeboolaConnectionComponent.config().action == "run"
    delete!(ENV, "KBC_DATADIR")

    path = mktempdir();
    ENV["KBC_DATADIR"] = path
    open(path * "/config.json", "w") do file
        write(file, "not a valid json")
    end
    @test_throws ErrorException KeboolaConnectionComponent.config().action == "run"
    delete!(ENV, "KBC_DATADIR")

    @test_throws SystemError KeboolaConnectionComponent.config().action == "run"
end

@testset "config.read" begin
    path = createconfig(getconfigdata())
    ENV["KBC_DATADIR"] = path
    config = KeboolaConnectionComponent.config()
    @test config.action == "run"
    @test config.parameters == Dict(
        "packages" => ["matrix"],
        "script" => ["this is a syntax error"]
    )
    @test config.storage == Dict(
        "input" => Dict(
            "tables" => [
                Dict(
                    "source" => "in.c-main.data",
                    "destination" => "sample.csv"
                )
            ]
        ),
        "output" => Dict(
            "tables" => [
                Dict(
                    "source" => "sample.csv",
                    "destination" => "out.c-main.data"
                )
            ]
        )
    )
    @test config.authorization == Dict()
    delete!(ENV, "KBC_DATADIR")
end

max_stars_repo_name: keboola/julia-component

max_issues_repo_name: keboola/julia-component

max_forks_repo_name: keboola/julia-component


text:
global seed = nothing

function CRRao_seed(x)
    global seed = x
end


text: println(1 +)


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

@doc raw"""IngressTLS describes the transport layer security associated with an Ingress.

    IoK8sApiNetworkingV1beta1IngressTLS(;
        hosts=nothing,
        secretName=nothing,
    )

    - hosts::Vector{String} : Hosts are a list of hosts included in the TLS certificate. The values in this list must match the name/s used in the tlsSecret. Defaults to the wildcard host setting for the loadbalancer controller fulfilling this Ingress, if left unspecified.
    - secretName::String : SecretName is the name of the secret used to terminate SSL traffic on 443. Field is left optional to allow SSL routing based on SNI hostname alone. If the SNI host in a listener conflicts with the \"Host\" header field used by an IngressRule, the SNI host is used for termination and value of the Host header is used for routing.
"""
mutable struct IoK8sApiNetworkingV1beta1IngressTLS <: SwaggerModel
    hosts::Any # spec type: Union{ Nothing, Vector{String} } # spec name: hosts
    secretName::Any # spec type: Union{ Nothing, String } # spec name: secretName

    function IoK8sApiNetworkingV1beta1IngressTLS(;hosts=nothing, secretName=nothing)
        o = new()
        validate_property(IoK8sApiNetworkingV1beta1IngressTLS, Symbol("hosts"), hosts)
        setfield!(o, Symbol("hosts"), hosts)
        validate_property(IoK8sApiNetworkingV1beta1IngressTLS, Symbol("secretName"), secretName)
        setfield!(o, Symbol("secretName"), secretName)
        o
    end
end # type IoK8sApiNetworkingV1beta1IngressTLS

const _property_map_IoK8sApiNetworkingV1beta1IngressTLS = Dict{Symbol,Symbol}(Symbol("hosts")=>Symbol("hosts"), Symbol("secretName")=>Symbol("secretName"))
const _property_types_IoK8sApiNetworkingV1beta1IngressTLS = Dict{Symbol,String}(Symbol("hosts")=>"Vector{String}", Symbol("secretName")=>"String")
Base.propertynames(::Type{ IoK8sApiNetworkingV1beta1IngressTLS }) = collect(keys(_property_map_IoK8sApiNetworkingV1beta1IngressTLS))
Swagger.property_type(::Type{ IoK8sApiNetworkingV1beta1IngressTLS }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiNetworkingV1beta1IngressTLS[name]))}
Swagger.field_name(::Type{ IoK8sApiNetworkingV1beta1IngressTLS }, property_name::Symbol) =  _property_map_IoK8sApiNetworkingV1beta1IngressTLS[property_name]

function check_required(o::IoK8sApiNetworkingV1beta1IngressTLS)
    true
end

function validate_property(::Type{ IoK8sApiNetworkingV1beta1IngressTLS }, name::Symbol, val)
end


text:
using DataFrames
using Test

m = test_page_model()
include("../src/components/TotalAbatementCosts.jl")

add_comp!(m, TotalAbatementCosts)

set_param!(m, :TotalAbatementCosts, :pop_population, readpagedata(m, "test/validationdata/pop_population.csv"))
set_param!(m, :TotalAbatementCosts, :tc_totalcosts_co2, readpagedata(m, "test/validationdata/tc_totalcosts_co2.csv"))
set_param!(m, :TotalAbatementCosts, :tc_totalcosts_ch4, readpagedata(m, "test/validationdata/tc_totalcosts_ch4.csv"))
set_param!(m, :TotalAbatementCosts, :tc_totalcosts_n2o, readpagedata(m, "test/validationdata/tc_totalcosts_n2o.csv"))
set_param!(m, :TotalAbatementCosts, :tc_totalcosts_linear, readpagedata(m, "test/validationdata/tc_totalcosts_linear.csv"))

run(m)

# Generated data
abate_cost = m[:TotalAbatementCosts, :tct_totalcosts]
abate_cost_per_cap = m[:TotalAbatementCosts, :tct_per_cap_totalcostspercap]

# Recorded data
cost_compare = readpagedata(m, "test/validationdata/tct_totalcosts.csv")
cost_cap_compare = readpagedata(m, "test/validationdata/tct_per_cap_totalcostspercap.csv")

@test abate_cost ≈ cost_compare rtol=1e-4
@test abate_cost_per_cap ≈ cost_cap_compare rtol=1e-7


text:
using Random
using Distributions
using MultiAgentPathFinding
using MultiAgentAllocationTransit
using Statistics
using JSON

## IGNORE - Just used to get some alpha beta values for supporting the theorem.

rng = MersenneTwister(2345)

const params_file = ARGS[1]
city_params = parse_city_params(params_file)

# const out_file_pref = ARGS[2]

lat_dist = Uniform(city_params.lat_start, city_params.lat_end)
lon_dist = Uniform(city_params.lon_start, city_params.lon_end)

# N_agents = N_depots
const N_DEPOTS = parse(Int64, ARGS[2])
const depots = [LatLonCoords((lat = rand(rng, lat_dist), lon = rand(rng, lon_dist))) for i = 1:N_DEPOTS]
const N_AGENTS = N_DEPOTS

# Big numbers of depots
const N_SITE_VALS = [200, 500, 1000]

for N_SITES in N_SITE_VALS

    sites = [LatLonCoords((lat = rand(rng, lat_dist), lon = rand(rng, lon_dist))) for i = 1:N_SITES]

    depot_sites = vcat(depots, sites)
    cost_fn(i, j) = MultiAgentAllocationTransit.distance_lat_lon_euclidean(depot_sites[i], depot_sites[j])

    agent_tours, max_tour_cost, obj_value, alpha, beta = task_allocation(N_DEPOTS, N_SITES, N_AGENTS, depot_sites, cost_fn)
    n_true_agents = length(agent_tours)

    println("For $(N_SITES) sites:")
    println("Max tour cost - $(max_tour_cost); OPTLB - $(obj_value); (alpha,beta,plus) : $(alpha), $(beta), $(alpha + beta)")
    approx_factor = max_tour_cost*n_true_agents/obj_value
    println("Approx factor - $(approx_factor)")
end


text:
#### Canned Callbacks ####

"""
    variable_fixing(; lag=2, eq_tol=1e-8)::Callback

Implementation of the variable fixing convergence acceleration heuristic in section 2.2 of (Watson & Woodruff 2010).
"""
function variable_fixing(; lag=2, eq_tol=1e-8)::Callback
    ext = Dict{Symbol,Any}()
    ext[:lag] = lag
    ext[:eq_tol] = eq_tol
    return Callback("variable_fixing",
                    _variable_fixing,
                    _variable_fixing_init,
                    ext)
end

function _variable_fixing_init(external::Dict{Symbol,Any}, phd::PHData)

    # Between iterations
    external[:value_count] = Dict{XhatID,Int}(
        xhid => 0 for xhid in keys(consensus_variables(phd))
    )
    external[:value] = Dict{XhatID,Float64}(
        xhid => value(xhat) for (xhid,xhat) in pairs(consensus_variables(phd))
    )
    external[:fixed] = Set{XhatID}()

    return
end

function _variable_fixing(external::Dict{Symbol,Any},
                          phd::PHData,
                          winf::WorkerInf,
                          niter::Int)::Bool

    lag = external[:lag]
    nscen = length(scenarios(phd))
    limit = lag * nscen

    if niter >= limit

        values = external[:value]
        counts = external[:value_count]
        fixed = external[:fixed]
        tol = external[:eq_tol]
        to_fix = Dict{ScenarioID,Dict{VariableID,Float64}}()

        for (xhid, xhat) in pairs(consensus_variables(phd))

            if xhid in fixed
                continue
            end

            is_equal = true
            for vid in variables(xhat)
                is_equal &= isapprox(value(xhat), branch_value(phd, vid), atol=tol)
            end

            if is_equal

                counts[xhid] = nrepeats = counts[xhid] + 1

                if nrepeats >= limit

                    for vid in variables(xhat)

                        scen = scenario(vid)

                        if !haskey(to_fix, scen)
                            to_fix[scen] = Dict{VariableID,Float64}()
                        end

                        to_fix[scen][vid] = value(xhat)
                    end

                    push!(fixed, xhid)

                end

            else

                values[xhid] = value(xhat)
                counts[xhid] = 1

            end

        end

        for (scen, value_dict) in pairs(to_fix)
            apply_to_subproblem(fix_variables, phd, winf, scen, (value_dict,))
        end

    end

    return true
end

"""
    mean_deviation(;tol::Float64=1e-8,
                   save_deviations::Bool=false
                   )::Callback

Implementation of a termination criterion given in section 2.3 of (Watson & Woodruff 2010). There it is called 'td'.
"""
function mean_deviation(;tol::Float64=1e-8,
                        save_deviations::Bool=false
                        )::Callback
    ext = Dict{Symbol,Any}(:tol => tol, :save => save_deviations)

    if save_deviations
        ext[:deviations] = Dict{Int,Float64}()
    end

    return Callback("mean_deviation",
                    _mean_deviation,
                    ext
                    )
end

function _mean_deviation(external::Dict{Symbol,Any},
                         phd::PHData,
                         winf::WorkerInf,
                         niter::Int)::Bool

    nscen = length(scenarios(phd))

    td = 0.0
    for (xhid, xhat) in consensus_variables(phd)
        deviation = 0.0
        for vid in variables(xhat)
            deviation += abs(branch_value(phd, vid) - value(xhat))
        end
        td += deviation / (value(xhat))
    end
    td /= nscen

    if external[:save]
        external[:deviations][niter] = td
    end

    return external[:tol] < td
end


text:
println("\n\nmake_d_location: start")

prepend!(LOAD_PATH, ["Project.toml"])
import LibPQ

DISASTER_PASSWORD = read("./etc/disaster-pass", String)

postgres = LibPQ.Connection("host=127.0.0.1 port=5432 dbname=disaster user=disaster password=$DISASTER_PASSWORD")

sql =
"""
drop table if exists public.d_location;
create table if not exists public.d_location (
    d_location_id  integer primary key,
    state_fips     text not null,
    state_name     text,
    county_fips    text not null,
    county_name    text
);

truncate public.d_location;
insert into public.d_location (
    d_location_id,
    state_fips,
    state_name,
    county_fips,
    county_name
)
select G.ogc_fid, G.statefp, S.state_name, G.countyfp, G.name
from tl_2015_us_county G
left join s_state_geocode S on S.state_fips = G.statefp;

-- add some values to fill in the gaps
update public.d_location set state_name = 'Puerto Rico' where state_fips = '72';
"""
LibPQ.execute(postgres, sql)
LibPQ.close(postgres)

println("make_d_location: stop")


text:
module OpenGL

#must use GLUT for platform independence
using GLUT

# To get valid gl function pointers, the glut/opengl context needs to be initialized
glutInit()
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE | GLUT_ALPHA)
glutInitWindowPosition(0, 0)
glutInitWindowSize(1,1)
window = glutCreateWindow("dummy")
#I'd love to destroy the window, but that gives problems for later calls to createWindow
glutHideWindow()

#macro for the glFunction declaration
macro createOpenGLFun(cFun)
    cName = cFun.args[1].args[1]
    arguments = map(function (arg)
                        if isa(arg, Symbol)
                            arg = Expr(__ofTypeSym, arg)
                        end
                        return arg
                    end, cFun.args[1].args[2:end])

    # Get info out of arguments of `cFun`
    argumentNames = map(arg->arg.args[1], arguments)
    returnType    = cFun.args[2]
    inputTypes    = map(arg->arg.args[2], arguments)
    # Construct the result.
    functionPtr = glutGetProcAddress(cName)
    if functionPtr == C_NULL
        println("Warning: returned nullPointer -- Function:$(string(cFun)) not supported by OpenGL Driver")
        return ""
    end
    body = Expr(:ccall, functionPtr, returnType, Expr(:tuple,inputTypes...), argumentNames...)
    ret  = Expr(:function, Expr(:call, cName, argumentNames...), body)
    return esc(ret)
end
glDefinitionFolder = "definitions/"
#include all OpenGL types
include(glDefinitionFolder*"types.jl")

#find out the OpenGL version
@createOpenGLFun glGetString(name::Uint16)::Ptr{Cuchar}

#might not work with old graphic cards... Can't test this.
version = glGetString(0x1F02)::Ptr{Uint8}
version = bytestring(convert(Ptr{Uint8}, version))
println("using OpenGL version: $(version)")
global OpenGLver = float(match(r"[1-5]+\.[0-5]*", version).match)

#include the right OpenGL definitions
include(glDefinitionFolder*"glu.jl")
if OpenGLver >= 1.0 && OpenGLver < 2.1
    include(glDefinitionFolder*"gl10.jl")
elseif OpenGLver >= 2.0 && OpenGLver < 3.0
    include(glDefinitionFolder*"gl21.jl")
elseif OpenGLver >= 3.0 && OpenGLver < 4.2
    include(glDefinitionFolder*"gl33.jl")
elseif OpenGLver >= 4.2 && OpenGLver < 4.3
    include(glDefinitionFolder*"gl42.jl")
elseif OpenGLver >= 4.3
    include(glDefinitionFolder*"gl43.jl")
else
    error("OpenGL.jl: unknown OpenGL version: $(version)")
end

end #Module OpenGL


text:
add_brackets(arr::AbstractArray, vars) = [add_brackets(element, vars) for element in arr]

add_brackets(s::Any, vars) = return s

function add_brackets(ex::Expr, vars)
    ex = postwalk(x -> x in vars ? "\\left[ $(convertSubscript(x)) \\right]" : x, ex)
    return ex
end

function _writetex(s::LaTeXString; name=tempname(), command="\\Large")
    doc = """
    \\documentclass[varwidth=100cm]{standalone}
    \\usepackage{amssymb}
    \\usepackage{amsmath}
    $(occursin("\\ce{", s) ? "\\usepackage{mhchem}" : "")
    \\begin{document}
    {
        $command
        $s
    }
    \\end{document}
    """
    doc = replace(doc, "\\begin{align}"=>"\\[\n\\begin{aligned}")
    doc = replace(doc, "\\end{align}"=>"\\end{aligned}\n\\]")
    doc = replace(doc, "\\require{mhchem}\n"=>"")
    open("$(name).tex", "w") do f
        write(f, doc)
    end

    return nothing
end

function _openfile(name; ext="pdf")
    if Sys.iswindows()
        run(`cmd /c "start $(name).$(ext)"`, wait=false)
    elseif Sys.islinux()
        run(`xdg-open $(name).$(ext)`, wait=false)
    elseif Sys.isapple()
        run(`open $(name).$(ext)`, wait=false)
    elseif Sys.isbsd()
        run(`xdg-open $(name).$(ext)`, wait=false)
    end

    return nothing
end

"""
    render(::LaTeXString[, ::MIME"mime"]; debug=false, name=tempname(), command="\\Large", callshow=true, open=true)

Display a standalone document with the given input. Supported MIME-type strings are
"application/pdf" (default), "application/x-dvi", "image/png" and "image/svg".
"""
function render(s::LaTeXString; kwargs...)
    return render(s, best_displayable(); kwargs...)
end

function best_displayable()
    priority_list = [
        MIME("juliavscode/html"),
        MIME("application/pdf"),
        MIME("application/x-dvi"),
        MIME("image/svg"),
        MIME("image/png"),
    ]
    for mime_type in priority_list
        displayable(mime_type) && return mime_type
    end
    return MIME("image/pdf")
end

function html_wrap(s::LaTeXString; scale=1.1, kwargs...)
    import_str = """
        <script>
            MathJax = {
                tex: {
                    displayMath: [['\$', '\$'], ['\\\\[', '\\\\]']]
                },
                chtml: {
                    scale: $scale
                },
                svg: {
                    scale: $scale
                }
            };
        </script>
        <script src="/js/mathjax/tex-chtml.js" id="MathJax-script" async></script>
        <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
        <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
        """
    return import_str * s.s
end

# render(s::LaTeXString, mime::MIME"juliavscode/html"; kwargs...) = render(stdout, mime; kwargs...)
function render(s::LaTeXString, mime::MIME"juliavscode/html"; kwargs...)
      display(mime, html_wrap(s; kwargs...))
end

function render(s::LaTeXString, ::MIME"application/pdf"; debug=false, name=tempname(), command="\\Large", open=true)
    _writetex(s; name=name, command=command)

    cd(dirname(name)) do
        cmd = `lualatex --interaction=batchmode $(name).tex`
        debug || (cmd = pipeline(cmd, devnull))
        run(cmd)
    end

    # `display(MIME("application/pdf")` is generally not defined even though
    # `displayable(MIME("application/pdf")` returns `true`.
    #
    # if callshow && displayable(MIME("application/pdf"))
    #     Base.open("$name.pdf") do f
    #         display(MIME("application/pdf"), read(f, String))
    #     end
    if open
        _openfile(name; ext="pdf")
    end

    return nothing
end

function render(s::LaTeXString, ::MIME"application/x-dvi"; debug=false, name=tempname(), command="\\Large", open=true)
    _writetex(s; name=name, command=command)

    cd(dirname(name)) do
        cmd = `dvilualatex --interaction=batchmode $(name).tex`
        debug || (cmd = pipeline(cmd, devnull))
        run(cmd)
    end

    # `display(MIME("application/x-dvi")` is generally not defined even though
    # `displayable(MIME("application/x-dvi")` returns `true`.
    #
    # if callshow && displayable(MIME("application/x-dvi"))
    #     Base.open("$name.dvi") do f
    #         display(MIME("application/x-dvi"), read(f, String))
    #     end
    if open
        _openfile(name; ext="dvi")
    end

    return nothing
end

function render(s::LaTeXString, ::MIME"image/png"; debug=false, name=tempname(), command="\\Large", callshow=true, open=true, dpi=300)
    render(s, MIME("application/x-dvi"); debug=debug, name=name, command=command, open=false)

    cmd = `dvipng -bg Transparent -D $(dpi) -T tight -o $(name).png $(name).dvi`
    debug || (cmd = pipeline(cmd, devnull))
    run(cmd)

    if callshow && displayable(MIME("image/png"))
        Base.open("$name.png") do f
            display(MIME("image/png"), read(f))
        end
    elseif open
        _openfile(name; ext="png")
    end

    return nothing
end

function render(s::LaTeXString, ::MIME"image/svg"; debug=false, name=tempname(), command="\\Large", callshow=true, open=true)
    render(s, MIME("application/x-dvi"); debug=debug, name=name, command=command, open=false)

    cmd = `dvisvgm -n -v 0 -o $(name).svg $(name).dvi`
    debug || (cmd = pipeline(cmd, devnull))
    run(cmd)

    # `displayable(MIME("image/svg"))` returns `true` even in a textual
    # context (e.g., in the REPL), but `display(MIME("image/svg+xml"), ...)`
    # is the one normally defined.
    if callshow && displayable(MIME("image/svg"))
        Base.open("$name.svg") do f
            display(MIME("image/svg+xml"), read(f, String))
        end
    elseif open
        _openfile(name; ext="svg")
    end

    return nothing
end

function expr_to_array(ex)
    ex.head == :typed_vcat && (ex = Expr(:vcat, ex.args[2:end]...))
    ex.head == :typed_hcat && (ex = Expr(:hcat, ex.args[2:end]...))
    ex.head == :ref && (ex = Expr(:vect, ex.args[2:end]...))
    ## If it is a matrix
    if ex.args[1] isa Expr && ex.args[1].head == :row
        return eval(ex.head)(map(y -> permutedims(y.args), ex.args)...)
    else
        if ex.head == :hcat
            return reduce(hcat, ex.args)
        elseif ex.head in [:vcat, :vect]
            return reduce(vcat, ex.args)
        end
    end
end


text:
print("##########################\n")
print(" Using cache: $(usecache)\n")
print("##########################\n")

if usecache
    BusinessDays.initcache(all_calendars_vec)
end

################
# bdays.jl
################
#export
#   isweekend, isbday, tobday, advancebdays, bdays

dt_tuesday = Dates.Date(2015,06,23)
dt_wednesday = Dates.Date(2015, 06, 24)
dt_thursday = Dates.Date(2015, 06, 25)
dt_friday = Dates.Date(2015, 06, 26)
dt_saturday = Dates.Date(2015, 06, 27)
dt_sunday = Dates.Date(2015, 06, 28)
dt_monday = Dates.Date(2015, 06, 29)
dt_newyears = Dates.Date(2016,1,1)

# Bounds tests
if !usecache
    # this should work
    isbday(hc_brazil, Dates.Date(1600,2,1))
    isbday(hc_brazil, Dates.Date(3000,2,1))
    bdays(hc_brazil, Dates.Date(1600,2,1), Dates.Date(1600, 2, 5))
    bdays(hc_brazil, Dates.Date(3000,2,1), Dates.Date(3000, 2, 5))
    bdayscount(hc_brazil, Dates.Date(1600,2,1), Dates.Date(1600, 2, 5))
    bdayscount(hc_brazil, Dates.Date(3000,2,1), Dates.Date(3000, 2, 5))
else
    #this should not work
    @test_throws AssertionError isbday(hc_brazil, Dates.Date(1600,2,1))
    @test_throws AssertionError isbday(hc_brazil, Dates.Date(3000,2,1))
    @test_throws AssertionError bdays(hc_brazil, Dates.Date(1600,2,1), Dates.Date(1600, 2, 5))
    @test_throws AssertionError bdays(hc_brazil, Dates.Date(3000,2,1), Dates.Date(3000, 2, 5))
    @test_throws AssertionError bdayscount(hc_brazil, Dates.Date(1600,2,1), Dates.Date(1600, 2, 5))
    @test_throws AssertionError bdayscount(hc_brazil, Dates.Date(3000,2,1), Dates.Date(3000, 2, 5))
end

@test_throws ErrorException isbday(:UnknownCalendar, Dates.Date(2016,1,1))
@test_throws ErrorException isbday("UnknownCalendar", Dates.Date(2016,1,1))

@test isweekend(dt_tuesday) == false
@test isweekend(dt_wednesday) == false
@test isweekend(dt_thursday) == false
@test isweekend(dt_friday) == false
@test isweekend(dt_saturday) == true
@test isweekend(dt_sunday) == true
@test isweekend(dt_monday) == false

@test isweekday(dt_tuesday) == true
@test isweekday(dt_wednesday) == true
@test isweekday(dt_thursday) == true
@test isweekday(dt_friday) == true
@test isweekday(dt_saturday) == false
@test isweekday(dt_sunday) == false
@test isweekday(dt_monday) == true

@test isbday(hc_brazil, dt_friday) == true
@test isbday(hc_brazil, dt_saturday) == false
@test isbday(hc_brazil, dt_sunday) == false
@test isbday(hc_brazil, dt_monday) == true

@test isholiday(hc_brazil, dt_friday) == false
@test isholiday(hc_brazil, dt_saturday) == false
@test isholiday(hc_brazil, dt_sunday) == false
@test isholiday(hc_brazil, dt_monday) == false
@test isholiday(hc_brazil, dt_newyears) == true

# Symbol
@test isholiday(:Brazil, dt_friday) == false
@test isholiday(:Brazil, dt_saturday) == false
@test isholiday(:Brazil, dt_sunday) == false
@test isholiday(:Brazil, dt_monday) == false
@test isholiday(:Brazil, dt_newyears) == true

# String
@test isholiday("Brazil", dt_friday) == false
@test isholiday("Brazil", dt_saturday) == false
@test isholiday("Brazil", dt_sunday) == false
@test isholiday("Brazil", dt_monday) == false
@test isholiday("Brazil", dt_newyears) == true

@test isholiday(BusinessDays.NullHolidayCalendar(), Dates.Date(2016,9,25)) == false
@test isholiday(:NullHolidayCalendar, Dates.Date(2016,9,25)) == false
@test isholiday("NullHolidayCalendar", Dates.Date(2016,9,25)) == false
@test isbday(BusinessDays.NullHolidayCalendar(), Dates.Date(2016,9,25)) == true
@test isbday(:NullHolidayCalendar, Dates.Date(2016,9,25)) == true
@test isbday("NullHolidayCalendar", Dates.Date(2016,9,25)) == true
@test bdayscount(:NullHolidayCalendar, Dates.Date(2016,9,25), Dates.Date(2016,9,28)) == 3
@test bdays(:NullHolidayCalendar, Dates.Date(2016,9,25), Dates.Date(2016,9,28)) == Dates.Day(3)

@test isholiday(BusinessDays.WeekendsOnly(), Dates.Date(2016,9,25)) == false
@test isholiday(:WeekendsOnly, Dates.Date(2016,9,25)) == false
@test isholiday("WeekendsOnly", Dates.Date(2016,9,25)) == false
@test isbday(BusinessDays.WeekendsOnly(), Dates.Date(2016,9,25)) == false
@test isbday(:WeekendsOnly, Dates.Date(2016,9,25)) == false
@test isbday("WeekendsOnly", Dates.Date(2016,9,25)) == false
@test bdayscount(:WeekendsOnly, Dates.Date(2016,9,25), Dates.Date(2016,9,28)) == 2

function test_bdays(cal, d0::Dates.Date, d1::Dates.Date, expected_result::Integer)
    @test bdays(cal, d0, d1) == Dates.Day(expected_result)
    if d0 != d1
        @test bdays(cal, d1, d0) == Dates.Day(-expected_result)
    end
    nothing
end

function test_bdays(cal,
        d0::Tuple{Int, Int, Int},
        d1::Tuple{Int, Int, Int},
        expected_result::Integer)

    test_bdays(cal, Dates.Date(d0[1], d0[2], d0[3]), Dates.Date(d1[1], d1[2], d1[3]), expected_result)
end

test_bdays(:WeekendsOnly, (2016, 9, 25), (2016, 9, 28), 2)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 9, 2), 5)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 9, 3), 6)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 9, 9), 10)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 9, 10), 11)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 8, 30), 4)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 8, 27), 1)
test_bdays(:WeekendsOnly, (2019, 8, 26), (2019, 8, 26), 0)
test_bdays(:WeekendsOnly, (2019, 8, 19), (2019, 8, 26), 5)
test_bdays(:WeekendsOnly, (2019, 8, 25), (2019, 8, 26), 0)
test_bdays(:WeekendsOnly, (2019, 8, 24), (2019, 8, 25), 0)
test_bdays(:WeekendsOnly, (2019, 8, 24), (2019, 8, 26), 0)
test_bdays(:WeekendsOnly, (2019, 8, 23), (2019, 8, 24), 1)

# Brazil HolidayCalendar tests
@test isbday(hc_brazil, Dates.Date(2014, 12, 31)) == true # wednesday
@test isbday(hc_brazil, Dates.Date(2015, 01, 01)) == false # new year
@test isbday(hc_brazil, Dates.Date(2015, 01, 02)) == true # friday

@test isbday(hc_brazil, Dates.Date(2015, 04, 20)) == true # monday
@test isbday(hc_brazil, Dates.Date(2015, 04, 21)) == false # tiradentes
@test isbday(hc_brazil, Dates.Date(2015, 04, 22)) == true # wednesday

@test isbday(hc_brazil, Dates.Date(2015, 04, 30)) == true # thursday
@test isbday(hc_brazil, Dates.Date(2015, 05, 01)) == false # labor day
@test isbday(hc_brazil, Dates.Date(2015, 05, 02)) == false # saturday

@test isbday(hc_brazil, Dates.Date(2015, 09, 06)) == false # sunday
@test isbday(hc_brazil, Dates.Date(2015, 09, 07)) == false # independence day
@test isbday(hc_brazil, Dates.Date(2015, 09, 08)) == true # tuesday

@test isbday(hc_brazil, Dates.Date(2015, 10, 11)) == false # sunday
@test isbday(hc_brazil, Dates.Date(2015, 10, 12)) == false # Nossa Senhora Aparecida
@test isbday(hc_brazil, Dates.Date(2015, 10, 13)) == true # tuesday

@test isbday(hc_brazil, Dates.Date(2015, 11, 01)) == false # sunday
@test isbday(hc_brazil, Dates.Date(2015, 11, 02)) == false # Finados
@test isbday(hc_brazil, Dates.Date(2015, 11, 03)) == true # tuesday

@test isbday(hc_brazil, Dates.Date(2013, 11, 14)) == true # thursday
@test isbday(hc_brazil, Dates.Date(2013, 11, 15)) == false # Republic
@test isbday(hc_brazil, Dates.Date(2013, 11, 16)) == false # saturday

@test isbday(hc_brazil, Dates.Date(2013, 12, 24)) == true # tuesday
@test isbday(hc_brazil, Dates.Date(2013, 12, 25)) == false # Christmas
@test isbday(hc_brazil, Dates.Date(2013, 12, 26)) == true # thursday

@test isbday(hc_brazil, Dates.Date(2013, 02, 08)) == true # friday
@test isbday(hc_brazil, Dates.Date(2013, 02, 09)) == false # saturday
@test isbday(hc_brazil, Dates.Date(2013, 02, 10)) == false # sunday
@test isbday(hc_brazil, Dates.Date(2013, 02, 11)) == false # segunda carnaval
@test isbday(hc_brazil, Dates.Date(2013, 02, 12)) == false # terca carnaval
@test isbday(hc_brazil, Dates.Date(2013, 02, 13)) == true # wednesday

@test isbday(hc_brazil, Dates.Date(2013, 03, 28)) == true # thursday
@test isbday(hc_brazil, Dates.Date(2013, 03, 29)) == false # sexta-feira santa
@test isbday(hc_brazil, Dates.Date(2013, 03, 30)) == false # saturday

@test isbday(hc_brazil, Dates.Date(2013, 05, 29)) == true # wednesday
@test isbday(hc_brazil, Dates.Date(2013, 05, 30)) == false # Corpus Christi
@test isbday(hc_brazil, Dates.Date(2013, 05, 31)) == true # friday

# Symbol
@test isbday(:Brazil, Dates.Date(2013, 05, 29)) == true # wednesday
@test isbday(:Brazil, Dates.Date(2013, 05, 30)) == false # Corpus Christi
@test isbday(:Brazil, Dates.Date(2013, 05, 31)) == true # friday

# String
@test isbday("Brazil", Dates.Date(2013, 05, 29)) == true # wednesday
@test isbday("Brazil", Dates.Date(2013, 05, 30)) == false # Corpus Christi
@test isbday("Brazil", Dates.Date(2013, 05, 31)) == true # friday

# BrazilBMF holiday calendar tests
@test isbday(hc_brazil_bmf, Dates.Date(2017, 11, 19)) == false # sunday
@test isbday(hc_brazil_bmf, Dates.Date(2017, 11, 20)) == false # Conciência Negra (segunda)
@test isbday(hc_brazil_bmf, Dates.Date(2017, 11, 21)) == true # Terca

@test isbday(:BrazilBMF, Dates.Date(2013, 05, 29)) == true # wednesday
@test isbday(:BrazilBMF, Dates.Date(2013, 05, 30)) == false # Corpus Christi (National Holiday)
@test isbday(:BrazilBMF, Dates.Date(2013, 05, 31)) == true # friday

# USSettlement HolidayCaledar tests
# Federal Holidays listed on https://www.opm.gov/policy-data-oversight/snow-dismissal-procedures/federal-holidays/#url=2015
@test isbday(hc_usa, Dates.Date(2014, 12, 31)) == true
@test isbday(hc_usa, Dates.Date(2015, 01, 01)) == false # New Year's Day - Thursday
@test isbday(hc_usa, Dates.Date(2015, 01, 02)) == true

@test isbday(hc_usa, Dates.Date(2015, 01, 18)) == false
@test isbday(hc_usa, Dates.Date(2015, 01, 19)) == false # Birthday of Martin Luther King, Jr. - Monday
@test isbday(hc_usa, Dates.Date(2015, 01, 20)) == true

@test isbday(hc_usa, Dates.Date(1982,01,18)) == true # not a holiday for Martin Luther King

@test isbday(hc_usa, Dates.Date(2015, 02, 15)) == false
@test isbday(hc_usa, Dates.Date(2015, 02, 16)) == false # Washington’s Birthday - Monday
@test isbday(hc_usa, Dates.Date(2015, 02, 17)) == true

@test isbday(hc_usa, Dates.Date(2015, 05, 24)) == false
@test isbday(hc_usa, Dates.Date(2015, 05, 25)) == false # Memorial Day - Monday
@test isbday(hc_usa, Dates.Date(2015, 05, 26)) == true

@test isbday(hc_usa, Dates.Date(2015, 07, 02)) == true
@test isbday(hc_usa, Dates.Date(2015, 07, 03)) == false # Independence Day - Friday
@test isbday(hc_usa, Dates.Date(2015, 07, 04)) == false

@test isbday(hc_usa, Dates.Date(2015, 09, 06)) == false
@test isbday(hc_usa, Dates.Date(2015, 09, 07)) == false # Labor Day - Monday
@test isbday(hc_usa, Dates.Date(2015, 09, 08)) == true

@test isbday(hc_usa, Dates.Date(2015, 10, 11)) == false
@test isbday(hc_usa, Dates.Date(2015, 10, 12)) == false # Columbus Day - Monday
@test isbday(hc_usa, Dates.Date(2015, 10, 13)) == true

@test isbday(hc_usa, Dates.Date(2015, 11, 10)) == true
@test isbday(hc_usa, Dates.Date(2015, 11, 11)) == false # Veterans Day - Wednesday
@test isbday(hc_usa, Dates.Date(2015, 11, 12)) == true

@test isbday(hc_usa, Dates.Date(2015, 11, 25)) == true
@test isbday(hc_usa, Dates.Date(2015, 11, 26)) == false # Thanksgiving Day - Thursday
@test isbday(hc_usa, Dates.Date(2015, 11, 27)) == true

@test isbday(hc_usa, Dates.Date(2015, 12, 24)) == true
@test isbday(hc_usa, Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday(hc_usa, Dates.Date(2015, 12, 26)) == false

@test isbday(hc_usa, Dates.Date(2010, 12, 31)) == false # new years day observed
@test isbday(hc_usa, Dates.Date(2004, 12, 31)) == false # new years day observed

@test isbday(hc_usa, Dates.Date(2013, 03, 28)) == true # thursday
@test isbday(hc_usa, Dates.Date(2013, 03, 29)) == true # good friday
@test isbday(hc_usa, Dates.Date(2013, 03, 30)) == false # saturday

# Symbol
@test isbday(:USSettlement, Dates.Date(2015, 12, 24)) == true
@test isbday(:USSettlement, Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday(:USSettlement, Dates.Date(2015, 12, 26)) == false

# String
@test isbday("USSettlement", Dates.Date(2015, 12, 24)) == true
@test isbday("USSettlement", Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday("USSettlement", Dates.Date(2015, 12, 26)) == false

## USNYSE HolidayCalendar tests

@test isbday(hc_usnyse, Dates.Date(2014, 12, 31)) == true
@test isbday(hc_usnyse, Dates.Date(2015, 01, 01)) == false # New Year's Day - Thursday
@test isbday(hc_usnyse, Dates.Date(2015, 01, 02)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 01, 18)) == false
@test isbday(hc_usnyse, Dates.Date(2015, 01, 19)) == false # Birthday of Martin Luther King, Jr. - Monday
@test isbday(hc_usnyse, Dates.Date(2015, 01, 20)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 02, 15)) == false
@test isbday(hc_usnyse, Dates.Date(2015, 02, 16)) == false # Washington’s Birthday - Monday
@test isbday(hc_usnyse, Dates.Date(2015, 02, 17)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 05, 24)) == false
@test isbday(hc_usnyse, Dates.Date(2015, 05, 25)) == false # Memorial Day - Monday
@test isbday(hc_usnyse, Dates.Date(2015, 05, 26)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 07, 02)) == true
@test isbday(hc_usnyse, Dates.Date(2015, 07, 03)) == false # Independence Day - Friday
@test isbday(hc_usnyse, Dates.Date(2015, 07, 04)) == false

@test isbday(hc_usnyse, Dates.Date(2015, 09, 06)) == false
@test isbday(hc_usnyse, Dates.Date(2015, 09, 07)) == false # Labor Day - Monday
@test isbday(hc_usnyse, Dates.Date(2015, 09, 08)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 10, 11)) == false
@test isbday(hc_usnyse, Dates.Date(2015, 10, 12)) == true # Columbus Day - Monday
@test isbday(hc_usnyse, Dates.Date(2015, 10, 13)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 11, 10)) == true
@test isbday(hc_usnyse, Dates.Date(2015, 11, 11)) == true # Veterans Day - Wednesday
@test isbday(hc_usnyse, Dates.Date(2015, 11, 12)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 11, 25)) == true
@test isbday(hc_usnyse, Dates.Date(2015, 11, 26)) == false # Thanksgiving Day - Thursday
@test isbday(hc_usnyse, Dates.Date(2015, 11, 27)) == true

@test isbday(hc_usnyse, Dates.Date(2015, 12, 24)) == true
@test isbday(hc_usnyse, Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday(hc_usnyse, Dates.Date(2015, 12, 26)) == false

@test isbday(hc_usnyse, Dates.Date(2010, 12, 31)) == true # Friday before new years
@test isbday(hc_usnyse, Dates.Date(2004, 12, 31)) == true # Friday before new years

@test isbday(hc_usnyse, Dates.Date(2013, 03, 28)) == true # thursday
@test isbday(hc_usnyse, Dates.Date(2013, 03, 29)) == false # good friday
@test isbday(hc_usnyse, Dates.Date(2013, 03, 30)) == false # saturday

# Symbol
@test isbday(:USNYSE, Dates.Date(2015, 12, 24)) == true
@test isbday(:USNYSE, Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday(:USNYSE, Dates.Date(2015, 12, 26)) == false

# String
@test isbday("USNYSE", Dates.Date(2015, 12, 24)) == true
@test isbday("USNYSE", Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday("USNYSE", Dates.Date(2015, 12, 26)) == false

## USGovernmentBond HolidayCalendar tests
@test isbday(hc_usgovbond, Dates.Date(2014, 12, 31)) == true
@test isbday(hc_usgovbond, Dates.Date(2015, 01, 01)) == false # New Year's Day - Thursday
@test isbday(hc_usgovbond, Dates.Date(2015, 01, 02)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 01, 18)) == false
@test isbday(hc_usgovbond, Dates.Date(2015, 01, 19)) == false # Birthday of Martin Luther King, Jr. - Monday
@test isbday(hc_usgovbond, Dates.Date(2015, 01, 20)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 02, 15)) == false
@test isbday(hc_usgovbond, Dates.Date(2015, 02, 16)) == false # Washington’s Birthday - Monday
@test isbday(hc_usgovbond, Dates.Date(2015, 02, 17)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 05, 24)) == false
@test isbday(hc_usgovbond, Dates.Date(2015, 05, 25)) == false # Memorial Day - Monday
@test isbday(hc_usgovbond, Dates.Date(2015, 05, 26)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 07, 02)) == true
@test isbday(hc_usgovbond, Dates.Date(2015, 07, 03)) == false # Independence Day - Friday
@test isbday(hc_usgovbond, Dates.Date(2015, 07, 04)) == false

@test isbday(hc_usgovbond, Dates.Date(2015, 09, 06)) == false
@test isbday(hc_usgovbond, Dates.Date(2015, 09, 07)) == false # Labor Day - Monday
@test isbday(hc_usgovbond, Dates.Date(2015, 09, 08)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 10, 11)) == false
@test isbday(hc_usgovbond, Dates.Date(2015, 10, 12)) == false # Columbus Day - Monday
@test isbday(hc_usgovbond, Dates.Date(2015, 10, 13)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 11, 10)) == true
@test isbday(hc_usgovbond, Dates.Date(2015, 11, 11)) == false # Veterans Day - Wednesday
@test isbday(hc_usgovbond, Dates.Date(2015, 11, 12)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 11, 25)) == true
@test isbday(hc_usgovbond, Dates.Date(2015, 11, 26)) == false # Thanksgiving Day - Thursday
@test isbday(hc_usgovbond, Dates.Date(2015, 11, 27)) == true

@test isbday(hc_usgovbond, Dates.Date(2015, 12, 24)) == true
@test isbday(hc_usgovbond, Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday(hc_usgovbond, Dates.Date(2015, 12, 26)) == false

@test isbday(hc_usgovbond, Dates.Date(2010, 12, 31)) == true # Friday before new years
@test isbday(hc_usgovbond, Dates.Date(2004, 12, 31)) == true # Friday before new years

@test isbday(hc_usgovbond, Dates.Date(2013, 03, 28)) == true # thursday
@test isbday(hc_usgovbond, Dates.Date(2013, 03, 29)) == false # good friday
@test isbday(hc_usgovbond, Dates.Date(2013, 03, 30)) == false # saturday

# Symbol
@test isbday(:USGovernmentBond, Dates.Date(2015, 12, 24)) == true
@test isbday(:USGovernmentBond, Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday(:USGovernmentBond, Dates.Date(2015, 12, 26)) == false

# String
@test isbday("USGovernmentBond", Dates.Date(2015, 12, 24)) == true
@test isbday("USGovernmentBond", Dates.Date(2015, 12, 25)) == false # Christmas - Friday
@test isbday("USGovernmentBond", Dates.Date(2015, 12, 26)) == false

# TARGET HolidayCalendar tests
@test isbday(targethc, Dates.Date(2017, 12, 24)) == false # Sunday
@test isbday(targethc, Dates.Date(2017, 12, 25)) == false # Christmas - Monday
@test isbday(targethc, Dates.Date(2017, 12, 26)) == false # Day of Goodwill - Tuesday
@test isbday(targethc, Dates.Date(2017, 12, 27)) == true  # Wednesday

@test isbday(targethc, Dates.Date(2017, 04, 16)) == false # Easter Sunday
@test isbday(targethc, Dates.Date(2017, 04, 17)) == false # Easter Monday
@test isbday(targethc, Dates.Date(2017, 04, 18)) == true # Tuesday

@test isbday(targethc, Dates.Date(2001, 12, 31)) == false # End of year
@test isbday(targethc, Dates.Date(2002, 12, 31)) == true # End of year

@test isbday(targethc, Dates.Date(2016, 1, 1)) == false # New Year's Day
@test isbday(targethc, Dates.Date(2017, 5, 1)) == false # Labour Day
@test isbday(targethc, Dates.Date(1998, 5, 1)) == true # Labour Day before 2000

# Symbol
@test isbday(:TARGET, Dates.Date(2017, 04, 16)) == false # Easter Sunday
@test isbday(:TARGET, Dates.Date(2017, 04, 17)) == false # Easter Monday
@test isbday(:TARGET, Dates.Date(2017, 04, 18)) == true # Tuesday

# String
@test isbday("TARGET", Dates.Date(2017, 04, 16)) == false # Easter Sunday
@test isbday("TARGET", Dates.Date(2017, 04, 17)) == false # Easter Monday
@test isbday("TARGET", Dates.Date(2017, 04, 18)) == true # Tuesday

# TARGET synonyms
@test isbday("TARGET2", Dates.Date(2017, 04, 18)) == isbday("TARGET", Dates.Date(2017, 04, 18))
@test isbday("EuroZone", Dates.Date(2017, 04, 18)) == isbday("TARGET", Dates.Date(2017, 04, 18))

## UKSettlement HolidayCalendar tests
@test isbday(hc_uk, Dates.Date(2014, 12, 31)) == true
@test isbday(hc_uk, Dates.Date(2015, 01, 01)) == false # New Year's Day Thursday
@test isbday(hc_uk, Dates.Date(2015, 01, 02)) == true

@test isbday(hc_uk, Dates.Date(2015, 08, 30)) == false
@test isbday(hc_uk, Dates.Date(2015, 08, 31)) == false # Monday   Summer bank holiday
@test isbday(hc_uk, Dates.Date(2015, 09, 01)) == true

@test isbday(hc_uk, Dates.Date(2015, 12, 24)) == true
@test isbday(hc_uk, Dates.Date(2015, 12, 25)) == false # 25 December  Friday  Christmas Day
@test isbday(hc_uk, Dates.Date(2015, 12, 26)) == false
@test isbday(hc_uk, Dates.Date(2015, 12, 27)) == false
@test isbday(hc_uk, Dates.Date(2015, 12, 28)) == false # Monday   Boxing Day (substitute day)
@test isbday(hc_uk, Dates.Date(2015, 12, 29)) == true

@test isbday(hc_uk, Dates.Date(2016, 03, 24)) == true
@test isbday(hc_uk, Dates.Date(2016, 03, 25)) == false # 25 March Friday  Good Friday
@test isbday(hc_uk, Dates.Date(2016, 03, 26)) == false
@test isbday(hc_uk, Dates.Date(2016, 03, 27)) == false
@test isbday(hc_uk, Dates.Date(2016, 03, 28)) == false # 28 March Monday  Easter Monday
@test isbday(hc_uk, Dates.Date(2016, 03, 29)) == true

@test isbday(hc_uk, Dates.Date(2016, 05, 01)) == false
@test isbday(hc_uk, Dates.Date(2016, 05, 02)) == false # 2 May    Monday  Early May bank holiday
@test isbday(hc_uk, Dates.Date(2016, 05, 03)) == true

@test isbday(hc_uk, Dates.Date(2016, 05, 29)) == false
@test isbday(hc_uk, Dates.Date(2016, 05, 30)) == false # 30 May   Monday  Spring bank holiday
@test isbday(hc_uk, Dates.Date(2016, 05, 31)) == true

@test isbday(hc_uk, Dates.Date(2016, 08, 28)) == false
@test isbday(hc_uk, Dates.Date(2016, 08, 29)) == false # 29 August    Monday  Summer bank holiday
@test isbday(hc_uk, Dates.Date(2016, 08, 30)) == true

@test isbday(hc_uk, Dates.Date(2016, 12, 23)) == true
@test isbday(hc_uk, Dates.Date(2016, 12, 24)) == false
@test isbday(hc_uk, Dates.Date(2016, 12, 25)) == false
@test isbday(hc_uk, Dates.Date(2016, 12, 26)) == false # 26 December  Monday  Boxing Day
@test isbday(hc_uk, Dates.Date(2016, 12, 27)) == false # 27 December  Tuesday Christmas Day (substitute day)
@test isbday(hc_uk, Dates.Date(2016, 12, 28)) == true

# 2012 UK Holidays
@test isbday(hc_uk, Dates.Date(2011, 12, 30)) == true
@test isbday(hc_uk, Dates.Date(2011, 12, 31)) == false
@test isbday(hc_uk, Dates.Date(2012, 01, 01)) == false
@test isbday(hc_uk, Dates.Date(2012, 01, 02)) == false # 2 January    Monday  New Year’s Day (substitute day)
@test isbday(hc_uk, Dates.Date(2012, 01, 03)) == true

@test isbday(hc_uk, Dates.Date(2012, 04, 05)) == true
@test isbday(hc_uk, Dates.Date(2012, 04, 06)) == false # 6 April  Friday  Good Friday
@test isbday(hc_uk, Dates.Date(2012, 04, 07)) == false
@test isbday(hc_uk, Dates.Date(2012, 04, 08)) == false
@test isbday(hc_uk, Dates.Date(2012, 04, 09)) == false # 9 April  Monday  Easter Monday
@test isbday(hc_uk, Dates.Date(2012, 04, 10)) == true

@test isbday(hc_uk, Dates.Date(2012, 05, 06)) == false
@test isbday(hc_uk, Dates.Date(2012, 05, 07)) == false # 7 May    Monday  Early May bank holiday
@test isbday(hc_uk, Dates.Date(2012, 05, 08)) == true

@test isbday(hc_uk, Dates.Date(2012, 06, 01)) == true
@test isbday(hc_uk, Dates.Date(2012, 06, 02)) == false
@test isbday(hc_uk, Dates.Date(2012, 06, 03)) == false
@test isbday(hc_uk, Dates.Date(2012, 06, 04)) == false # 4 June   Monday  Spring bank holiday (substitute day)
@test isbday(hc_uk, Dates.Date(2012, 06, 05)) == false # 5 June   Tuesday Queen’s Diamond Jubilee (extra bank holiday)
@test isbday(hc_uk, Dates.Date(2012, 06, 06)) == true

@test isbday(hc_uk, Dates.Date(2011, 04, 29)) == false # wedding

@test isbday(hc_uk, Dates.Date(2012, 08, 26)) == false
@test isbday(hc_uk, Dates.Date(2012, 08, 27)) == false # 27 August    Monday  Summer bank holiday
@test isbday(hc_uk, Dates.Date(2012, 08, 28)) == true

@test isbday(hc_uk, Dates.Date(2012, 12, 24)) == true
@test isbday(hc_uk, Dates.Date(2012, 12, 25)) == false # 25 December  Tuesday Christmas Day
@test isbday(hc_uk, Dates.Date(2012, 12, 26)) == false # 26 December  Wednesday   Boxing Day
@test isbday(hc_uk, Dates.Date(2012, 12, 27)) == true

# 1999 UK holidays
@test isbday(hc_uk, Dates.Date(1999, 12, 26)) == false # Sunday
@test isbday(hc_uk, Dates.Date(1999, 12, 27)) == false # Christmas observed
@test isbday(hc_uk, Dates.Date(1999, 12, 28)) == false # Boxing observed
@test isbday(hc_uk, Dates.Date(1999, 12, 29)) == true
@test isbday(hc_uk, Dates.Date(1999, 12, 30)) == true
@test isbday(hc_uk, Dates.Date(1999, 12, 31)) == false

@test tobday(hc_brazil, Dates.Date(2013, 02, 08)) == Dates.Date(2013, 02, 08) # regular friday
@test tobday(hc_brazil, Dates.Date(2013, 02, 09)) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday(hc_brazil, Dates.Date(2013, 02, 09); forward = true) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday(hc_brazil, Dates.Date(2013, 02, 13); forward = false) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday(hc_brazil, Dates.Date(2013, 02, 12); forward = false) == Dates.Date(2013, 02, 08) # before carnaval

@test tobday(:Brazil, Dates.Date(2013, 02, 08)) == Dates.Date(2013, 02, 08) # regular friday
@test tobday(:Brazil, Dates.Date(2013, 02, 09)) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday(:Brazil, Dates.Date(2013, 02, 09); forward = true) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday(:Brazil, Dates.Date(2013, 02, 13); forward = false) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday(:Brazil, Dates.Date(2013, 02, 12); forward = false) == Dates.Date(2013, 02, 08) # before carnaval

@test tobday("Brazil", Dates.Date(2013, 02, 08)) == Dates.Date(2013, 02, 08) # regular friday
@test tobday("Brazil", Dates.Date(2013, 02, 09)) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday("Brazil", Dates.Date(2013, 02, 09); forward = true) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday("Brazil", Dates.Date(2013, 02, 13); forward = false) == Dates.Date(2013, 02, 13) # after carnaval
@test tobday("Brazil", Dates.Date(2013, 02, 12); forward = false) == Dates.Date(2013, 02, 08) # before carnaval

@test advancebdays(hc_brazil, Dates.Date(2013, 02, 06), 0) == Dates.Date(2013, 02, 06) # regular wednesday
@test advancebdays(hc_brazil, Dates.Date(2013, 02, 06), 1) == Dates.Date(2013, 02, 07) # regular thursday
@test advancebdays(hc_brazil, Dates.Date(2013, 02, 07), -1) == Dates.Date(2013, 02, 06) # regular thursday
@test advancebdays(hc_brazil, Dates.Date(2013, 02, 06), 2) == Dates.Date(2013, 02, 08) # regular friday
@test advancebdays(hc_brazil, Dates.Date(2013, 02, 06), 3) == Dates.Date(2013, 02, 13) # after carnaval wednesday
@test advancebdays(hc_brazil, Dates.Date(2013, 02, 06), 4) == Dates.Date(2013, 02, 14) # after carnaval thursday
@test advancebdays(hc_brazil, Dates.Date(2013, 02, 14), -4) == Dates.Date(2013, 02, 06) # after carnaval thursday

@test advancebdays(:Brazil, Dates.Date(2013, 02, 06), 0) == Dates.Date(2013, 02, 06) # regular wednesday
@test advancebdays(:Brazil, Dates.Date(2013, 02, 06), 1) == Dates.Date(2013, 02, 07) # regular thursday
@test advancebdays(:Brazil, Dates.Date(2013, 02, 06), 2) == Dates.Date(2013, 02, 08) # regular friday
@test advancebdays(:Brazil, Dates.Date(2013, 02, 06), 3) == Dates.Date(2013, 02, 13) # after carnaval wednesday
@test advancebdays(:Brazil, Dates.Date(2013, 02, 06), 4) == Dates.Date(2013, 02, 14) # after carnaval thursday

@test advancebdays("Brazil", Dates.Date(2013, 02, 06), 0) == Dates.Date(2013, 02, 06) # regular wednesday
@test advancebdays("Brazil", Dates.Date(2013, 02, 06), 1) == Dates.Date(2013, 02, 07) # regular thursday
@test advancebdays("Brazil", Dates.Date(2013, 02, 06), 2) == Dates.Date(2013, 02, 08) # regular friday
@test advancebdays("Brazil", Dates.Date(2013, 02, 06), 3) == Dates.Date(2013, 02, 13) # after carnaval wednesday
@test advancebdays("Brazil", Dates.Date(2013, 02, 06), 4) == Dates.Date(2013, 02, 14) # after carnaval thursday

@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 06)) == Dates.Day(0)
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 07)) == Dates.Day(1)
@test bdays(hc_brazil, Dates.Date(2013, 02, 07), Dates.Date(2013, 02, 06)).value == -1
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 08)).value == 2
@test bdays(hc_brazil, Dates.Date(2013, 02, 08), Dates.Date(2013, 02, 06)).value == -2
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 09)).value == 3
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 10)).value == 3
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 11)).value == 3
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 12)).value == 3
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 13)).value == 3
@test bdays(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 14)).value == 4
@test bdays(hc_brazil, Dates.Date(2013, 02, 14), Dates.Date(2013, 02, 06)).value == -4

@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 06)) == 0
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 07)) == 1
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 07), Dates.Date(2013, 02, 06)) == -1
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 08)) == 2
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 08), Dates.Date(2013, 02, 06)) == -2
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 09)) == 3
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 10)) == 3
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 11)) == 3
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 12)) == 3
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 13)) == 3
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 06), Dates.Date(2013, 02, 14)) == 4
@test bdayscount(hc_brazil, Dates.Date(2013, 02, 14), Dates.Date(2013, 02, 06)) == -4

# Canada

tsxdates16 = [
    Dates.Date(2016, 1, 1),
    Dates.Date(2016, 2, 15),
    Dates.Date(2016, 3, 25),
    Dates.Date(2016, 5, 23),
    Dates.Date(2016, 7, 1),
    Dates.Date(2016, 8, 1),
    Dates.Date(2016, 9, 5),
    Dates.Date(2016, 10, 10),
    Dates.Date(2016, 12, 26),
    Dates.Date(2016, 12, 27)
]

alldates16itr = Dates.Date(2016,1,1):Dates.Day(1):Dates.Date(2016, 12,31)
for i in alldates16itr
    if i ∈ tsxdates16
        @test isholiday(hc_canadatsx, i) == true
    else
        @test isholiday(hc_canadatsx, i) == false
    end
end

tsxdates17 = [
    Dates.Date(2017, 1, 2),
    Dates.Date(2017, 2, 20),
    Dates.Date(2017, 4, 14),
    Dates.Date(2017, 5, 22),
    Dates.Date(2017, 7, 3),
    Dates.Date(2017, 8, 7),
    Dates.Date(2017, 9, 4),
    Dates.Date(2017, 10, 9),
    Dates.Date(2017, 12, 25),
    Dates.Date(2017, 12, 26)
]

alldates17itr = Dates.Date(2017,1,1):Dates.Day(1):Dates.Date(2017, 12,31)
for i in alldates17itr
    if i ∈ tsxdates17
        @test isholiday(hc_canadatsx, i) == true
    else
        @test isholiday(hc_canadatsx, i) == false
    end
end

canadaDates16 = [
    Dates.Date(2016, 1, 1),
    Dates.Date(2016, 2, 15),
    Dates.Date(2016, 3, 25),
    Dates.Date(2016, 5, 23),
    Dates.Date(2016, 7, 1),
    Dates.Date(2016, 8, 1),
    Dates.Date(2016, 9, 5),
    Dates.Date(2016, 10, 10),
    Dates.Date(2016, 11, 11),
    Dates.Date(2016, 12, 26),
    Dates.Date(2016, 12, 27)
]

for i in alldates16itr
    if i ∈ canadaDates16
        @test isholiday(hc_canada, i) == true
    else
        @test isholiday(hc_canada, i) == false
    end
end

# Issue #8
@test isbday(hc_canada, Dates.Date(2011,1,3)) == true
@test isbday(hc_canadatsx, Dates.Date(2008, 2, 18)) == false

# Australian Stock Exchange (ASX)
christmasday = Dates.Date(2018,12, 25)
boxingday    = Dates.Date(2018,12, 26)
asxdates18 = Set([
    Dates.Date(2018, 1,  1),  # New year's day
    Dates.Date(2018, 1, 26),  # Australia Day
    Dates.Date(2018, 3, 30),  # Good Friday
    Dates.Date(2018, 4,  2),  # Easter Monday
    Dates.Date(2018, 4, 25),  # ANZAC Day
    Dates.Date(2018, 6, 11),  # Queen's Birthday holiday
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, asxdates18)
        dt != boxingday && @test isholiday(hc_australiaasx, dt-Dates.Day(1)) == false
        @test isholiday(hc_australiaasx, dt) == true
        dt != christmasday && @test isholiday(hc_australiaasx, dt+Dates.Day(1)) == false
    else
        @test isholiday(hc_australiaasx, dt) == false
    end
end

# Australian states and territories
@test_throws MethodError BusinessDays.Australia()         # State/territory not specified
@test_throws AssertionError BusinessDays.Australia(:XXX)  # Invalid state/territory

# The Australian Capital Territory (ACT)
actdates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3, 12),  # Canberra Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  3, 31),  # Easter Saturday
    Dates.Date(2018,  4,  1),  # Easter Sunday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  5, 28),  # Reconciliation Day
    Dates.Date(2018,  6, 11),  # Queen's Birthday holiday
    Dates.Date(2018, 10,  1),  # Labour Day
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, actdates18)
        @test isholiday(hc_australiaact, dt) == true
    else
        @test isholiday(hc_australiaact, dt) == false
    end
end

# The state of New South Wales (NSW), Australia
nswdates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  3, 31),  # Easter Saturday
    Dates.Date(2018,  4,  1),  # Easter Sunday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  6, 11),  # Queen's Birthday holiday
    Dates.Date(2018,  8,  6),  # Bank Holiday
    Dates.Date(2018, 10,  1),  # Labour Day
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, nswdates18)
        @test isholiday(hc_australiansw, dt) == true
    else
        @test isholiday(hc_australiansw, dt) == false
    end
end

# The Northern Territory (NT), Australia
ntdates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  3, 31),  # Easter Saturday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  5,  7),  # May Day
    Dates.Date(2018,  6, 11),  # Queen's Birthday holiday
    Dates.Date(2018,  8,  6),  # Picnic Day
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, ntdates18)
        @test isholiday(hc_australiant, dt) == true
    else
        @test isholiday(hc_australiant, dt) == false
    end
end

# The state of Queensland (QLD), Australia
qlddates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  3, 31),  # Easter Saturday
    Dates.Date(2018,  4,  1),  # Easter Sunday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  5,  7),  # Labour Day
    Dates.Date(2018,  8, 15),  # Royal Brisbane Show (brisbane area only)
    Dates.Date(2018, 10,  1),  # Queen's Birthday holiday
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, qlddates18)
        @test isholiday(hc_australiaqld, dt) == true
    else
        @test isholiday(hc_australiaqld, dt) == false
    end
end
@test isholiday(hc_australiaqld, Dates.Date(2013, 6, 10)) == true

# The state of South Australia (SA)
sadates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3, 12),  # March public Holiday
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  3, 31),  # Easter Saturday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  6, 11),  # Queen's Birthday holiday
    Dates.Date(2018, 10,  1),  # Labour Day
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, sadates18)
        @test isholiday(hc_australiasa, dt) == true
    else
        @test isholiday(hc_australiasa, dt) == false
    end
end

# The state of Tasmania (TAS), Australia
tasdates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  2, 12),  # Royal Hobart Regatta
    Dates.Date(2018,  3, 12),  # Labour Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  6, 11),  # Queen's Birthday holiday
    Dates.Date(2018, 11,  5),  # Recreation Day
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, tasdates18)
        @test isholiday(hc_australiatas, dt) == true
    else
        @test isholiday(hc_australiatas, dt) == false
    end
end

# The state of Western Australia (WA)
wadates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3,  5),  # Labour Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  6,  4),  # Western Australia Day
    Dates.Date(2018,  9, 24),  # Queen's Birthday holiday
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, wadates18)
        @test isholiday(hc_australiawa, dt) == true
    else
        @test isholiday(hc_australiawa, dt) == false
    end
end
@test isholiday(hc_australiawa, Dates.Date(2011, 10, 28)) == true
@test isholiday(hc_australiawa, Dates.Date(2012, 10,  1)) == true

# The state of Victoria (VIC), Australia
vicdates18 = Set([
    Dates.Date(2018,  1,  1),  # New year's day
    Dates.Date(2018,  1, 26),  # Australia Day
    Dates.Date(2018,  3, 12),  # Labour Day
    Dates.Date(2018,  3, 30),  # Good Friday
    Dates.Date(2018,  3, 31),  # Easter Saturday
    Dates.Date(2018,  4,  1),  # Easter Sunday
    Dates.Date(2018,  4,  2),  # Easter Monday
    Dates.Date(2018,  4, 25),  # ANZAC Day
    Dates.Date(2018,  6, 11),  # Queen's Birthday holiday
    Dates.Date(2018,  9, 28),  # AFL Grand Final Eve holiday
    Dates.Date(2018, 11,  6),  # Melbourne Cup holiday
    christmasday,
    boxingday
])
for dt in Dates.Date(2018,1,1):Dates.Day(1):Dates.Date(2018,12,31)
    if in(dt, vicdates18)
        @test isholiday(hc_australiavic, dt) == true
    else
        @test isholiday(hc_australiavic, dt) == false
    end
end

# dates are treated per value
d0 = Dates.Date(2013, 02, 06)
d1 = Dates.Date(2013, 02, 14)
@test bdays(hc_brazil, d0, d1).value == 4
@test bdayscount(hc_brazil, d0, d1) == 4
@test d0 == Dates.Date(2013, 02, 06) # d0 is changed inside bdays function, but outer-scope value remains the same
@test d1 == Dates.Date(2013, 02, 14)

d0 = Dates.Date(2015, 06, 29) ; d2 = Dates.Date(2100, 12, 20)
@test bdays(hc_brazil, d0, d2).value == 21471
@test bdayscount(hc_brazil, d0, d2) == 21471

# Tests for Composite Calendar
@test isholiday(hc_composite_BR_USA, Dates.Date(2012,9,3)) # US Labor Day
@test isholiday(hc_composite_BR_USA, Dates.Date(2012,9,7)) # BR Independence Day
@test bdayscount(hc_composite_BR_USA, Dates.Date(2012,8,31), Dates.Date(2012,9,10)) == 4 # 3/sep labor day US, 7/sep Indep day BR
@test bdays(hc_composite_BR_USA, Dates.Date(2012,8,31), Dates.Date(2012,9,10)) == Dates.Day(4) # 3/sep labor day US, 7/sep Indep day BR

println("Timing composite calendar bdays calculation")
@time bdays(hc_composite_BR_USA, Dates.Date(2012,8,31), Dates.Date(2012,9,10))

println("Timing single bdays calculation")
@time bdays(hc_brazil, d0, d2)

println("Timing 100 bdays calculations")
@time for i in 1:100 bdays(hc_brazil, d0, d2) end

dInicio = Dates.Date(1950, 01, 01) ; dFim = Dates.Date(2100, 12, 20)

if !usecache
    println("Timing cache creation")
    @time x = BusinessDays._create_bdays_cache_arrays(hc_brazil, dInicio, dFim)
end

if usecache
    println("a million...")
    @time for i in 1:1000000 bdays(hc_brazil, d0, d2) end
end

# Vector functions
d0 = Dates.Date(2000,01,04)
d1 = Dates.Date(2020,01,04)

d1vec = collect(d0:Dates.Day(1):d1)
d0vec = fill(d0, length(d1vec))

r = bdays(hc_brazil, d0vec, d1vec)
b = isbday(hc_brazil, d0vec)
b2 = isbday(:Brazil, d0vec)
b3 = isbday("Brazil", d0vec)
@test tobday([hc_brazil, hc_usa], [Dates.Date(2015,11,11), Dates.Date(2015,11,11)]) == [Dates.Date(2015,11,11), Dates.Date(2015,11,12)]
@test tobday([:Brazil, :USSettlement], [Dates.Date(2015,11,11), Dates.Date(2015,11,11)]) == [Dates.Date(2015,11,11), Dates.Date(2015,11,12)]
@test tobday(["Brazil", "USSettlement"], [Dates.Date(2015,11,11), Dates.Date(2015,11,11)]) == [Dates.Date(2015,11,11), Dates.Date(2015,11,12)]

# Vector with different sizes
@test_throws AssertionError bdays(hc_brazil, fill(d0, length(d1vec)+1), d1vec)
@test_throws AssertionError bdays([hc_brazil, hc_usa], [Dates.Date(2015,11,11)], [Dates.Date(2015,11,11),Dates.Date(2015,11,11)])
@test_throws AssertionError tobday([hc_brazil, hc_usa], fill(d0, 3))
@test_throws AssertionError isbday( [hc_brazil, hc_usa, hc_uk], [Dates.Date(2015,01,01), Dates.Date(2015,01,01)])

println("Timing vectorized functions (vector length $(length(d0vec)))")
@time bdays(hc_brazil, d0vec, d1vec)
@time bdays(:Brazil, d0vec, d1vec)
@time bdays("Brazil", d0vec, d1vec)
@time isbday(hc_brazil, d0vec)
@time isbday(:Brazil, d0vec)
@time isbday("Brazil", d0vec)

d2001 = collect(Dates.Date(2001,01,01):Dates.Day(1):Dates.Date(2001,01,15))

@test isweekend(d2001) == [ false, false, false, false, false, true, true, false, false, false, false, false, true, true, false]
@test tobday(hc_brazil, d2001; forward=true) == [ Dates.Date(2001,01,02), Dates.Date(2001,01,02), Dates.Date(2001,01,03), Dates.Date(2001,01,04), Dates.Date(2001,01,05), Dates.Date(2001,01,08), Dates.Date(2001,01,08), Dates.Date(2001,01,08), Dates.Date(2001,01,09), Dates.Date(2001,01,10), Dates.Date(2001,01,11), Dates.Date(2001,01,12), Dates.Date(2001,01,15), Dates.Date(2001,01,15), Dates.Date(2001,01,15)]
@test tobday(hc_brazil, d2001; forward=false) == [ Dates.Date(2000,12,29), Dates.Date(2001,01,02), Dates.Date(2001,01,03), Dates.Date(2001,01,04), Dates.Date(2001,01,05), Dates.Date(2001,01,05), Dates.Date(2001,01,05), Dates.Date(2001,01,08), Dates.Date(2001,01,09), Dates.Date(2001,01,10), Dates.Date(2001,01,11), Dates.Date(2001,01,12), Dates.Date(2001,01,12), Dates.Date(2001,01,12), Dates.Date(2001,01,15)]

@test tobday(:Brazil, d2001; forward=true) == [ Dates.Date(2001,01,02), Dates.Date(2001,01,02), Dates.Date(2001,01,03), Dates.Date(2001,01,04), Dates.Date(2001,01,05), Dates.Date(2001,01,08), Dates.Date(2001,01,08), Dates.Date(2001,01,08), Dates.Date(2001,01,09), Dates.Date(2001,01,10), Dates.Date(2001,01,11), Dates.Date(2001,01,12), Dates.Date(2001,01,15), Dates.Date(2001,01,15), Dates.Date(2001,01,15)]
@test tobday("Brazil", d2001; forward=false) == [ Dates.Date(2000,12,29), Dates.Date(2001,01,02), Dates.Date(2001,01,03), Dates.Date(2001,01,04), Dates.Date(2001,01,05), Dates.Date(2001,01,05), Dates.Date(2001,01,05), Dates.Date(2001,01,08), Dates.Date(2001,01,09), Dates.Date(2001,01,10), Dates.Date(2001,01,11), Dates.Date(2001,01,12), Dates.Date(2001,01,12), Dates.Date(2001,01,12), Dates.Date(2001,01,15)]

@test bdays([hc_brazil, hc_usa], [Dates.Date(2012,8,31), Dates.Date(2012,8,31)], [Dates.Date(2012,9,10), Dates.Date(2012,9,10)]) == [Dates.Day(5), Dates.Day(5)] # 1/sep labor day US, 7/sep Indep day BR
@test bdayscount([hc_brazil, hc_usa], [Dates.Date(2012,8,31), Dates.Date(2012,8,31)], [Dates.Date(2012,9,10), Dates.Date(2012,9,10)]) == [5, 5] # 1/sep labor day US, 7/sep Indep day BR
@test isbday([hc_brazil, hc_usa], [Dates.Date(2012, 09, 07), Dates.Date(2012, 09, 03)]) == [false, false] # 1/sep labor day US, 7/sep Indep day BR
@test advancebdays(hc_brazil, Dates.Date(2015,9,1), [0, 1, 3, 4, 5]) == [Dates.Date(2015,9,1),Dates.Date(2015,9,2),Dates.Date(2015,9,4),Dates.Date(2015,9,8),Dates.Date(2015,9,9)]
@test advancebdays(hc_brazil, Dates.Date(2015,9,1), 0:1:5) == [Dates.Date(2015,9,1),Dates.Date(2015,9,2),Dates.Date(2015,9,3),Dates.Date(2015,9,4),Dates.Date(2015,9,8),Dates.Date(2015,9,9)]
@test listholidays(hc_brazil, Dates.Date(2016,1,1), Dates.Date(2016,5,30)) == [Dates.Date(2016,1,1),Dates.Date(2016,2,8),Dates.Date(2016,2,9),Dates.Date(2016,3,25),Dates.Date(2016,4,21),Dates.Date(2016,5,1),Dates.Date(2016,5,26)]

@test bdays([:Brazil, :USSettlement], [Dates.Date(2012,8,31), Dates.Date(2012,8,31)], [Dates.Date(2012,9,10), Dates.Date(2012,9,10)]) == [Dates.Day(5), Dates.Day(5)] # 1/sep labor day US, 7/sep Indep day BR
@test bdayscount([:Brazil, :USSettlement], [Dates.Date(2012,8,31), Dates.Date(2012,8,31)], [Dates.Date(2012,9,10), Dates.Date(2012,9,10)]) == [5, 5] # 1/sep labor day US, 7/sep Indep day BR
@test isbday([:Brazil, :USSettlement], [Dates.Date(2012, 09, 07), Dates.Date(2012, 09, 03)]) == [false, false] # 1/sep labor day US, 7/sep Indep day BR
@test advancebdays(:Brazil, Dates.Date(2015,9,1), [0, 1, 3, 4, 5]) == [Dates.Date(2015,9,1),Dates.Date(2015,9,2),Dates.Date(2015,9,4),Dates.Date(2015,9,8),Dates.Date(2015,9,9)]
@test advancebdays(:Brazil, Dates.Date(2015,9,1), 0:5) == [Dates.Date(2015,9,1),Dates.Date(2015,9,2),Dates.Date(2015,9,3),Dates.Date(2015,9,4),Dates.Date(2015,9,8),Dates.Date(2015,9,9)]
@test listholidays(:Brazil, Dates.Date(2016,1,1), Dates.Date(2016,5,30)) == [Dates.Date(2016,1,1),Dates.Date(2016,2,8),Dates.Date(2016,2,9),Dates.Date(2016,3,25),Dates.Date(2016,4,21),Dates.Date(2016,5,1),Dates.Date(2016,5,26)]

@test bdays(["Brazil", "USSettlement"], [Dates.Date(2012,8,31), Dates.Date(2012,8,31)], [Dates.Date(2012,9,10), Dates.Date(2012,9,10)]) == [Dates.Day(5), Dates.Day(5)] # 1/sep labor day US, 7/sep Indep day BR
@test bdayscount(["Brazil", "USSettlement"], [Dates.Date(2012,8,31), Dates.Date(2012,8,31)], [Dates.Date(2012,9,10), Dates.Date(2012,9,10)]) == [5, 5] # 1/sep labor day US, 7/sep Indep day BR
@test isbday(["Brazil", "USSettlement"], [Dates.Date(2012, 09, 07), Dates.Date(2012, 09, 03)]) == [false, false] # 1/sep labor day US, 7/sep Indep day BR
@test advancebdays("Brazil", Dates.Date(2015,9,1), [0, 1, 3, 4, 5]) == [Dates.Date(2015,9,1),Dates.Date(2015,9,2),Dates.Date(2015,9,4),Dates.Date(2015,9,8),Dates.Date(2015,9,9)]
@test advancebdays("Brazil", Dates.Date(2015,9,1), 0:5) == [Dates.Date(2015,9,1),Dates.Date(2015,9,2),Dates.Date(2015,9,3),Dates.Date(2015,9,4),Dates.Date(2015,9,8),Dates.Date(2015,9,9)]
@test listholidays("Brazil", Dates.Date(2016,1,1), Dates.Date(2016,5,30)) == [Dates.Date(2016,1,1),Dates.Date(2016,2,8),Dates.Date(2016,2,9),Dates.Date(2016,3,25),Dates.Date(2016,4,21),Dates.Date(2016,5,1),Dates.Date(2016,5,26)]

@test listbdays("Brazil", Dates.Date(2016,5,18), Dates.Date(2016,5,23)) == [Dates.Date(2016,5,18),Dates.Date(2016,5,19),Dates.Date(2016,5,20),Dates.Date(2016,5,23)]
@test listbdays("Brazil", Dates.Date(2016,5,18), Dates.Date(2016,5,18)) == [Dates.Date(2016,5,18)]
@test isempty(listbdays("Brazil", Dates.Date(2016,5,21), Dates.Date(2016,5,21)))
@test isempty(listbdays("Brazil", Dates.Date(2016,5,21), Dates.Date(2016,5,22)))
@test listbdays("Brazil", Dates.Date(2016,5,21), Dates.Date(2016,5,23)) == [Dates.Date(2016,5,23)]

@test bdays(:Brazil, Dates.Date(2016,11,1), [Dates.Date(2016,11,3), Dates.Date(2016,11,7), Dates.Date(2016,11,4)]) == [Dates.Day(1), Dates.Day(3), Dates.Day(2)]
@test bdayscount(:Brazil, Dates.Date(2016,11,1), [Dates.Date(2016,11,3), Dates.Date(2016,11,7), Dates.Date(2016,11,4)]) == [1, 3, 2]

@test bdays(:Brazil, [Dates.Date(2018,3,28), Dates.Date(2018,3,28), Dates.Date(2018,3,28), Dates.Date(2018,3,28)], [Dates.Date(2018,3,28), Dates.Date(2018,3,29), Dates.Date(2018,3,30), Dates.Date(2018,4,2)]) == [Dates.Day(0), Dates.Day(1), Dates.Day(2), Dates.Day(2)]
@test bdayscount(:Brazil, [Dates.Date(2018,3,28), Dates.Date(2018,3,28), Dates.Date(2018,3,28), Dates.Date(2018,3,28)], [Dates.Date(2018,3,28), Dates.Date(2018,3,29), Dates.Date(2018,3,30), Dates.Date(2018,4,2)]) == [0, 1, 2, 2]

# first/last businessdayofmonth
@test firstbdayofmonth(:Brazil, Dates.Date(2017,12,10)) == Dates.Date(2017,12,1)
@test firstbdayofmonth(:Brazil, Dates.Date(2018,1,10)) == Dates.Date(2018,1,2)
@test lastbdayofmonth(:Brazil, Dates.Date(2017,12,10)) == Dates.Date(2017,12,29)

@test firstbdayofmonth(:Brazil, 2017, 12) == Dates.Date(2017,12,1)
@test firstbdayofmonth(:Brazil, 2018, 1) == Dates.Date(2018,1,2)
@test lastbdayofmonth(:Brazil, 2017, 12) == Dates.Date(2017,12,29)

@test firstbdayofmonth(:Brazil, Dates.Year(2017), Dates.Month(12)) == Dates.Date(2017,12,1)
@test firstbdayofmonth(:Brazil, Dates.Year(2018), Dates.Month(1)) == Dates.Date(2018,1,2)
@test lastbdayofmonth(:Brazil, Dates.Year(2017), Dates.Month(12)) == Dates.Date(2017,12,29)

# list holidays for all available calendars
for c in [:BRSettlement, :BrazilExchange, :USNYSE, :USGovernmentBond, :USSettlement, :CanadaTSX, :CanadaSettlement, :EuroZone, :UKSettlement, :AustraliaASX]
    listholidays(c, Dates.Date(1990,1,1), Dates.Date(2100,1,1))
end


text:
"""
    cSIL.jl

This is a Julia port of a MATLAB implementation of batch and incremental
Centroid-based Silhouette (cSIL) Cluster Validity Index.

Authors:
MATLAB implementation: Leonardo Enzo Brito da Silva
Julia port: Sasha Petrenko <sap625@mst.edu>

REFERENCES
[1] L. E. Brito da Silva, N. M. Melton, and D. C. Wunsch II, "Incremental
Cluster Validity Indices for Hard Partitions: Extensions  and  Comparative
Study," ArXiv  e-prints, Feb 2019, arXiv:1902.06711v1 [cs.LG].
[2] P. J. Rousseeuw, "Silhouettes: A graphical aid to the interpretation and
validation of cluster analysis," Journal of Computational and Applied
Mathematics, vol. 20, pp. 53–65, 1987.
[3] M. Rawashdeh and A. Ralescu, "Center-wise intra-inter silhouettes," in
Scalable Uncertainty Management, E. Hüllermeier, S. Link, T. Fober et al.,
Eds. Berlin, Heidelberg: Springer, 2012, pp. 406–419.
"""

"""
    cSIL

The stateful information of the Centroid-based Silhouette (cSIL) Cluster Validity Index.

# References
1. L. E. Brito da Silva, N. M. Melton, and D. C. Wunsch II, "Incremental Cluster Validity Indices for Hard Partitions: Extensions  and  Comparative Study," ArXiv  e-prints, Feb 2019, arXiv:1902.06711v1 [cs.LG].
2. P. J. Rousseeuw, "Silhouettes: A graphical aid to the interpretation and validation of cluster analysis," Journal of Computational and Applied Mathematics, vol. 20, pp. 53–65, 1987.
3. M. Rawashdeh and A. Ralescu, "Center-wise intra-inter silhouettes," in Scalable Uncertainty Management, E. Hüllermeier, S. Link, T. Fober et al., Eds. Berlin, Heidelberg: Springer, 2012, pp. 406–419.
"""
mutable struct cSIL <: CVI
    label_map::LabelMap
    dim::Integer
    n_samples::Integer
    n::IntegerVector        # dim
    v::RealMatrix           # dim x n_clusters
    CP::RealVector          # dim
    G::RealMatrix           # dim x n_clusters
    S::RealMatrix           # n_clusters x n_clusters
    sil_coefs::RealVector   # dim
    n_clusters::Integer
    criterion_value::Float
end # cSIL <: CVI

"""
    cSIL()

Default constructor for the Centroid-based Silhouette (cSIL) Cluster Validity Index.
"""
function cSIL()
    cSIL(
        LabelMap(),                     # label_map
        0,                              # dim
        0,                              # n_samples
        Array{Integer, 1}(undef, 0),    # n
        Array{Float, 2}(undef, 0, 0),   # v
        Array{Float, 1}(undef, 0),      # CP
        Array{Float, 2}(undef, 0, 0),   # G
        Array{Float, 2}(undef, 0, 0),   # S
        Array{Float, 1}(undef, 0),      # sil_coefs
        0,                              # n_clusters
        0.0                             # criterion_value
    )
end # cSIL()

"""
    setup!(cvi::cSIL, sample::Vector{T}) where {T<:RealFP}
"""
function setup!(cvi::cSIL, sample::Vector{T}) where {T<:RealFP}
    # Get the feature dimension
    cvi.dim = length(sample)
    # Initialize the augmenting 2-D arrays with the correct feature dimension
    # NOTE: R is emptied and calculated in evaluate!, so it is not defined here
    cvi.v = Array{T, 2}(undef, cvi.dim, 0)
    cvi.G = Array{T, 2}(undef, cvi.dim, 0)
end # setup!(cvi::cSIL, sample::Vector{T}) where {T<:RealFP}

function param_inc!(cvi::cSIL, sample::RealVector, label::Integer)
    # Get the internal label
    i_label = get_internal_label!(cvi.label_map, label)

    n_samples_new = cvi.n_samples + 1
    if cvi.n_samples == 0
        setup!(cvi, sample)
    end

    if i_label > cvi.n_clusters
        n_new = 1
        v_new = sample
        CP_new = transpose(sample) * sample
        G_new = sample
        # Compute S_new
        if cvi.n_clusters == 0
            # S_new = 0.0
            S_new = zeros(1,1)
        else
            S_new = zeros(cvi.n_clusters + 1, cvi.n_clusters + 1)
            S_new[1:cvi.n_clusters, 1:cvi.n_clusters] = cvi.S
            S_row_new = zeros(cvi.n_clusters + 1)
            S_col_new = zeros(cvi.n_clusters + 1)
            for cl = 1:cvi.n_clusters
                # Column "bmu_temp" - D_new
                C = CP_new + (transpose(cvi.v[:, cl]) * cvi.v[:, cl]) - 2 * (transpose(G_new) * cvi.v[:, cl])
                S_col_new[cl] = C
                # Row "bmu_temp" - E
                C = cvi.CP[cl] + cvi.n[cl] * (transpose(v_new)*v_new) - 2*(transpose(cvi.G[:, cl]) * v_new)
                S_row_new[cl] = C / cvi.n[cl]
            end
            # Column "ind_minus" - F
            S_col_new[i_label] = 0
            S_row_new[i_label] = S_col_new[i_label]
            S_new[:, i_label] = S_col_new
            S_new[i_label, :] = S_row_new
        end
        # Update 1-D parameters with a push
        cvi.n_clusters += 1
        push!(cvi.CP, CP_new)
        push!(cvi.n, n_new)
        # Update 2-D parameters with appending and reassignment
        cvi.v = [cvi.v v_new]
        cvi.G = [cvi.G G_new]
        cvi.S = S_new
    else
        n_new = cvi.n[i_label] + 1
        v_new = (1 - 1/n_new) .* cvi.v[:, i_label] + (1/n_new) .* sample
        CP_new = cvi.CP[i_label] + (transpose(sample) * sample)
        G_new = cvi.G[:, i_label] + sample
        # Compute S_new
        S_row_new = zeros(cvi.n_clusters)
        S_col_new = zeros(cvi.n_clusters)
        for cl = 1:cvi.n_clusters
            # Skip the i_label iteration
            if cl == i_label
                continue
            end
            # Column "bmu_temp" - D_new
            diff_x_v = sample - cvi.v[:, cl]
            C = cvi.CP[i_label] + (transpose(diff_x_v)*diff_x_v) + cvi.n[i_label]*(transpose(cvi.v[:, cl]) * cvi.v[:, cl]) - 2 * (transpose(G_new) * cvi.v[:, cl])
            S_col_new[cl] = C / n_new
            # Row "bmu_temp" - E
            C = cvi.CP[cl] + cvi.n[cl] * (transpose(v_new)*v_new) - 2*(transpose(cvi.G[:, cl]) * v_new)
            S_row_new[cl] = C / cvi.n[cl]
        end
        # Column "ind_minus" - F
        diff_x_v = sample - v_new
        C = cvi.CP[i_label] + (transpose(diff_x_v) * diff_x_v) + cvi.n[i_label] * (transpose(v_new) * v_new) - 2*(transpose(cvi.G[:, i_label])*v_new)
        S_col_new[i_label] = C / n_new
        S_row_new[i_label] = S_col_new[i_label]
        # Update parameters
        cvi.n[i_label] = n_new
        cvi.v[:, i_label] = v_new
        cvi.CP[i_label] = CP_new
        cvi.G[:, i_label] = G_new
        cvi.S[:, i_label] = S_col_new
        cvi.S[i_label, :] = S_row_new
    end
    cvi.n_samples = n_samples_new
end # param_inc!(cvi::cSIL, sample::RealVector, label::Integer)

function param_batch!(cvi::cSIL, data::RealMatrix, labels::IntegerVector)
    cvi.dim, cvi.n_samples = size(data)
    # u = findfirst.(isequal.(unique(labels)), [labels])
    u = unique(labels)
    cvi.n_clusters = length(u)
    cvi.n = zeros(Integer, cvi.n_clusters)
    cvi.v = zeros(cvi.dim, cvi.n_clusters)
    cvi.CP = zeros(cvi.n_clusters)
    cvi.S = zeros(cvi.n_clusters, cvi.n_clusters)
    D = zeros(cvi.n_samples, cvi.n_clusters)
    for ix = 1:cvi.n_clusters
        subset = data[:, findall(x->x==u[ix], labels)]
        cvi.n[ix] = size(subset, 2)
        cvi.v[:, ix] = mean(subset, dims=2)
        # Compute CP in case of switching back to incremental mode
        d_temp = (data - cvi.v[:, ix]*ones(1, cvi.n_samples)).^2
        D[:, ix] = transpose(sum(d_temp, dims=1))
    end
    for ix = 1:cvi.n_clusters
        for jx = 1:cvi.n_clusters
            subset_ind = findall(x->x==u[jx], labels)
            cvi.S[ix, jx] = sum(D[subset_ind, ix]) / cvi.n[jx]
        end
    end
end # param_batch!(cvi::cSIL, data::RealMatrix, labels::IntegerVector)

function evaluate!(cvi::cSIL)
    cvi.sil_coefs = zeros(cvi.n_clusters)
    if !isempty(cvi.S) && cvi.n_clusters > 1
        for ix = 1:cvi.n_clusters
            # Same cluster
            a = cvi.S[ix, ix]
            # Other clusters
            b = minimum(cvi.S[ix, 1:end .!= ix])
            cvi.sil_coefs[ix] = (b-a)/max(a, b)
        end
        # cSIL index value
        cvi.criterion_value = sum(cvi.sil_coefs) / cvi.n_clusters
    else
        cvi.criterion_value = 0.0
    end
end # evaluate(cvi::cSIL)


text:
#download from remote site
import MatrixDepot: URL_REDIRECT, load, loadinfo, loadsvd

# test only for julia nightly
if length(VERSION.prerelease) == 0
    println("remote tests not executed")
else
    URL_REDIRECT[] = 0
    # sp
    pattern = "*/494_bus" # which has not been touched in other tests
    @test loadinfo(pattern) == 1 # load only header
    println("downloading svd for $pattern")
    @test loadsvd(pattern) == 1 # load svd extension data
    @test load(pattern) == 1 # loaded full data

    # Matrix Market
    pattern = "*/*/494_bus" # which has not been touched in other tests
    @test loadinfo(pattern) == 1 # load only header
    @test load(pattern) == 1 # loaded full data
end


text:
function evaluate!{F, LD}(output::AbstractArray{F}, mlp::MultilayerPerceptron{F, LD}, input::AbstractArray, layerstorage::Storage{MultilayerPerceptron{F, LD}})
  l = length(LD)
  #run a batch evaluate WITH using buffers for intermediate values.
  evaluate!(layer(layerstorage, Val{2}), mlp.layers[1], input)
  for idx = 2:(l - 2)
    evaluate!(layer(layerstorage, Val{idx + 1}), mlp.layers[idx], layer(layerstorage, Val{idx}))
  end
  evaluate!(output, mlp.layers[end], layer(layerstorage, Val{l - 1}))
end

max_stars_repo_name: interplanetary-robot/GenML

max_issues_repo_name: interplanetary-robot/GenML

max_forks_repo_name: interplanetary-robot/GenML


text:
# AUTO GENERATED FILE - DO NOT EDIT

export alert

"""
    alert(;kwargs...)
    alert(children::Any;kwargs...)
    alert(children_maker::Function;kwargs...)

An Alert component.
Attract user attention with important static message. For more information, see: https://mantine.dev/core/alert/
Keyword arguments:
- `children` (a list of or a singular dash component, string or number; optional): Alert message
- `id` (String; optional): The ID of this component, used to identify dash components in callbacks
- `className` (String; optional): Often used with CSS to style elements with common properties
- `color` (a value equal to: "dark", "gray", "red", "pink", "grape", "violet", "indigo", "blue", "cyan", "teal", "green", "lime", "yellow", "orange"; optional): Alert title and line colors from theme
- `duration` (Real; optional): Duration in milliseconds after which the Alert dismisses itself.
- `show` (Bool; optional): Whether to show the alert
- `style` (Dict; optional): Inline style override
- `title` (String; optional): Optional alert title
- `withCloseButton` (Bool; optional): Display close button
"""
function alert(; kwargs...)
        available_props = Symbol[:children, :id, :className, :color, :duration, :show, :style, :title, :withCloseButton]
        wild_props = Symbol[]
        return Component("alert", "Alert", "dash_mantine_components", available_props, wild_props; kwargs...)
end

alert(children::Any; kwargs...) = alert(;kwargs..., children = children)
alert(children_maker::Function; kwargs...) = alert(children_maker(); kwargs...)