text:
# See default_template.jl.
using GeneratorUtils

using DataStructures: OrderedDict
using JSON

# Modify as desired.
const IO_IN = stdin
const IO_OUT = stdout

function parse_operations(operations)
    out = IOBuffer()
    for op in operations
        op_name = op["operation"]
        if op_name == "read"
            if op["should_succeed"]
                s = "@test popfirst!(cb) == $(op["expected"])"
            else
                s = "@test_throws BoundsError popfirst!(cb)"
            end
        elseif op_name == "write"
            item = op["item"]
            if op["should_succeed"]
                s = "@test push!(cb, $item) === cb"
            else
                s = "@test_throws BoundsError push!(cb, $item)"
            end
        elseif op_name == "overwrite"
            s = "@test push!(cb, $(op["item"]); overwrite=true) === cb"
        elseif op_name == "clear"
            s = "@test empty!(cb) === cb"
        else
            throw(ArgumentError("Unrecognized operation `$op_name`."))
        end
        write(out, s, '\n')
    end
    out.size -= 1  # remove last newline
    return String(take!(out))
end

function print_custom_tests(io::IO)
    println(
        io,
        """
        @testset "overwrite=true and overwrite=false" begin
            cb = CircularBuffer{Int}(2)
            @test empty!(cb) === cb
            @test push!(cb, 1; overwrite=true) === cb
            @test push!(cb, 2; overwrite=true) === cb
            @test_throws BoundsError push!(cb, 3; overwrite=false)
            @test push!(cb, 4; overwrite=true) === cb
            @test popfirst!(cb) == 2
            @test popfirst!(cb) == 4
            @test_throws BoundsError popfirst!(cb)
        end

        @testset "type parameter" begin
            cb = CircularBuffer{Int}(1)
            @test_throws Exception push!(cb, "0")
            cb = CircularBuffer{String}(1)
            @test_throws Exception push!(cb, 0)
            @test push!(cb, "0") === cb
            @test popfirst!(cb) == "0"
        end
        """
    )
end

function print_bonus_tests(io::IO)
    println(
        io,

        """
# Uncomment the following line to enable bonus tests.
# enable_bonus_tests = true

if @isdefined(enable_bonus_tests) && enable_bonus_tests
    println("\\nBonus tests enabled.\\n")

    @testset "is subtype of AbstractVector" begin
        @test CircularBuffer <: AbstractVector
    end

    # Copied from DataStructures.jl and slightly modified.
    @testset "Bonus test set taken from DataStructures.jl (CircularBuffer)" begin
        @testset "Core Functionality" begin
            cb = CircularBuffer{Int}(5)
            @testset "When empty" begin
                @test length(cb) == 0
                @test capacity(cb) == 5
                @test_throws BoundsError first(cb)
                @test_throws BoundsError last(cb)
                @test isempty(cb) == true
                @test isfull(cb) == false
                @test eltype(cb) == Int
                @test eltype(typeof(cb)) == Int
            end

            @testset "With 1 element" begin
                push!(cb, 1)
                @test length(cb) == 1
                @test capacity(cb) == 5
                @test isfull(cb) == false
                @test first(cb) == last(cb)
            end

            @testset "Appending many elements" begin
                append!(cb, 2:8; overwrite=true)
                @test length(cb) == capacity(cb)
                @test size(cb) == (length(cb),)
                @test isempty(cb) == false
                @test isfull(cb) == true
                @test convert(Array, cb) == Int[4,5,6,7,8]
            end

            @testset "getindex" begin
                @test cb[1] == 4
                @test cb[2] == 5
                @test cb[3] == 6
                @test cb[4] == 7
                @test cb[5] == 8
                @test_throws BoundsError cb[6]
                @test_throws BoundsError cb[3:6]
                @test cb[3:4] == Int[6,7]
                @test cb[[1,5]] == Int[4,8]
                @test first(cb) == 4
                @test last(cb) == 8
            end

            @testset "setindex" begin
                cb[3] = 999
                @test convert(Array, cb) == Int[4,5,999,7,8]
            end
        end

        @testset "pushfirst" begin
            cb = CircularBuffer{Int}(5)  # New, empty one for full test coverage
            for i in -5:5
                pushfirst!(cb, i; overwrite=true)
            end
            arr = convert(Array, cb)
            @test arr == Int[5, 4, 3, 2, 1]
            for (idx, n) in enumerate(5:1)
                @test arr[idx] == n
            end
        end

        @testset "Issue 429" begin
            cb = CircularBuffer{Int}(5)
            map(x -> pushfirst!(cb, x; overwrite=true), 1:8)
            pop!(cb)
            pushfirst!(cb, 9)
            arr = convert(Array, cb)
            @test arr == Int[9, 8, 7, 6, 5]
        end

        @testset "Issue 379" begin
            cb = CircularBuffer{Int}(5)
            pushfirst!(cb, 1)
            @test cb == [1]
            pushfirst!(cb, 2)
            @test cb == [2, 1]
        end

        @testset "empty!" begin
            cb = CircularBuffer{Int}(5)
            push!(cb, 13)
            empty!(cb)
            @test length(cb) == 0
        end

        @testset "pop!" begin
            cb = CircularBuffer{Int}(5)
            for i in 0:5    # one extra to force wraparound
                push!(cb, i; overwrite=true)
            end
            for j in 5:-1:1
                @test pop!(cb) == j
                @test convert(Array, cb) == collect(1:j-1)
            end
            @test isempty(cb)
            @test_throws BoundsError pop!(cb)
        end

        @testset "popfirst!" begin
            cb = CircularBuffer{Int}(5)
            for i in 0:5    # one extra to force wraparound
                push!(cb, i; overwrite=true)
            end
            for j in 1:5
                @test popfirst!(cb) == j
                @test convert(Array, cb) == collect(j+1:5)
            end
            @test isempty(cb)
            @test_throws BoundsError popfirst!(cb)
        end
    end
end
"""
    )
end # print_bonus_tests

function main()
    canonical_data = tighten(JSON.parse(IO_IN; dicttype=OrderedDict))

    for case in canonical_data["cases"]
        input = case["input"]
        override!(
            case;
            setup="cb = CircularBuffer{Int}($(input["capacity"]))",
            test=parse_operations(input["operations"]),
        )
    end

    print_runtests(IO_OUT, canonical_data)
    print_custom_tests(IO_OUT)
    print_bonus_tests(IO_OUT)
end

main()


text:
"""
    Trixi

**Trixi.jl** is a numerical simulation framework for hyperbolic conservation
laws. A key objective for the
framework is to be useful to both scientists and students. Therefore, next to
having an extensible design with a fast implementation, Trixi is
focused on being easy to use for new or inexperienced users, including the
installation and postprocessing procedures.

See also: [trixi-framework/Trixi.jl](https://github.com/trixi-framework/Trixi.jl)
"""
module Trixi

# Include other packages that are used in Trixi
# (standard library packages first, other packages next, all of them sorted alphabetically)
using LinearAlgebra: dot
using Pkg.TOML: parsefile
using Printf: @printf, @sprintf, println
using Profile: clear_malloc_data
using Random: seed!

using EllipsisNotation
using HDF5: h5open, attrs
using StaticArrays: @MVector, @SVector, MVector, MMatrix, MArray, SVector, SMatrix, SArray
using TimerOutputs: @notimeit, @timeit, TimerOutput, print_timer, reset_timer!
using UnPack: @unpack

# Tullio.jl makes use of LoopVectorization.jl via Requires.jl.
# Hence, we need `using LoopVectorization` after loading Tullio and before using @tullio.
using Tullio: @tullio
using LoopVectorization

# Use a central dictionary for global settings
const globals = Dict{Symbol, Any}()
export globals

# Include all top-level source files
include("auxiliary/auxiliary.jl")
include("equations/equations.jl")
include("mesh/mesh.jl")
include("solvers/solvers.jl")
include("io/io.jl")
include("timedisc/timedisc.jl")
include("amr/amr.jl")

# Include top-level run method
include("run.jl")

# export types/functions that define the public API of Trixi
export CompressibleEulerEquations2D, CompressibleEulerEquations3D,
       IdealGlmMhdEquations2D, IdealGlmMhdEquations3D,
       HyperbolicDiffusionEquations2D, HyperbolicDiffusionEquations3D,
       LinearScalarAdvectionEquation2D, LinearScalarAdvectionEquation3D
export flux_central, flux_lax_friedrichs, flux_hll,
       flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_kennedy_gruber, flux_shima_etal
export examples_dir, get_examples, default_example

end

ext: jl


text:
#run the time series regressions
function analyzeqfactors(;Ftest::Vector{Symbol} = FF_PORT_VALS,
  Ffactors::Vector{Symbol} = FACTOR_FIELDS,
  factname::String = FACT_NAME, outpath::String = OUT_PATH)

  #read in the data nd make the requisite structure
  df = CSV.read("$outpath\\$factname.csv") |> DataFrame
  fs::FactorSpec = FactorSpec(df, :date, Ffactors, Ftest)

  #not strictly necessary, but helps stop doubling up on the multi-threading
  PARALLEL[] && (BLAS.set_num_threads(1))

  #run the regressions
  results::Vector{FMLM} = timeseriesregressions(fs)

  #make the output table

end

max_stars_repo_name: clintonTE/CCA

max_issues_repo_name: clintonTE/CCA

max_forks_repo_name: clintonTE/CCA


text:
type IdDict{T}
    key2id::Dict{T,Int}
    id2key::Vector{T}
    id2count::Vector{Int}

    IdDict() = new(Dict{T,Int}(), T[], Int[])
end
IdDict() = IdDict{Any}()

function IdDict{T}(data::Vector{T})
    d = IdDict{T}()
    for x in data
        push!(d, x)
    end
    d
end

function IdDict(f, path::String)
    data = map(x -> f(chomp(x)), open(readlines,path))
    IdDict(data)
end
IdDict(path::String) = IdDict(identity, path)

Base.count(d::IdDict, id::Int) = d.id2count[id]

Base.getkey(d::IdDict, id::Int) = d.id2key[id]

Base.getindex(d::IdDict, key) = d.key2id[key]

Base.get(d::IdDict, key, default=0) = get(d.key2id, key, default)

Base.length(d::IdDict) = length(d.key2id)

function Base.push!{T}(d::IdDict{T}, key::T)
    if haskey(d.key2id, key)
        id = d.key2id[key]
        d.id2count[id] += 1
    else
        id = length(d.id2key) + 1
        d.key2id[key] = id
        push!(d.id2key, key)
        push!(d.id2count, 1)
    end
    id
end

Base.append!{T}(d::IdDict{T}, keys::Vector{T}) = map(k -> push!(d,k), keys)

max_stars_repo_name: hshindo/Merlin-Examples

max_issues_repo_name: hshindo/Merlin-Examples

max_forks_repo_name: hshindo/Merlin-Examples


text:
#-----------------------------------------------------------------#
# This routine advances the solution in time using Split-Explicit using a
# General Order RK method in Butcher tableau form following as in Schlegel et al. GMD 2012.
# Written by F.X. Giraldo / P.R. Mugg on 9/22/2019
#           Department of Applied Mathematics
#           Naval Postgraduate School
#           Monterey, CA 93943-5216
#------------------------------------------------------------------#

function multirate_erk_butcher(q0,c,αI,βI,I,αJ,βJ,J,Δt,time)

    #Compute Coefficients
    #Outer Loop
    α̃I = zeros(I+1,I)
    c̃I = zeros(I+1,1)
    cI = zeros(I,1)
    for i = 2:I
        cI[i] = sum(αI[i,:])
        α̃I[i,:] = αI[i,:] - αI[i-1,:]
        c̃I[i] = cI[i] - cI[i-1]
    end
    for j = 1:I
        α̃I[I+1,j] = βI[j] - αI[I,j]
    end
    c̃I[I+1] = 1.0 - cI[I]

    #Inner Loop
    α̃J = zeros(J+1,J)
    c̃J = zeros(J+1,1)
    cJ = zeros(J,1)
    for i = 2:J
        cJ[i] = sum(αJ[i,:])
        α̃J[i,:] = αJ[i,:] - αJ[i-1,:]
        c̃J[i] = cJ[i] - cJ[i-1]
    end
    for j = 1:J
        α̃J[J+1,j] = βJ[j] - αJ[J,j]
    end
    c̃J[J+1] = 1.0 - cJ[J]

    #Initialize Arrays
    Q = zeros(I+1)
    V = zeros(I+1,J+1)

    #Outer Loop
    Q[1] = q0
    for i = 2:I+1
        r_i = 0
        for j = 1:i-1
            t = time + Δt*cI[j]
            (rhs,f𝑗,g𝑗) = rhs_function(Q[j],c,t)
            r_i += α̃I[i,j]*g𝑗
        end

        V[i] = Q[i-1]
        #Inner Loop
        for j = 2:J+1
            R_sum = 0
            for k = 1:j-1
                t = time + Δt*( cI[i-1] + c̃I[i]*cJ[k] )           # doesn't seem to matter
                (rhs,f𝑘,g𝑘) = rhs_function(V[i,k],c,t)
                R_sum += α̃J[j,k]*( r_i + c̃I[i]*f𝑘 )
            end # end k loop
            V[i,j] = V[i,j-1] + Δt*R_sum
        end # end j loop
        Q[i] = V[i,J+1]
    end # end i loop

    return qp = Q[I+1]

end # end multirate_erk_butcher function


text:
using Documenter, BlockMaps

makedocs(;
    modules=[BlockMaps],
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/jagot/BlockMaps.jl/blob/{commit}{path}#L{line}",
    sitename="BlockMaps.jl",
    authors="Stefanos Carlström <stefanos.carlstrom@gmail.com>",
    assets=String[],
)

deploydocs(;
    repo="github.com/jagot/BlockMaps.jl",
)


text:
# Comparison to a situation when all values are being put in one
# channel. Note in such situation we will have only one receiving
# channel. This example also shows a starvation issue as consumer gets
# `nothing` only after all numbers are consumed.

consumer = Channel()

t3 = @async begin
    for i in 1:1000000
        put!(consumer, i)
    end
end

t4 = @async begin
    sleep(1)
    put!(consumer, nothing)
end

let
    state = 0

    start = time()

    while true

        value = take!(consumer)

        if value == nothing
            break
        end

        state = value

    end

    duration = time() - start

    @show duration, state

end


text:
using NNlib:softmax

"""
    struct GradientBanditLearner{Ts<:AbstractActionSelector, Tb<:Union{Float64, Function}} <: AbstractModelFreeLearner
        Q::TabularQ
        selector::Ts
        α::Float64
        baseline::Tb
    end

See more details at Section (2.8) on Page 37 of the book *Sutton, Richard S., and Andrew G. Barto. Reinforcement learning: An introduction. MIT press, 2018.*
"""
struct GradientBanditLearner{Ts<:AbstractActionSelector, Tb<:Union{Float64, Function}} <: AbstractModelFreeLearner
    Q::TabularQ
    selector::Ts
    α::Float64
    baseline::Tb
end

function (learner::GradientBanditLearner)(s::Int)
    s |> learner.Q |> softmax |> learner.selector
end

function update!(learner::GradientBanditLearner, s, a, R, R̄)
    α = learner.α
    prob = s |> learner.Q |> softmax
    errors = α * (R - R̄) .* (onehot(length(prob), a, Float64) .- prob)
    update!(learner.Q, s, errors)
end

update!(learner::GradientBanditLearner{<:AbstractActionSelector, Float64}, s, a, r) = update!(learner, s, a, r, learner.baseline)
update!(learner::GradientBanditLearner{<:AbstractActionSelector, <:Function}, s, a, r) = update!(learner, s, a, r, learner.baseline(r))

function update!(learner::GradientBanditLearner, buffer::SARDBuffer)
    update!(learner, buffer.state[end-1], buffer.action[end-1], buffer.reward[end])
end

function update!(learner::GradientBanditLearner, buffer::Union{SARDSABuffer, SARDSBuffer})
    update!(learner, buffer.state[end], buffer.action[end], buffer.reward[end])
end


text:
using MD5

hex(s) = string(s, base=16)
"""
Downloads a dataset located at a given url to a path. The function is taken
from Flux.jl/Data.jl
``https://github.com/FluxML/Flux.jl/blob/ea26f45a1f4e93d91b1e8942c807f8bf229d5775/src/data/Data.jl#L26``
"""
function download_dataset(url, path, hash=nothing)
  println("Downloading...")
  if hash !== nothing
    tmppath = tempname()
    download(url, tmppath)
    hash_download = bytes2hex(open(md5, tmppath))
    if hash_download !== hash
      msg  = "Hash Mismatch!\n"
      msg *= "  Expected md5: $hash\n"
      msg *= "  Calculated md5: $hash_download\n"
      @warn msg
    end
    mv(tmppath, path; force = true)
  else
    download(url, path)
  end
end

function is_new(path::String, online_hash)
  if online_hash === nothing
    @warn "No hash-value provided. File might have been modified. You can force_download trigger a new download."
    return false
  else
    offline_hash = bytes2hex(open(md5, path))
    return offline_hash !== online_hash
  end
end

function get_filepath(filename)
  path = @__DIR__
  path *= "/../data/"
  return path*"$filename"
end

function download_system_data_if_required(filename, url, hash=nothing; force_download = false)
  filepath = get_filepath(filename)
  if !isfile(filepath)
    download_dataset(url, filepath, hash)
  elseif is_new(filepath, hash)
    println("Local file is modified.")
    download_dataset(url, filepath, hash)
  elseif force_download === true
    download_dataset(url, filepath, hash)
  end
end


text:
using Plots

function plot_dataset_distribution(dataset_setup::Dataset; id::String="",
                                   imagename::String = "dataset-distribution.png")
    plot_distribution(dataset_setup.output_train, dataset_setup.labels, id = id, imagename = imagename)
end

function plot_dataset_distribution(dataset_setup::SeparatedDataset; set::Symbol=:training, id::String="",
                                   imagename::String = "dataset-distribution.png")
    if set == :training
        plot_distribution(dataset_setup.output_train, dataset_setup.labels, id = string(id, " (training)"), imagename = imagename)
    elseif set == :test
        plot_distribution(dataset_setup.output_test, dataset_setup.labels, id = string(id, " (test)"), imagename = imagename)
    end
end

function plot_distribution(outputs::Vector{Vector{T}}, labels::Vector{T}; id::String="",
                          imagename::String = "dataset-distribution.png") where T <: Number
    distribution = countmap(getindex.(outputs,1))
    frequencies = getindex.([distribution], labels)
    title = id == "" ? "Dataset distribution" : "Dataset $id distribution"
    dist = plot(labels, frequencies, xlabel = "Class", xticks = 0:1:length(labels), linetype=[:bar],
              ylabel = "Number of samples", title = title, legend=false, color=:purple)
    savefig(dist, imagename)
end

max_stars_repo_name: Lucas-Muniz/MNEAT

max_issues_repo_name: Lucas-Muniz/MNEAT

max_forks_repo_name: Lucas-Muniz/MNEAT


text:
# Example for basic 2D modeling:
# The receiver positions and the source wavelets are the same for each of the four experiments.
# Author: Philipp Witte, pwitte@eos.ubc.ca
# Date: January 2017
#
# Author: Mathias Louboutin, mlouboutin3@gatech.edu
# Update Date: July 2020

### Model
model, model0, dm = setup_model(tti, viscoacoustic, nlayer)
q, srcGeometry, recGeometry, f0 = setup_geom(model)
dt = srcGeometry.dt[1]

m0 = model0.m
######################## WITH DENSITY ############################################

@testset "Jacobian test with $(nlayer) layers and tti $(tti) and viscoacoustic $(viscoacoustic) freesurface $(fs)" begin
    # Write shots as segy files to disk
    opt = Options(sum_padding=true, dt_comp=dt, free_surface=fs, f0=f0)

    # Setup operators
    Pr = judiProjection(recGeometry)
    F = judiModeling(model; options=opt)
    F0 = judiModeling(model0; options=opt)
    Ps = judiProjection(srcGeometry)
    J = judiJacobian(Pr*F0*adjoint(Ps), q)

    # Linear modeling
    dobs = Pr*F0*Ps'*q
    dD = J*dm

    @test norm(J*(0f0.*dm)) == 0
    @test isapprox(dD, J*vec(dm.data); rtol=1f-6)

    # Jacobian test
    maxiter = 6
    h = 5f-2
    err1 = zeros(Float32, maxiter)
    err2 = zeros(Float32, maxiter)

    for j=1:maxiter

        F.model.m = m0 + h*dm
        dpred = Pr*F*Ps'*q

        err1[j] = norm(dpred - dobs)
        err2[j] = norm(dpred - dobs - h*dD)
        j == 1 ? prev = 1 : prev = j - 1
        @printf("h = %2.2e, e1 = %2.2e, rate = %2.2e", h, err1[j], err1[prev]/err1[j])
        @printf(", e2 = %2.2e, rate = %2.2e \n", err2[j], err2[prev]/err2[j])

        h = h * .8f0
    end
end

### Extended source

@testset "Extended source Jacobian test with $(nlayer) layers and tti $(tti) and freesurface $(fs)" begin
    @timeit TIMEROUTPUT "Extended source Jacobian" begin
        opt = Options(sum_padding=true, dt_comp=dt, return_array=true, free_surface=fs, f0=f0)

        # Setup operators
        Pr = judiProjection(recGeometry)
        F = judiModeling(model; options=opt)
        F0 = judiModeling(model0; options=opt)
        Pw = judiLRWF(q.geometry.dt[1], q.data[1])

        # Combined operators
        A = Pr*F*adjoint(Pw)
        A0 = Pr*F0*adjoint(Pw)

        # Extended source weights
        w = judiWeights(randn(Float32, model0.n))
        J = judiJacobian(A0, w)

        # Nonlinear modeling
        dobs = A0*w
        wa = adjoint(A0)*dobs
        @test typeof(dobs) == Vector{Float32}
        @test typeof(wa) == Vector{Float32}
        dD = J*dm
        @test typeof(dD) == Vector{Float32}

        # Jacobian test
        maxiter = 6
        h = 5f-2
        err1 = zeros(Float32, maxiter)
        err2 = zeros(Float32, maxiter)

        for j=1:maxiter

            A.model.m = m0 + h*dm
            dpred = A*w
            @test typeof(dpred) == Vector{Float32}

            err1[j] = norm(dpred - dobs)
            err2[j] = norm(dpred - dobs - h*dD)
            j == 1 ? prev = 1 : prev = j - 1
            @printf("h = %2.2e, e1 = %2.2e, rate = %2.2e", h, err1[j], err1[prev]/err1[j])
            @printf(", e2 = %2.2e, rate = %2.2e \n", err2[j], err2[prev]/err2[j])

            h = h * .8f0
        end

        rate_1 = sum(err1[1:end-1]./err1[2:end])/(maxiter - 1)
        rate_2 = sum(err2[1:end-1]./err2[2:end])/(maxiter - 1)

        @test isapprox(rate_1, 1.25f0; rtol=1f-2)
        @test isapprox(rate_2, 1.5625f0; rtol=1f-2)
    end
end


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

module Web

using Random
using Dates
using Swagger
import Swagger: field_name, property_type, hasproperty, validate_property, SwaggerApi, SwaggerModel
import Base: convert, propertynames

include("modelincludes.jl")

include("api_AdminApi.jl")
include("api_AdminAppsApi.jl")
include("api_AdminAppsApprovedApi.jl")
include("api_AdminAppsRequestsApi.jl")
include("api_AdminAppsRestrictedApi.jl")
include("api_AdminConversationsApi.jl")
include("api_AdminConversationsEkmApi.jl")
include("api_AdminConversationsRestrictAccessApi.jl")
include("api_AdminEmojiApi.jl")
include("api_AdminInviteRequestsApi.jl")
include("api_AdminInviteRequestsApprovedApi.jl")
include("api_AdminInviteRequestsDeniedApi.jl")
include("api_AdminTeamsApi.jl")
include("api_AdminTeamsAdminsApi.jl")
include("api_AdminTeamsOwnersApi.jl")
include("api_AdminTeamsSettingsApi.jl")
include("api_AdminUsergroupsApi.jl")
include("api_AdminUsersApi.jl")
include("api_AdminUsersSessionApi.jl")
include("api_ApiApi.jl")
include("api_AppsApi.jl")
include("api_AppsEventAuthorizationsApi.jl")
include("api_AppsPermissionsApi.jl")
include("api_AppsPermissionsResourcesApi.jl")
include("api_AppsPermissionsScopesApi.jl")
include("api_AppsPermissionsUsersApi.jl")
include("api_AuthApi.jl")
include("api_BotsApi.jl")
include("api_CallsApi.jl")
include("api_CallsParticipantsApi.jl")
include("api_ChatApi.jl")
include("api_ChatScheduledMessagesApi.jl")
include("api_ConversationsApi.jl")
include("api_DialogApi.jl")
include("api_DndApi.jl")
include("api_EmojiApi.jl")
include("api_FilesApi.jl")
include("api_FilesCommentsApi.jl")
include("api_FilesRemoteApi.jl")
include("api_MigrationApi.jl")
include("api_OauthApi.jl")
include("api_OauthV2Api.jl")
include("api_PinsApi.jl")
include("api_ReactionsApi.jl")
include("api_RemindersApi.jl")
include("api_RtmApi.jl")
include("api_SearchApi.jl")
include("api_StarsApi.jl")
include("api_TeamApi.jl")
include("api_TeamProfileApi.jl")
include("api_UsergroupsApi.jl")
include("api_UsergroupsUsersApi.jl")
include("api_UsersApi.jl")
include("api_UsersProfileApi.jl")
include("api_ViewsApi.jl")
include("api_WorkflowsApi.jl")

# export models
export convert, Blocks
export convert, BlocksInner
export convert, DefsAppId
export convert, DefsBotId
export convert, DefsChannel
export convert, DefsChannelId
export convert, DefsChannelName
export convert, DefsCommentId
export convert, DefsDmId
export convert, DefsEnterpriseId
export convert, DefsEnterpriseName
export convert, DefsEnterpriseUserId
export convert, DefsFileId
export convert, DefsGroupId
export convert, DefsOkFalse
export convert, DefsOkTrue
export convert, DefsOptionalAppId
export convert, DefsPinnedInfo
export convert, DefsReminderId
export convert, DefsSubteamId
export convert, DefsTeam
export convert, DefsTopicPurposeCreator
export convert, DefsTs
export convert, DefsUserId
export convert, DefsWorkspaceId
export convert, ObjsBotProfile
export convert, ObjsBotProfileIcons
export convert, ObjsChannel
export convert, ObjsChannelPurpose
export convert, ObjsComment
export convert, ObjsComments
export convert, ObjsConversation
export convert, ObjsEnterpriseUser
export convert, ObjsExternalOrgMigrations
export convert, ObjsExternalOrgMigrationsCurrent
export convert, ObjsFile
export convert, ObjsFileShares
export convert, ObjsIcon
export convert, ObjsMessage
export convert, ObjsMessageAttachments
export convert, ObjsMessageIcons
export convert, ObjsPaging
export convert, ObjsPrimaryOwner
export convert, ObjsReaction
export convert, ObjsReminder
export convert, ObjsResources
export convert, ObjsResponseMetadata
export convert, ObjsScopes
export convert, ObjsSubteam
export convert, ObjsSubteamPrefs
export convert, ObjsTeam
export convert, ObjsTeamProfileField
export convert, ObjsTeamProfileFieldOption
export convert, ObjsTeamSsoProvider
export convert, ObjsUser
export convert, ObjsUserProfile
export convert, ObjsUserProfileShort

# export operations
export convert, AdminApi, AdminAppsApi, AdminAppsApprovedApi, AdminAppsRequestsApi, AdminAppsRestrictedApi, AdminConversationsApi, AdminConversationsEkmApi, AdminConversationsRestrictAccessApi, AdminEmojiApi, AdminInviteRequestsApi, AdminInviteRequestsApprovedApi, AdminInviteRequestsDeniedApi, AdminTeamsApi, AdminTeamsAdminsApi, AdminTeamsOwnersApi, AdminTeamsSettingsApi, AdminUsergroupsApi, AdminUsersApi, AdminUsersSessionApi, ApiApi, AppsApi, AppsEventAuthorizationsApi, AppsPermissionsApi, AppsPermissionsResourcesApi, AppsPermissionsScopesApi, AppsPermissionsUsersApi, AuthApi, BotsApi, CallsApi, CallsParticipantsApi, ChatApi, ChatScheduledMessagesApi, ConversationsApi, DialogApi, DndApi, EmojiApi, FilesApi, FilesCommentsApi, FilesRemoteApi, MigrationApi, OauthApi, OauthV2Api, PinsApi, ReactionsApi, RemindersApi, RtmApi, SearchApi, StarsApi, TeamApi, TeamProfileApi, UsergroupsApi, UsergroupsUsersApi, UsersApi, UsersProfileApi, ViewsApi, WorkflowsApi

export check_required, field_name, property_type, hasproperty, propertynames, validate_property, convert

end


text:
using FeatureExtraction
using MLKernels
using Base.Test

MOD = FeatureExtraction

FloatingPointTypes = (Float32, Float64)

# Unit Tests
include("test_common.jl")
include("test_kpca.jl")


text:
# Integrate with k-means better
function dp_means{T <: Real}(data::Matrix{T}, lambda::Real, opts::Options)
    @defaults opts tolerance => 10e-8
    @defaults opts max_iter => 1_000

    # Keep track of the number of data points
    n, p = size(data)

    # Initially assign all data points to a single cluster
    k = 1
    assignments = ones(Int64, n)
    centers = mean(data, 1)
    distances = Array(Float64, k)

    # Keep working until convergence or exceeding bound on iterations
    converged, iter = false, 0

    # Keep track of error in system
    ss_old, ss_new = Inf, Inf

    while !converged && iter < max_iter
        iter += 1

        # Update cluster assignments
        for i in 1:n
            for cluster in 1:k
                d = 0.0
                for j in 1:p
                    d += (data[i, j] - centers[cluster, j])^2
                end
                distances[cluster] = d
            end
            d_min, ind_min = findmin(distances)
            if d_min > lambda
                k += 1
                assignments[i] = k
                centers = vcat(centers, data[i, :])
                push!(distances, 0.0)
            else
                assignments[i] = ind_min
            end
        end

        # Update cluster centers for non-empty clusters
        for cluster in 1:k
            n_obs = 0
            for i in 1:n
                if assignments[i] == cluster
                    n_obs += 1
                end
            end
            if n_obs > 0
                for j in 1:p
                    centers[cluster, j] = 0.0
                end
            end
            for i in 1:n
                if assignments[i] == cluster
                    for j in 1:p
                        centers[cluster, j] += data[i, j]
                    end
                end
            end
            for j in 1:p
                centers[cluster, j] /= n_obs
            end
        end

        # Update convergence criterion
        ss_old, ss_new = ss_new, 0.0
        for i in 1:n
            for j in 1:p
                ss_new += (data[i, j] - centers[assignments[i], j])^2
            end
        end
        ss_change = ss_old - ss_new
        if !isnan(ss_change) && ss_change < tolerance
            converged = true
        end
    end

    results = DPMeansOutput(assignments,
                            centers,
                            k,
                            iter,
                            ss_new,
                            converged)

    return results
end

function dp_means{T <: Real}(data::Matrix{T}, lambda::Real)
    dp_means(data, lambda, Options())
end


text:
using Zlib

function int4unpack(bytes)
    int(reinterpret(Int32, reverse(bytes))[1])
end

function int2unpack(bytes)
    int(reinterpret(Int8, reverse(bytes))[1])
end

function floatunpack(bytes)
    reinterpret(Float64, reverse(bytes))[1]
end

function charintpack(value::Integer, size::Int)
    bytes = zeros(Uint8, size)
    for i=1:size
        bytes[i] = uint8(value)
        value = value >>> 8
        end
    reverse(bytes)
end

function charintpack(value::Integer)
    bytes = []
    while value != 0
        bytes = vcat(bytes, uint8(value & 0xff))
        value = value >>> 8
    end
    uint8(bytes)
end

function charint4pack(integer::Integer)
    charintpack(integer, 4)
end

function charint2pack(integer::Integer)
    charintpack(integer, 2)
end

function charsignedint4pack(integer::Integer)
    charintpack(integer, 4)
end

function lencheck(bytes::Array{Uint8,1}, limit::Int64)
    len = length(bytes)
    lencheck(len, len < limit, bytes)
end

function lencheck(bytes::Array{Uint8,1}, pred::Bool)
    len = length(bytes)
    lencheck(len, pred, bytes)
end

function lencheck(len::Int64, limit::Int64, bytes::Array{Uint8,1})
    lencheck(limit, len < limit, bytes)
end

function lencheck(len::Int64, pred::Bool, bytes::Array{Uint8,1})
    if pred
        throw(IncompleteData(bytes))
    end
    len
end

function compressterm(encodedterm, compression::Bool)
    compressterm(encodedterm, 6)
end

function compressterm(encodedterm, compression::Int)
    if compression < 0 || compression > 9
        throw(InvalidCompressionLevel(compression))
    end
    comp = Zlib.compress(encodedterm, compression)
    len = length(encodedterm)
    # XXX add check here for too small of length
    if length(comp) + 5 <= len
        vcat(int4pack(len), comp)
    end
end

function decompressterm(bytes::Array{Uint8,1})
    if length(bytes) < 16
        throw(IncompleteData(bytes))
    end
    sentlen = int4unpack(bytes[3:6])
    term = Zlib.decompress(bytes[7:end])
    actuallen = length(term)
    if actuallen != sentlen
        msg = "Header declared $sentlen bytes but got $actuallen bytes."
        throw(InvalidCompressedTag(msg))
    end
    return term
end


text:
deg = 3
pl, wl = tri_quadrature(deg)
V = vandermonde_matrix(Tri, deg, pl[:, 1], pl[:, 2])
Vr, Vs = ∂vandermonde_matrix(Tri, deg, pl[:, 1], pl[:, 2])
∂l = ∂lagrange(V, Vr, Vs)

a, b = rs_ab(pl[:, 1], pl[:, 2])

p1 = [-1.0, -1 / √3]
p2 = [1.0, -1 / √3]
p3 = [0.0, 2 / √3]
p = (p1, p2, p3)
points, weights = tri_quadrature(3, vertices = p)

@test points == pl
@test weights == wl

r, s = xy_rs(points)
a, b = rs_ab(r, s)
V = vandermonde_matrix(Tri, 3, r, s)

#using Plots
#scatter(points[:, 1], points[:, 2])


text:
# Utilities

##### Buffer

immutable XBuffer
    ptr::Xptr

    function XBuffer(bytes::Integer)
        p = ccall(xmlBufferCreateSize, Xptr, (Csize_t,), bytes)
        p != nullptr || error("Failed to create buffer of $bytes bytes.")
        new(p)
    end
end

free(buf::XBuffer) = ccall(xmlBufferFree, Void, (Xptr,), buf.ptr)

Base.length(buf::XBuffer) = int(ccall(xmlBufferLength, Cint, (Xptr,), buf.ptr))

content(buf::XBuffer) = bytestring(ccall(xmlBufferContent, Xstr, (Xptr,), buf.ptr))


text:
function windowing!(N::Int, Map::Array{Float64, 2}; type="default")

    inds = (((0:(N-1)) .+ 0.5 .- (N/2)) ./ N ) .* π
    X = reshape(repeat(inds, N), N ,N)
    Y = X'

    window = cos.(X) .* cos.(Y)

    window .* Map

end

function windowing_k!(N::Int, Map::Array{Float64, 2}; type="default")

    inds = (((0:(N-1)) .+ 0.5 .- (N/2)) ./ N ) .* π
    X = reshape(repeat(inds, N), N ,N)
    Y = X'

    window = (α^2) * sqrt(1-( 2*X / (N-1) - 1) .^2) * sqrt(1-( 2*Y / (N-1) - 1) .^2)

    window .* Map

end

function get_power_spectrum(Map1::Array{Float64, 2}, Map2::Array{Float64, 2},
                            max_ell::Float64, delta_ell::Float64,
                            pix_size::Float64, N::Int)

    inds = ((0:(N-1)) .+ 0.5 .- (N/2)) ./ (N - 1.0)
    X  = reshape(repeat(range(-0.5, 0.5, length=N), N), N, N)
    Y = X'
    R = (X .^2 .+ Y .^2) .^0.5
    pix_to_rad = pix_size / 60. * π  / 180.
    lsf = 2. * π / pix_to_rad

    ell2d = R .* lsf

    N_bins = Int(round(max_ell / delta_ell))

    ell_array = Array{Float64, 1}(undef, 0)
    Cl_array  = Array{Float64, 1}(undef, 0)

    FMap1 = ifft(fftshift(Map1))
    FMap2 = ifft(fftshift(Map2))
    PSMap =  fftshift(real.(conj.(FMap1) .* FMap2))

    for i = 1:N_bins

        l = (i - 0.5) * delta_ell
        append!(ell_array, l)
        Mask = (ell2d .>= ((i-1)*delta_ell)) .* (ell2d .< (i*delta_ell))
        val_cl = PSMap[Mask]
        Cl = sum(val_cl) / length(val_cl)
        append!(Cl_array, Cl)

    end

    Dl_array = Cl_array ./ (2.0 .* π ./ (ell_array .* (ell_array .+ 1.) ))

    return ell_array, Dl_array

end


text:
@testset "modes" begin

@testset "center_mode" begin
    offsets = ((-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1))
    X = [6  7  9
         5  6  2
         2  1  6]
    @test 6 == center_mode(X, CartesianIndex(2, 2), offsets)

    iX = IntegralArray(X)
    @test 6 == center_mode(iX, CartesianIndex(2, 2), CartesianIndex(0, 0), offsets)
    @test mean(X[2:3,2:3]) == center_mode(iX, CartesianIndex(2, 2), CartesianIndex(1, 1), offsets)
end

@testset "average_mode" begin
    offsets = ((-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1))
    X = [6  7  9
         5  6  2
         2  1  6]
    @test mean(X) ≈ average_mode(X, CartesianIndex(2, 2), offsets)

    iX = IntegralArray(X)
    @test mean(X) ≈ average_mode(iX, CartesianIndex(2, 2), CartesianIndex(0, 0), offsets)

    ref = (mean(X[1:2, 1:2]) + mean(X[2:3, 1:2]) + mean(X[3, 1:2]) +
          mean(X[1:2, 2:3]) + mean(X[2:3, 2:3]) + mean(X[3, 2:3]) +
          mean(X[1:2, 3  ]) + mean(X[2:3, 3  ]) + mean(X[3, 3]))/9
    @test ref ≈ average_mode(iX, CartesianIndex(2, 2), CartesianIndex(1, 1), offsets)
end

@testset "LBP" begin
    lbp = LBP((1, 1))
    @test lbp.mode == center_mode
    @test lbp.block_size == (1, 1)

    @test_throws MethodError LBP()
    @test_throws ArgumentError LBP((0, 3))
end

end


text:
module TOML

VERSION = v"0.1.2"

using Compat

if Base.VERSION >= v"0.4.0-dev+5050"
    anchored_regex(r) = Regex(r, Base.PCRE.ANCHORED, 0)
else
    anchored_regex(r) = Regex(r, Base.PCRE.ANCHORED)
end

include("datetime.jl")

type ParserState
    subject::UTF8String
    index::Integer
    line::Integer
    result::Dict{UTF8String, Any}
    cur_tbl::Dict{UTF8String, Any}
    tbl_names::Set{UTF8String}

    function ParserState{T<: @compat Union{AbstractString, Array{UInt8, 1}}}(subject::T)
        if isa(subject, @compat Union{ByteString, Array{UInt8, 1}}) && !isvalid(UTF8String, subject)
            throw(TOMLError("$T with invalid UTF-8 byte sequence."))
        end
        try
            subject = convert(UTF8String, subject)
        catch
            throw(TOMLError("Couldn't convert $T to UTF8String " *
                "(no method convert(Type{UTF8String}, $T))."))
        end
        BOM = length(subject) > 0 && subject[1] == '\ufeff'  ? true : false
        maintbl = Dict{UTF8String,Any}()
        new(
            subject,
            BOM ? 4 : 1,      # index. Strip the BOM if present.
            1,                # line
            maintbl,          # result
            maintbl,          # cur_tbl
            Set{UTF8String}() # tbl_names
        )
    end
end

include("util.jl")

function parse(subject:: @compat Union{AbstractString, Array{UInt8, 1}})
    try
        state = ParserState(subject)
        while true
            char = next_non_comment!(state)
            if char == :eof
                break
            elseif char != '['
                state.index -= 1
                key(state)
            elseif getchar(state) == '['
                state.index += 1
                table_array(state)
            else
                table(state)
            end
        end
        state.result
    catch err
        (isa(err, TOMLError) ? throw : rethrow)(err)
    end
end

const table_pattern = anchored_regex("[ \t]*([^ \t\r\n][^\]\r\n]*)\]")

function table(state::ParserState)
    m = match(table_pattern, state.subject, state.index)
    if m == nothing
        _error("Malformed table name", state)
    end
    state.index += m.match.endof
    ks = strip(m.captures[1])
    if contains(ks, "[")
        _error("Opening brackets '[' are forbidden in table names", state)
    end
    keys = split(ks, ".")
    tbl = state.result
    for (i, k) in enumerate(keys)
        if k == ""
            _error("Empty key name is not allowed in $ks", state)
        end
        if haskey(tbl, k)
            if isa(tbl[k], Dict) && (
                i != length(keys) ||
                !(join(keys, ".") in state.tbl_names)
            )
                tbl = tbl[k]
            else
                _error("Key \"$k\" already defined", state)
            end
        else
            tbl[k] = Dict{UTF8String,Any}()
            tbl = tbl[k]
        end
    end
    push!(state.tbl_names, join(keys, "."))
    endline!(state)
    state.cur_tbl = tbl
end

const table_array_pattern = anchored_regex("[ \t]*([^ \t\r\n]?[^\]\r\n]*)\]\]")

function table_array(state::ParserState)
    m = match(table_array_pattern, state.subject, state.index)
    if m == nothing
        _error("Malformed table array name", state)
    end
    state.index += m.match.endof
    ks = strip(m.captures[1])
    keys = split(ks, ".")
    tbl = state.result
    for (i, k) in enumerate(keys)
        if k == ""
            _error("Empty key name is not allowed in $ks", state)
        end
        if haskey(tbl, k)
            if i < length(keys)
                if !isa(tbl[k], @compat Union{Array{Dict{UTF8String, Any}, 1}, Dict{UTF8String, Any}})
                    _error("Attempt to overwrite key $(join(keys[1:i], '.'))", state)
                end
                if isa(tbl[k], Dict)
                    tbl = tbl[k]
                else # tbl[k] is an array
                    tbl = last(tbl[k])
                end
            else
                if !isa(tbl[k], Array{Dict{UTF8String, Any}, 1})
                    _error("Attempt to overwrite value with array", state)
                end
                push!(tbl[k], Dict{UTF8String,Any}())
                tbl = last(tbl[k])
                break
            end
        else
            if i < length(keys)
                tbl[k] = Dict{UTF8String,Any}()
                tbl = tbl[k]
            else # we're done
                tbl[k] = [Dict{UTF8String,Any}()]
                tbl = last(tbl[k])
                break
            end
        end
    end
    endline!(state)
    state.cur_tbl = tbl
end

const key_pattern = anchored_regex("([^\n\r=]*)([\n\r=])")

function key(state)
    m = match(key_pattern, state.subject, state.index)
    if m == nothing
        _error("Unexpected end of file", state)
    end
    state.index += m.match.endof
    if m.captures[2] != "="
        _error("New lines are forbidden in key names", state)
    end
    k = strip(m.captures[1])
    if k == ""
        _error("Key name can't be empty", state)
    end
    if haskey(state.cur_tbl, k)
        _error("Attempt to redefine key \"$k\"", state)
    end
    state.cur_tbl[k] = value(state)
    endline!(state)
end

function value(state)
    c = next_non_space!(state)
    if c == :eof || c == '\r' || c == '\n'
        _error("Value expected", state)
    end
    if c == '"'
        return string_value(state)
    elseif c == '['
        return array_value(state)
    elseif idem("true", state.subject, state.index - 1)
        state.index += 3
        return true
    elseif idem("false", state.subject, state.index - 1)
        state.index += 4
        return false
    elseif (d = match(date_pattern, state.subject, state.index - 1); d != nothing)
        state.index += 19
        return ymd_hms(map(s -> Base.parse(Int, s), d.captures)..., "UTC")
    elseif c == '-' || '0' <= c <= '9'
        state.index -= 1
        return numeric_value(state)
    else
        _error("Invalid value", state)
    end
end

valid_escape = @compat Dict{Char,Char}(
    '0'  => '\0',
    '"'  => '"',
    '\\' => '\\',
    '/' => '/',
    'b'  => '\b',
    'f'  => '\f',
    'n'  => '\n',
    'r'  => '\r',
    't'  => '\t',
)

function string_value(state::ParserState)
    buf = (Char)[]
    while (chr = nextchar!(state)) != '"'
        if chr == :eof
            _error("Premature end of file in a string", state)
        end
        if chr == '\r' || chr == '\n'
            _error("Unexpected end of line in a string", state)
        end
        if chr == '\\'
            chr = nextchar!(state)
            if chr == 'u'
                num = (nextchar!(state), nextchar!(state), nextchar!(state), nextchar!(state))
                try
                    chr = Base.parse(Int, string(num...), 16)
                catch
                    _error("Invalid Unicode escape sequence '\\u$(string(num...))'", state)
                end
            else
                unesc = chr
                chr = get(valid_escape, chr, :invalid)
                if chr == :invalid
                    _error("Invalid escape sequence '\\$unesc' in string", state)
                end
            end
        end
        push!(buf, chr)
    end
    Base.utf8(buf)
end

function numeric_value(state::ParserState)
    NumTyp = Int64
    acc = (Char)[]
    firstdigit = 1
    if getchar(state) == '-'
        push!(acc, '-')
        nextchar!(state)
        firstdigit = 2
    end
    local c
    while (c=nextchar!(state); c!=:eof && '0'<=c<='9')
        push!(acc, c)
    end
    if c == '.'
        push!(acc, '.')
        while (c=nextchar!(state);  c!=:eof && '0'<=c<='9')
            push!(acc, c)
        end
        if last(acc) == '.'
            _error("Malformed number", state)
        end
        NumTyp = Float64
    end
    state.index -= c==:eof ? 0 : 1

    num = 0
    try
        numrepr = string(acc...)
        num = Base.parse(NumTyp, numrepr)
    catch err
        _error("Couldn't parse number ($(repr(err)))", state)
    end
    num
end

function array_value(state)
    ary = Any[]
    local typ = Any
    while next_non_comment!(state) != ']' # covers empty arrays and trailing comas
        state.index -= 1
        val = value(state)
        if length(ary) == 0
            typ = typeof(val)
            typ = typ <: Array ? Array : typ
            ary = (typ)[]
        end
        if isa(val, typ)
            push!(ary, val)
        else
            _error("Mixed types in array: expected $typ, found $(typeof(val))", state)
        end
        c = next_non_comment!(state)
        if c == ']'
            break
        elseif c != ','
            _error("Syntax error in array. Coma expected", state)
        end
    end
    ary
end

end ## module TOML


text:
@testset "indexing" begin
    @on_device threadIdx().x
    @on_device blockDim().x
    @on_device blockIdx().x
    @on_device gridDim().x

    @on_device threadIdx().y
    @on_device blockDim().y
    @on_device blockIdx().y
    @on_device gridDim().y

    @on_device threadIdx().z
    @on_device blockDim().z
    @on_device blockIdx().z
    @on_device gridDim().z

    @testset "range metadata" begin
        foobar() = threadIdx().x
        ir = sprint(io->CUDA.code_llvm(io, foobar, Tuple{}; raw=true))

        @test occursin(r"call .+ @llvm.nvvm.read.ptx.sreg.tid.x.+ !range", ir)
    end
end

############################################################################################

@testset "math" begin
    @test testf(a->log10.(a), Float32[100])

    @testset "pow" begin
        for T in (Float32, Float64, ComplexF32, ComplexF64)
            range = (T<:Integer) ? (T(5):T(10)) : T
            @test testf((x,y)->x.^y, rand(Float32, 1), rand(range, 1))
            @test testf((x,y)->x.^y, rand(Float32, 1), -rand(range, 1))
        end
    end

    @testset "isinf" begin
      for x in (Inf32, Inf, NaN32, NaN)
        @test testf(x->isinf.(x), [x])
      end
    end

    @testset "isnan" begin
      for x in (Inf32, Inf, NaN32, NaN)
        @test testf(x->isnan.(x), [x])
      end
    end

    for op in (exp, angle, exp2, exp10, expm1)
        @testset "$op" begin
            for T in (Float32, Float64)
                @test testf(x->op.(x), rand(T, 1))
                @test testf(x->op.(x), -rand(T, 1))
            end

        end
    end

    for op in (exp, abs, abs2, angle, log)
        @testset "Complex - $op" begin
            for T in (ComplexF32, ComplexF64)
                @test testf(x->op.(x), rand(T, 1))
                @test testf(x->op.(x), -rand(T, 1))
            end

        end
    end
end

############################################################################################

endline = Sys.iswindows() ? "\r\n" : "\n"

@testset "formatted output" begin
    _, out = @grab_output @on_device @cuprintf("")
    @test out == ""

    _, out = @grab_output @on_device @cuprintf("Testing...\n")
    @test out == "Testing...$endline"

    # narrow integer
    _, out = @grab_output @on_device @cuprintf("Testing %d %d...\n", Int32(1), Int32(2))
    @test out == "Testing 1 2...$endline"

    # wide integer
    _, out = @grab_output if Sys.iswindows()
        @on_device @cuprintf("Testing %lld %lld...\n", Int64(1), Int64(2))
    else
        @on_device @cuprintf("Testing %ld %ld...\n", Int64(1), Int64(2))
    end
    @test out == "Testing 1 2...$endline"

    _, out = @grab_output @on_device begin
        @cuprintf("foo")
        @cuprintf("bar\n")
    end
    @test out == "foobar$endline"

    # c argument promotions
    function kernel(A)
        @cuprintf("%f %f\n", A[1], A[1])
        return
    end
    x = CuArray(ones(2, 2))
    _, out = @grab_output begin
        CUDA.@sync @cuda kernel(x)
    end
    @test out == "1.000000 1.000000$endline"
end

@testset "@cuprint" begin
    # basic @cuprint/@cuprintln

    _, out = @grab_output @on_device @cuprint("Hello, World\n")
    @test out == "Hello, World$endline"

    _, out = @grab_output @on_device @cuprintln("Hello, World")
    @test out == "Hello, World$endline"

    # argument interpolation (by the macro, so can use literals)

    _, out = @grab_output @on_device @cuprint("foobar")
    @test out == "foobar"

    _, out = @grab_output @on_device @cuprint(:foobar)
    @test out == "foobar"

    _, out = @grab_output @on_device @cuprint("foo", "bar")
    @test out == "foobar"

    _, out = @grab_output @on_device @cuprint("foobar ", 42)
    @test out == "foobar 42"

    _, out = @grab_output @on_device @cuprint("foobar $(42)")
    @test out == "foobar 42"

    _, out = @grab_output @on_device @cuprint("foobar $(4)", 2)
    @test out == "foobar 42"

    _, out = @grab_output @on_device @cuprint("foobar ", 4, "$(2)")
    @test out == "foobar 42"

    _, out = @grab_output @on_device @cuprint(42)
    @test out == "42"

    _, out = @grab_output @on_device @cuprint(4, 2)
    @test out == "42"

    # bug: @cuprintln failed to invokce @cuprint with endline in the case of interpolation
    _, out = @grab_output @on_device @cuprintln("foobar $(42)")
    @test out == "foobar 42$endline"

    # argument types

    # we're testing the generated functions now, so can't use literals
    function test_output(val, str)
        canary = rand(Int32) # if we mess up the main arg, this one will print wrong
        _, out = @grab_output @on_device @cuprint(val, " (", canary, ")")
        @test out == "$(str) ($(Int(canary)))"
    end

    for typ in (Int16, Int32, Int64, UInt16, UInt32, UInt64)
        test_output(typ(42), "42")
    end

    for typ in (Float32, Float64)
        test_output(typ(42), "42.000000")
    end

    test_output(Cchar('c'), "c")

    for typ in (Ptr{Cvoid}, Ptr{Int})
        ptr = convert(typ, Int(0x12345))
        test_output(ptr, Sys.iswindows() ? "0000000000012345" : "0x12345")
    end

    test_output(true, "1")
    test_output(false, "0")

    # escaping

    kernel1(val) = (@cuprint(val); nothing)
    _, out = @grab_output @on_device kernel1(42)
    @test out == "42"

    kernel2(val) = (@cuprintln(val); nothing)
    _, out = @grab_output @on_device kernel2(42)
    @test out == "42$endline"
end

@testset "@cushow" begin
    function kernel()
        seven_i32 = Int32(7)
        three_f64 = Float64(3)
        @cushow seven_i32
        @cushow three_f64
        @cushow 1f0 + 4f0
        return
    end

    _, out = @grab_output @on_device kernel()
    @test out == "seven_i32 = 7$(endline)three_f64 = 3.000000$(endline)1.0f0 + 4.0f0 = 5.000000$(endline)"
end

@testset "@cushow array pointers" begin
    function kernel()
        a = @cuStaticSharedMem(Float32, 1)
        b = @cuStaticSharedMem(Float32, 2)
        @cushow pointer(a) pointer(b)
        return
    end

    _, out = @grab_output @on_device kernel()
    @test occursin("pointer(a) = ", out)
    @test occursin("pointer(b) = ", out)
    @test occursin("= 0x", out)
end

############################################################################################

@testset "assertion" begin
    function kernel(i)
        @cuassert i > 0
        @cuassert i > 0 "test"
        return
    end

    @cuda kernel(1)
end

############################################################################################

# a composite type to test for more complex element types
@eval struct RGB{T}
    r::T
    g::T
    b::T
end

@testset "shared memory" begin

n = 256

@testset "constructors" begin
    # static
    @on_device @cuStaticSharedMem(Float32, 1)
    @on_device @cuStaticSharedMem(Float32, (1,2))
    @on_device @cuStaticSharedMem(Tuple{Float32, Float32}, 1)
    @on_device @cuStaticSharedMem(Tuple{Float32, Float32}, (1,2))
    @on_device @cuStaticSharedMem(Tuple{RGB{Float32}, UInt32}, 1)
    @on_device @cuStaticSharedMem(Tuple{RGB{Float32}, UInt32}, (1,2))

    # dynamic
    @on_device @cuDynamicSharedMem(Float32, 1)
    @on_device @cuDynamicSharedMem(Float32, (1, 2))
    @on_device @cuDynamicSharedMem(Tuple{Float32, Float32}, 1)
    @on_device @cuDynamicSharedMem(Tuple{Float32, Float32}, (1,2))
    @on_device @cuDynamicSharedMem(Tuple{RGB{Float32}, UInt32}, 1)
    @on_device @cuDynamicSharedMem(Tuple{RGB{Float32}, UInt32}, (1,2))

    # dynamic with offset
    @on_device @cuDynamicSharedMem(Float32, 1, 8)
    @on_device @cuDynamicSharedMem(Float32, (1,2), 8)
    @on_device @cuDynamicSharedMem(Tuple{Float32, Float32}, 1, 8)
    @on_device @cuDynamicSharedMem(Tuple{Float32, Float32}, (1,2), 8)
    @on_device @cuDynamicSharedMem(Tuple{RGB{Float32}, UInt32}, 1, 8)
    @on_device @cuDynamicSharedMem(Tuple{RGB{Float32}, UInt32}, (1,2), 8)
end

@testset "dynamic shmem" begin

@testset "statically typed" begin
    function kernel(d, n)
        t = threadIdx().x
        tr = n-t+1

        s = @cuDynamicSharedMem(Float32, n)
        s[t] = d[t]
        sync_threads()
        d[t] = s[tr]

        return
    end

    a = rand(Float32, n)
    d_a = CuArray(a)

    @cuda threads=n shmem=n*sizeof(Float32) kernel(d_a, n)
    @test reverse(a) == Array(d_a)
end

@testset "parametrically typed" begin
    @testset for T in [Int32, Int64, Float32, Float64]
        function kernel(d::CuDeviceArray{T}, n) where {T}
            t = threadIdx().x
            tr = n-t+1

            s = @cuDynamicSharedMem(T, n)
            s[t] = d[t]
            sync_threads()
            d[t] = s[tr]

            return
        end

        a = rand(T, n)
        d_a = CuArray(a)

        @cuda threads=n shmem=n*sizeof(T) kernel(d_a, n)
        @test reverse(a) == Array(d_a)
    end
end

@testset "alignment" begin
    # bug: used to generate align=12, which is invalid (non pow2)
    function kernel(v0::T, n) where {T}
        shared = @cuDynamicSharedMem(T, n)
        @inbounds shared[Cuint(1)] = v0
        return
    end

    n = 32
    typ = typeof((0f0, 0f0, 0f0))
    @cuda shmem=n*sizeof(typ) kernel((0f0, 0f0, 0f0), n)
end

end

@testset "static shmem" begin

@testset "statically typed" begin
    function kernel(d, n)
        t = threadIdx().x
        tr = n-t+1

        s = @cuStaticSharedMem(Float32, 1024)
        s2 = @cuStaticSharedMem(Float32, 1024)  # catch aliasing

        s[t] = d[t]
        s2[t] = 2*d[t]
        sync_threads()
        d[t] = s[tr]

        return
    end

    a = rand(Float32, n)
    d_a = CuArray(a)

    @cuda threads=n kernel(d_a, n)
    @test reverse(a) == Array(d_a)
end

@testset "parametrically typed" begin
    @testset for typ in [Int32, Int64, Float32, Float64]
        function kernel(d::CuDeviceArray{T}, n) where {T}
            t = threadIdx().x
            tr = n-t+1

            s = @cuStaticSharedMem(T, 1024)
            s2 = @cuStaticSharedMem(T, 1024)  # catch aliasing

            s[t] = d[t]
            s2[t] = d[t]
            sync_threads()
            d[t] = s[tr]

            return
        end

        a = rand(typ, n)
        d_a = CuArray(a)

        @cuda threads=n kernel(d_a, n)
        @test reverse(a) == Array(d_a)
    end
end

@testset "alignment" begin
    # bug: used to generate align=12, which is invalid (non pow2)
    function kernel(v0::T) where {T}
        shared = CUDA.@cuStaticSharedMem(T, 32)
        @inbounds shared[Cuint(1)] = v0
        return
    end

    @cuda kernel((0f0, 0f0, 0f0))
end

end

@testset "dynamic shmem consisting of multiple arrays" begin

# common use case 1: dynamic shmem consists of multiple homogeneous arrays
#                    -> split using `view`
@testset "homogeneous" begin
    function kernel(a, b, n)
        t = threadIdx().x
        tr = n-t+1

        s = @cuDynamicSharedMem(eltype(a), 2*n)

        sa = view(s, 1:n)
        sa[t] = a[t]
        sync_threads()
        a[t] = sa[tr]

        sb = view(s, n+1:2*n)
        sb[t] = b[t]
        sync_threads()
        b[t] = sb[tr]

        return
    end

    a = rand(Float32, n)
    d_a = CuArray(a)

    b = rand(Float32, n)
    d_b = CuArray(b)

    @cuda threads=n shmem=2*n*sizeof(Float32) kernel(d_a, d_b, n)
    @test reverse(a) == Array(d_a)
    @test reverse(b) == Array(d_b)
end

# common use case 2: dynamic shmem consists of multiple heterogeneous arrays
#                    -> construct using pointer offset
@testset "heterogeneous" begin
    function kernel(a, b, n)
        t = threadIdx().x
        tr = n-t+1

        sa = @cuDynamicSharedMem(eltype(a), n)
        sa[t] = a[t]
        sync_threads()
        a[t] = sa[tr]

        sb = @cuDynamicSharedMem(eltype(b), n, n*sizeof(eltype(a)))
        sb[t] = b[t]
        sync_threads()
        b[t] = sb[tr]

        return
    end

    a = rand(Float32, n)
    d_a = CuArray(a)

    b = rand(Int64, n)
    d_b = CuArray(b)

    @cuda threads=n shmem=(n*sizeof(Float32) + n*sizeof(Int64)) kernel(d_a, d_b, n)
    @test reverse(a) == Array(d_a)
    @test reverse(b) == Array(d_b)
end

end

end

############################################################################################

@testset "data movement and conversion" begin

if capability(device()) >= v"3.0"

@testset "shuffle idx" begin
    function kernel(d)
        i = threadIdx().x
        j = 32 - i + 1

        d[i] = shfl_sync(FULL_MASK, d[i], j)

        return
    end

    warpsize = CUDA.warpsize(device())

    @testset for T in [UInt8, UInt16, UInt32, UInt64, UInt128,
                       Int8, Int16, Int32, Int64, Int128,
                       Float32, Float64, ComplexF32, ComplexF64, Bool]
        a = rand(T, warpsize)
        d_a = CuArray(a)
        @cuda threads=warpsize kernel(d_a)
        @test Array(d_a) == reverse(a)
    end
end

@testset "shuffle down" begin
    n = 14

    function kernel(d::CuDeviceArray, n)
        t = threadIdx().x
        if t <= n
            d[t] += shfl_down_sync(FULL_MASK, d[t], n÷2, 32)
        end
        return
    end

    @testset for T in [Int32, Float32]
        a = T[T(i) for i in 1:n]
        d_a = CuArray(a)

        threads = nextwarp(device(), n)
        @cuda threads=threads kernel(d_a, n)

        a[1:n÷2] += a[n÷2+1:end]
        @test a == Array(d_a)
    end
end

end

end

############################################################################################

@testset "clock and nanosleep" begin
@on_device clock(UInt32)
@on_device clock(UInt64)

if CUDA.release() >= v"10.0" && v"6.2" in CUDA.ptx_support()
    @on_device nanosleep(UInt32(16))
end
end

@testset "parallel synchronization and communication" begin

@on_device sync_threads()
@on_device sync_threads_count(Int32(1))
@on_device sync_threads_count(true)
@on_device sync_threads_and(Int32(1))
@on_device sync_threads_and(true)
@on_device sync_threads_or(Int32(1))
@on_device sync_threads_or(true)

@testset "llvm ir barrier int" begin
    function kernel_barrier_count(an_array_of_1)
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        if sync_threads_count(an_array_of_1[i]) == 3
            an_array_of_1[i] += Int32(1)
        end
        return nothing
    end

    b_in = Int32[1, 1, 1, 0, 0]  # 3 true
    d_b = CuArray(b_in)
    @cuda threads=5 kernel_barrier_count(d_b)
    b_out = Array(d_b)

    @test b_out == b_in .+ 1

    function kernel_barrier_and(an_array_of_1)
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        if sync_threads_and(an_array_of_1[i]) > 0
            an_array_of_1[i] += Int32(1)
        end
        return nothing
    end

    a_in = Int32[1, 1, 1, 1, 1]  # all true
    d_a = CuArray(a_in)
    @cuda threads=5 kernel_barrier_and(d_a)
    a_out = Array(d_a)

    @test a_out == a_in .+ 1

    function kernel_barrier_or(an_array_of_1)
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        if sync_threads_or(an_array_of_1[i]) > 0
            an_array_of_1[i] += Int32(1)
        end
        return nothing
    end

    c_in = Int32[1, 0, 0, 0, 0]  # 1 true
    d_c = CuArray(c_in)
    @cuda threads=5 kernel_barrier_or(d_c)
    c_out = Array(d_c)

    @test c_out == c_in .+ 1
end

@testset "llvm ir barrier bool" begin
    function kernel_barrier_count(an_array_of_1)
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        if sync_threads_count(an_array_of_1[i] > 0) == 3
            an_array_of_1[i] += Int32(1)
        end
        return nothing
    end

    b_in = Int32[1, 1, 1, 0, 0]  # 3 true
    d_b = CuArray(b_in)
    @cuda threads=5 kernel_barrier_count(d_b)
    b_out = Array(d_b)

    @test b_out == b_in .+ 1

    function kernel_barrier_and(an_array_of_1)
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        if sync_threads_and(an_array_of_1[i] > 0)
            an_array_of_1[i] += Int32(1)
        end
        return nothing
    end

    a_in = Int32[1, 1, 1, 1, 1]  # all true
    d_a = CuArray(a_in)
    @cuda threads=5 kernel_barrier_and(d_a)
    a_out = Array(d_a)

    @test a_out == a_in .+ 1

    function kernel_barrier_or(an_array_of_1)
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        if sync_threads_or(an_array_of_1[i] > 0)
            an_array_of_1[i] += Int32(1)
        end
        return nothing
    end

    c_in = Int32[1, 0, 0, 0, 0]  # 1 true
    d_c = CuArray(c_in)
    @cuda threads=5 kernel_barrier_or(d_c)
    c_out = Array(d_c)

    @test c_out == c_in .+ 1
end

@on_device sync_warp()
@on_device sync_warp(0xffffffff)
@on_device threadfence_block()
@on_device threadfence()
@on_device threadfence_system()

@testset "voting" begin

@testset "any" begin
    d_a = CuArray([false])

    function kernel(a, i)
        vote = vote_any_sync(FULL_MASK, threadIdx().x >= i)
        if threadIdx().x == 1
            a[1] = vote
        end
        return
    end

    @cuda threads=2 kernel(d_a, 1)
    @test Array(d_a)[]

    @cuda threads=2 kernel(d_a, 2)
    @test Array(d_a)[]

    @cuda threads=2 kernel(d_a, 3)
    @test !Array(d_a)[]
end

@testset "all" begin
    d_a = CuArray([false])

    function kernel(a, i)
        vote = vote_all_sync(FULL_MASK, threadIdx().x >= i)
        if threadIdx().x == 1
            a[1] = vote
        end
        return
    end

    @cuda threads=2 kernel(d_a, 1)
    @test Array(d_a)[]

    @cuda threads=2 kernel(d_a, 2)
    @test !Array(d_a)[]

    @cuda threads=2 kernel(d_a, 3)
    @test !Array(d_a)[]
end

@testset "uni" begin
    d_a = CuArray([false])

    function kernel1(a, i)
        vote = vote_uni_sync(FULL_MASK, threadIdx().x >= i)
        if threadIdx().x == 1
            a[1] = vote
        end
        return
    end

    @cuda threads=2 kernel1(d_a, 1)
    @test Array(d_a)[]

    @cuda threads=2 kernel1(d_a, 2)
    @test !Array(d_a)[]

    function kernel2(a, i)
        vote = vote_uni_sync(FULL_MASK, blockDim().x >= i)
        if threadIdx().x == 1
            a[1] = vote
        end
        return
    end

    @cuda threads=2 kernel2(d_a, 3)
    @test Array(d_a)[]
end

@testset "ballot" begin
    d_a = CuArray(UInt32[0])

    function kernel(a, i)
        vote = vote_ballot_sync(FULL_MASK, threadIdx().x == i)
        if threadIdx().x == 1
            a[1] = vote
        end
        return
    end

    len = 4
    for i in 1:len
        @cuda threads=len kernel(d_a, i)
        @test Array(d_a) == [2^(i-1)]
    end
end

end

end

############################################################################################

@testset "libcudadevrt" begin
    kernel() = (CUDA.device_synchronize(); nothing)
    @cuda kernel()
end

############################################################################################

@testset "atomics (low-level)" begin

@testset "atomic_add" begin
    types = [Int32, Int64, UInt32, UInt64, Float32]
    capability(device()) >= v"6.0" && push!(types, Float64)

    @testset for T in types
        a = CuArray([zero(T)])

        function kernel(a, b)
            CUDA.atomic_add!(pointer(a), b)
            return
        end

        @cuda threads=1024 kernel(a, one(T))
        @test Array(a)[1] == T(1024)
    end
end

@testset "atomic_sub" begin
    types = [Int32, Int64, UInt32, UInt64]
    capability(device()) >= v"6.0" && append!(types, [Float32, Float64])

    @testset for T in types
        a = CuArray([T(2048)])

        function kernel(a, b)
            CUDA.atomic_sub!(pointer(a), b)
            return
        end

        @cuda threads=1024 kernel(a, one(T))
        @test Array(a)[1] == T(1024)
    end
end

@testset "atomic_inc" begin
    @testset for T in [Int32]
        a = CuArray([zero(T)])

        function kernel(a, b)
            CUDA.atomic_inc!(pointer(a), b)
            return
        end

        @cuda threads=768 kernel(a, T(512))
        @test Array(a)[1] == T(255)
    end
end

@testset "atomic_dec" begin
    @testset for T in [Int32]
        a = CuArray([T(1024)])

        function kernel(a, b)
            CUDA.atomic_dec!(pointer(a), b)
            return
        end

        @cuda threads=256 kernel(a, T(512))
        @test Array(a)[1] == T(257)
    end
end

@testset "atomic_xchg" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([zero(T)])

        function kernel(a, b)
            CUDA.atomic_xchg!(pointer(a), b)
            return
        end

        @cuda threads=1024 kernel(a, one(T))
        @test Array(a)[1] == one(T)
    end
end

@testset "atomic_and" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([T(1023)])

        function kernel(a, T)
            i = threadIdx().x - 1
            k = 1
            for i = 1:i
                k *= 2
            end
            b = 1023 - k  # 1023 - 2^i
            CUDA.atomic_and!(pointer(a), T(b))
            return
        end

        @cuda threads=10 kernel(a, T)
        @test Array(a)[1] == zero(T)
    end
end

@testset "atomic_or" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([zero(T)])

        function kernel(a, T)
            i = threadIdx().x
            b = 1  # 2^(i-1)
            for i = 1:i
                b *= 2
            end
            b /= 2
            CUDA.atomic_or!(pointer(a), T(b))
            return
        end

        @cuda threads=10 kernel(a, T)
        @test Array(a)[1] == T(1023)
    end
end

@testset "atomic_xor" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([T(1023)])

        function kernel(a, T)
            i = threadIdx().x
            b = 1  # 2^(i-1)
            for i = 1:i
                b *= 2
            end
            b /= 2
            CUDA.atomic_xor!(pointer(a), T(b))
            return
        end

        @cuda threads=10 kernel(a, T)
        @test Array(a)[1] == zero(T)
    end
end

if capability(device()) >= v"6.0"

@testset "atomic_cas" begin
    @testset for T in [Int32, Int64, Float32, Float64]
        a = CuArray([zero(T)])

        function kernel(a, b, c)
            CUDA.atomic_cas!(pointer(a), b, c)
            return
        end

        @cuda threads=1024 kernel(a, zero(T), one(T))
        @test Array(a)[1] == one(T)
    end
end

end

@testset "atomic_max" begin
    types = [Int32, Int64, UInt32, UInt64]
    capability(device()) >= v"6.0" && append!(types, [Float32, Float64])

    @testset for T in types
        a = CuArray([zero(T)])

        function kernel(a, T)
            i = threadIdx().x
            CUDA.atomic_max!(pointer(a), T(i))
            return
        end

        @cuda threads=1024 kernel(a, T)
        @test Array(a)[1] == T(1024)
    end
end

@testset "atomic_min" begin
    types = [Int32, Int64, UInt32, UInt64]
    capability(device()) >= v"6.0" && append!(types, [Float32, Float64])

    @testset for T in types
        a = CuArray([T(1024)])

        function kernel(a, T)
            i = threadIdx().x
            CUDA.atomic_min!(pointer(a), T(i))
            return
        end

        @cuda threads=1024 kernel(a, T)
        @test Array(a)[1] == one(T)
    end
end

if capability(device()) >= v"6.0"

@testset "atomic_mul" begin
    @testset for T in [Float32, Float64]
        a = CuArray([one(T)])

        function kernel(a, b)
            CUDA.atomic_mul!(pointer(a), b)
            return
        end

        @cuda threads=10 kernel(a, T(2))
        @test Array(a)[1] == T(1024)
    end
end

@testset "atomic_div" begin
    @testset for T in [Float32, Float64]
        a = CuArray([T(1024)])

        function kernel(a, b)
            CUDA.atomic_div!(pointer(a), b)
            return
        end

        @cuda threads=10 kernel(a, T(2))
        @test Array(a)[1] == one(T)
    end
end

@testset "shared memory" begin
    function kernel()
        shared = @cuStaticSharedMem(Float32, 1)
        @atomic shared[threadIdx().x] += 0f0
        return
    end

    CUDA.@sync @cuda kernel()
end

end

end

@testset "atomics (high-level)" begin

@testset "add" begin
    types = [Int32, Int64, UInt32, UInt64, Float32]
    capability(device()) >= v"6.0" && push!(types, Float64)

    @testset for T in types
        a = CuArray([zero(T)])

        function kernel(T, a)
            @atomic a[1] = a[1] + T(1)
            @atomic a[1] += T(1)
            return
        end

        @cuda threads=1024 kernel(T, a)
        @test Array(a)[1] == T(2048)
    end
end

@testset "sub" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([T(4096)])

        function kernel(T, a)
            @atomic a[1] = a[1] - T(1)
            @atomic a[1] -= T(1)
            return
        end

        @cuda threads=1024 kernel(T, a)
        @test Array(a)[1] == T(2048)
    end
end

@testset "and" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([~zero(T), ~zero(T)])

        function kernel(T, a)
            i = threadIdx().x
            mask = ~(T(1) << (i-1))
            @atomic a[1] = a[1] & mask
            @atomic a[2] &= mask
            return
        end

        @cuda threads=8*sizeof(T) kernel(T, a)
        @test Array(a)[1] == zero(T)
        @test Array(a)[2] == zero(T)
    end
end

@testset "or" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([zero(T), zero(T)])

        function kernel(T, a)
            i = threadIdx().x
            mask = T(1) << (i-1)
            @atomic a[1] = a[1] | mask
            @atomic a[2] |= mask
            return
        end

        @cuda threads=8*sizeof(T) kernel(T, a)
        @test Array(a)[1] == ~zero(T)
        @test Array(a)[2] == ~zero(T)
    end
end

@testset "xor" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([zero(T), zero(T)])

        function kernel(T, a)
            i = threadIdx().x
            mask = T(1) << ((i-1)%(8*sizeof(T)))
            @atomic a[1] = a[1] ⊻ mask
            @atomic a[2] ⊻= mask
            return
        end

        nb = 4
        @cuda threads=(8*sizeof(T)+nb) kernel(T, a)
        @test Array(a)[1] == ~zero(T) & ~((one(T) << nb) - one(T))
        @test Array(a)[2] == ~zero(T) & ~((one(T) << nb) - one(T))
    end
end

@testset "max" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([zero(T)])

        function kernel(T, a)
            i = threadIdx().x
            @atomic a[1] = max(a[1], T(i))
            return
        end

        @cuda threads=32 kernel(T, a)
        @test Array(a)[1] == 32
    end
end

@testset "min" begin
    @testset for T in [Int32, Int64, UInt32, UInt64]
        a = CuArray([typemax(T)])

        function kernel(T, a)
            i = threadIdx().x
            @atomic a[1] = min(a[1], T(i))
            return
        end

        @cuda threads=32 kernel(T, a)
        @test Array(a)[1] == 1
    end
end

@testset "macro" begin
    using CUDA: AtomicError

    @test_throws_macro AtomicError("right-hand side of an @atomic assignment should be a call") @macroexpand begin
        @atomic a[1] = 1
    end
    @test_throws_macro AtomicError("right-hand side of an @atomic assignment should be a call") @macroexpand begin
        @atomic a[1] = b ? 1 : 2
    end

    @test_throws_macro AtomicError("right-hand side of a non-inplace @atomic assignment should reference the left-hand side") @macroexpand begin
        @atomic a[1] = a[2] + 1
    end

    @test_throws_macro AtomicError("unknown @atomic expression") @macroexpand begin
        @atomic wat(a[1])
    end

    @test_throws_macro AtomicError("@atomic should be applied to an array reference expression") @macroexpand begin
        @atomic a = a + 1
    end
end

@testset "shared memory" begin
    # test that atomic operations on shared memory work
    # https://github.com/JuliaGPU/CUDA.jl/issues/311

    function kernel(a)
        b = CUDA.@cuStaticSharedMem(Int, 1)

        if threadIdx().x == 1
            b[] = a[]
        end
        sync_threads()

        CUDA.atomic_add!(pointer(b), 1)
        sync_threads()

        if threadIdx().x == 1
            a[] = b[]
        end
        return
    end

    a = CuArray([0])
    @cuda threads=16 kernel(a)
    @test Array(a) == [16]
end

@testset "shared memory bug" begin
    # shared memory atomics resulted in illegal memory accesses
    # https://github.com/JuliaGPU/CUDA.jl/issues/558

    function kernel()
        tid = threadIdx().x
        shared = @cuStaticSharedMem(Float32, 4)
        CUDA.atomic_add!(pointer(shared, tid), shared[tid + 2])
        sync_threads()
        CUDA.atomic_add!(pointer(shared, tid), shared[tid + 2])
        return
    end

    @cuda threads=2 kernel()
    synchronize()
end

end

############################################################################################

@testset "random numbers" begin

n = 256

@testset "basic" begin
    function kernel(A::CuDeviceArray{T}, B::CuDeviceArray{T}) where {T}
        tid = threadIdx().x
        A[tid] = rand(T)
        B[tid] = rand(T)
        return nothing
    end

    @testset for T in (Int32, UInt32, Int64, UInt64, Int128, UInt128,
                       Float32, Float64)
        a = CUDA.zeros(T, n)
        b = CUDA.zeros(T, n)

        @cuda threads=n kernel(a, b)

        @test all(Array(a) .!= Array(b))
    end
end

@testset "custom seed" begin
    function kernel(A::CuDeviceArray{T}) where {T}
        tid = threadIdx().x
        Random.seed!(1234)
        A[tid] = rand(T)
        return nothing
    end

    @testset for T in (Int32, UInt32, Int64, UInt64, Int128, UInt128,
                       Float32, Float64)
        a = CUDA.zeros(T, n)
        b = CUDA.zeros(T, n)

        @cuda threads=n kernel(a)
        @cuda threads=n kernel(b)

        @test Array(a) == Array(b)
    end
end

end


text:
export generate_spn

"""
    generate_spn(X::Matrix, algo::Symbol; ...)

Generate an SPN structure using a structure learning algorithm.

Arguments:
* `X`: Data matrix.
* `algo`: Algorithm, one out of [:learnspn, :random].
"""
function generate_spn(X::Matrix, algo::Symbol; params...)
    if algo == :learnspn
        return learnspn(X; params...)
    elseif algo == :random
        return randomspn(X; params...)
    else
        @error("Unknown structure learning algorithm: ", algo)
    end
end

"""
    learnspn(X; distribution=Normal(), minclustersize=100)

Return Sum Product Network learned by a simplified LearnSPN algorithm.
"""
function learnspn(X; distributions::Vector = map(d -> Normal, 1:size(X,2)), minclustersize=100)
    q = Queue{Tuple}()
    root = FiniteSumNode()
    instances = collect(1:size(X)[1])
    variables = collect(1:size(X)[2])
    enqueue!(q, (root, variables, instances))

    while length(q) > 0
        node, variables, instances = dequeue!(q)

        # stopping condition, one variable left, estimate distribution
        if length(variables) == 1
            v = variables[1]
            slice = X[instances, v]
            add!(node, UnivariateNode(fit(distributions[v], slice), v))
            continue
        end

        # stopping condition: too small cluster, factorize variables
        if length(instances) <= minclustersize
            # root doesn't have enough instances for clustering
            if typeof(node) <: SumNode
                prod = FiniteProductNode()
                add!(node, prod, log(1.0))
                node = prod
            end
            for v in variables
                slice = X[instances, v]
                add!(node, UnivariateNode(fit(distributions[v], slice), v))
            end
            continue
        end

        # divide and conquer
        if isa(node, SumNode)
            clusterweights = cluster_instances(X, variables, instances)
            for (cluster, weight) in clusterweights
                prod = FiniteProductNode()
                add!(node, prod, log(weight))
                enqueue!(q, (prod, variables, cluster))
            end
        else  # isa(node, ProductNode)
            splits = split_variables(X, variables, instances)
            for split in splits
                if length(split) == 1
                    enqueue!(q, (node, split, instances))
                    continue
                end
                sum = FiniteSumNode()
                add!(node, sum)
                enqueue!(q, (sum, split, instances))
            end
        end
    end

    return SumProductNetwork(root)
end

"""
    split_variables(X, variables, instances)

Split variables into two groups by a G-test based method.
"""
function split_variables(X, variables, instances)
    function binarize(x)
        binary_x = zeros(Int, size(x))
        binary_x[x .> mean(x)] .= 1
        return binary_x
    end
    @assert length(variables) > 1
    slice = X[instances, variables]
    distances = zeros(length(variables))
    p = sum(binarize(slice[:, rand(1:length(variables))]))/length(instances)
    for i in 1:length(variables)
        q = sum(binarize(slice[:, i]))/length(instances)
        e = (p + q)/2
        d = evaluate(KLDivergence(), [p, (1 - p), q, (1 - q)], [e, (1 - e), e, (1 - e)])
        distances[i] = d
    end
    dependentindex = partialsortperm(distances, 1:floor(Integer, length(variables)/2))
    splitone = variables[dependentindex]
    splittwo = setdiff(variables, splitone)

    return (splitone, splittwo)
end

"""
    cluster_instances(X, variables, instances)

Cluster instances into two groups by k-means clustering.
"""
function cluster_instances(X, variables, instances)
    slice = X[instances, variables]
    results = kmeans(transpose(slice), 2)
    clusterone = instances[results.assignments .== 1]
    clustertwo = setdiff(instances, clusterone)
    weight = length(clusterone)/length(instances)

    if length(clustertwo) == 0
        return ((clusterone, weight),)
    end
    return ((clusterone, weight), (clustertwo, 1 - weight))
end

randomspn(X;params...) = @error("Random structure learning is currently not supported.")


text:
using Surrogates
using Distributions
#1D
lb = 0.0
ub = 5.0
n = 5
d = 1
Surrogates.sample(n,lb,ub,GridSample(0.1))
Surrogates.sample(n,lb,ub,UniformSample())
Surrogates.sample(n,lb,ub,SobolSample())
Surrogates.sample(n,lb,ub,LatinHypercubeSample())
Surrogates.sample(20,lb,ub,LowDiscrepancySample(10))
Surrogates.sample(5,d,Cauchy())
Surrogates.sample(5,d,Normal(0,4))

#ND
lb = [0.1,-0.5]
ub = [1.0,20.0]
n = 5
d = 2
s = Surrogates.sample(n,lb,ub,GridSample([0.1,0.5]))
Surrogates.sample(n,lb,ub,UniformSample())
Surrogates.sample(n,lb,ub,SobolSample())
Surrogates.sample(n,lb,ub,LatinHypercubeSample())
Surrogates.sample(n,lb,ub,LowDiscrepancySample([10,3]))
Surrogates.sample(n,d,Cauchy())
Surrogates.sample(n,d,Normal(3,5))


text:
include("../Strukture/studenti.jl")

function mergeSortStudent!(A)
    return mergeSortStudentStep!(A,1,length(A))
end

function mergeSortStudentStep!(A,p,r)
    if p < r
        q = Int(floor((p+r)/2));
        mergeSortStudentStep!(A, p, q);
        mergeSortStudentStep!(A, q+1, r);
        mergeStudentRez!(A, p, q, r);
    end
    return A
end

function mergeStudentRez!(A, p, q, r)
    L = copy(A[p:q])
    R = copy(A[q+1:r])
    push!(L, Student("-","-",typemax(Int64)))
    push!(R, Student("-","-",typemax(Int64)))
    i = 1;
    j = 1;
    for k = p:r
        if uporediStudente(L[i],R[j])
            A[k] = L[i];
            i = i + 1;
        else
            A[k] = R[j];
            j = j + 1;
        end
    end
end

function  uporediStudente(x,y)
    return x.brojIndeksa < y.brojIndeksa
end

ispisStudenata(mergeSortStudent!(studenti))


text:
# ---
# title: 260. Single Number III
# id: problem260
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Bit Manipulation
# link: <https://leetcode.com/problems/single-number-iii/description/>
# hidden: true
# ---
#
# Given an integer array `nums`, in which exactly two elements appear only once
# and all the other elements appear exactly twice. Find the two elements that
# appear only once. You can return the answer in **any order**.
#
# **Follow up:  **Your algorithm should run in linear runtime complexity. Could
# you implement it using only constant space complexity?
#
#
#
# **Example 1:**
#
#
#
#     Input: nums = [1,2,1,3,2,5]
#     Output: [3,5]
#     Explanation: [5, 3] is also a valid answer.
#
#
# **Example 2:**
#
#
#
#     Input: nums = [-1,0]
#     Output: [-1,0]
#
#
# **Example 3:**
#
#
#
#     Input: nums = [0,1]
#     Output: [1,0]
#
#
#
#
# **Constraints:**
#
#   * `1 <= nums.length <= 30000`
#   *  Each integer in `nums` will appear twice, only two integers will appear once.
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
using Pkg
Pkg.add(["Pluto", "PlutoUI", "PackageCompiler"]) #"Plots", "Images", "ImageIO", "ImageMagick",

using PackageCompiler
create_sysimage([:Pluto, :PlutoUI]; precompile_execution_file="warmup.jl", replace_default=true, cpu_target = PackageCompiler.default_app_cpu_target())


text:
########################################
## File Name: cost_test.jl
## Author: Haruki Nishimura (hnishimura@stanford.edu)
## Date Created: 2020/05/14
## Description: Test code for src/cost_models.jl
########################################

using LinearAlgebra
using Distributions
using ForwardDiff

@testset "Cost Test" begin

# CostPosRangeLocalization
cost_prl = CostPosRangeLocalization();
p_robot = PhysPos(0.,[5.,7.]);
bPos = BelMvNormal(0.,zeros(2),100*Matrix(1.0I, 2, 2));
bVecPos = [bPos for ii = 1:100];
sV = AugState(p_robot,bVecPos);
uPos = PosControl(0.,[2.,3.2]);
Cu = Matrix(1.0I, 2, 2);

ic = instCost(cost_prl, sV, uPos, Cu)
@test isapprox(ic, 0.5*(2.0^2 + 3.2^2))

ic_grad_p = instCost_grad_p(cost_prl, sV)
@test ic_grad_p == zeros(2)

ic_grad_b = instCost_grad_b(cost_prl, sV)
@test all([g == zeros(6) for g in ic_grad_b])

tc = termCost(cost_prl, sV)
@test isapprox(tc, 100*exp(entropy(MvNormal(bPos))))

tc_grad_p = termCost_grad_p(cost_prl, sV)
@test tc_grad_p == zeros(2)

tc_grad_b = termCost_grad_b(cost_prl, sV)
function test_termCost(b::Vector{<:Real})
    μ,Σ = b[1:2], reshape(b[3:6], 2, 2)
    d = MvNormal(μ, Σ)
    return exp(entropy(d))
end
test_termCost_grad_b(b::Vector{Float64}) = ForwardDiff.gradient(test_termCost, b)
@test all([all(isapprox.(b, test_termCost_grad_b([0., 0., 100., 0., 0., 100.]))) for b in tc_grad_b])

# CostManipulate2D
cost_m = CostManipulate2D()
xMP = PhysManipulate2D(0.,[0.1,0.2],0.5,[0.3,0.4],0.6,3.,5.,[10.,11.],0.7);
uMP = MControl2D(0.,6.,7.,8.);
bMP = BelMvNormal(xMP.t,vec(xMP),10*Matrix(1.0I, 11, 11));
CsMP = Matrix(1.0I, 11, 11);
CuMP = Matrix(1.0I, 3, 3);

icMP = instCost(cost_m, bMP, uMP, CsMP, CuMP)
μ_target = [0.,0.,pi,0.,0.,0.,0.,0.,0.,0.,0.];
@test isapprox(icMP, 0.5*tr(CsMP*10*Matrix(1.0I, 11, 11)) + 0.5*(vec(xMP) - μ_target)'*CsMP*(vec(xMP) - μ_target) + 0.5*vec(uMP)'*CuMP*vec(uMP))

ic_grad_mp = instCost_grad(cost_m, bMP, CsMP)
function test_instCostMP(b::Vector{<:Real})
    bel = BelMvNormal(0.0, b)
    return instCost(cost_m, bel, uMP, CsMP, CuMP)
end
test_instCostMP_grad(b::Vector{Float64}) = ForwardDiff.gradient(test_instCostMP, b)
@test all(isapprox.(ic_grad_mp, test_instCostMP_grad(bMP.params)))

tcMP = termCost(cost_m, bMP, CsMP)
@test isapprox(tcMP, icMP - 0.5*vec(uMP)'*CuMP*vec(uMP))

tc_grad_mp = termCost_grad(cost_m, bMP, CsMP)
@test all(isapprox.(tc_grad_mp, ic_grad_mp))

end