text:
include("global_panel.jl")
include("simulation_panel.jl")

function draw_main_panel(gui_data::GuiData, app_data::Model.AppData, sock::Comm.SocClient)
    CImGui.SetNextWindowPos((0, 0), CImGui.ImGuiCond_Once)

    # we use a Begin/End pair to create a named window.
    CImGui.Begin("Main panel")  # create a window panel and append into it.
    # CImGui.Text("This is some useful text.")  # display some text
    # @c CImGui.Checkbox("Demo Window", &app.show_demo_window)  # edit bools storing our window open/close state
    # @c CImGui.Checkbox("Another Window", &app.show_another_window)

    # @c CImGui.SliderFloat("float", &app.float_slide, 0, 1)  # edit 1 float using a slider from 0 to 1
    # CImGui.ColorEdit3("clear color", app.clear_color)  # edit 3 floats representing a color
    # CImGui.Separator()

    # CImGui.Text(@sprintf("Simulation '%s'", Model.simulation(app.model)))
    CImGui.Text(@sprintf("Status: %.2f ms/frame (%.1f FPS)", 1000 / CImGui.GetIO().Framerate, CImGui.GetIO().Framerate))
    CImGui.Separator()

    # Button bar ************************************************
    if CImGui.Button("Load Sim")
        # load simulation data1
        Model.load_sim!(app_data.model)

        # Try to load any samples based on model properties.
        # The samples are split into "span"s. They are either in RamDisk or disc.
        Model.load_samples(app_data.samples, app_data.model)
    end
    CImGui.SameLine()

    if CImGui.Button("Save Sim")
        Model.save_sim(app_data.model)
    end
    CImGui.SameLine()

    if CImGui.Button("Save App")
        Model.save_data(app_data)
    end
    CImGui.SameLine()

    if CImGui.Button("Simulate")
        # Check that the app data is correct, for example, RangeEnd should <=
        # to Duration.
        range_end = Model.range_end(app_data.model)
        duration = Model.duration(app_data.model)

        if range_end > duration
            # Issue dialog box
            gui_data.show_warning_dialog = true
        else
            # Get protocol
            data = app_data.basic_protocol

            # Populate
            data["From"] = "Client"
            data["To"] = "Server"
            data["Type"] = "Cmd"
            data["Data"] = "Simulate"
            data["Data1"] = Model.simulation(app_data.model)

            if Model.is_changed(app_data.model)
                println("Model has changed")
                # Save changes
                if Model.is_app_changed(app_data.model)
                    println("App Model has changed")
                    Model.save_data(app_data)
                end
                if Model.is_sim_changed(app_data.model)
                    println("Sim Model has changed")
                    Model.save_sim(app_data.model)
                end

                if app_data.configured
                    # Reset samples for new incoming data
                    Model.reset_samples!(app_data.samples)
                else
                    Model.config!(app_data)
                end
            end

            Comm.send(sock, data)
        end
    end
    CImGui.SameLine()

    if CImGui.Button("Re-Simulate")
        # Check that the app data is correct, for example, RangeEnd should <=
        # to Duration.
        range_end = Model.range_end(app_data.model)
        duration = Model.duration(app_data.model)

        if range_end > duration
            # Issue dialog box
            gui_data.show_warning_dialog = true
        else
            # Get protocol
            data = app_data.basic_protocol

            # Populate
            data["From"] = "Client"
            data["To"] = "Server"
            data["Type"] = "Cmd"
            data["Data"] = "Re-Simulate"
            data["Data1"] = Model.simulation(app_data.model)

            if Model.is_changed(app_data.model)
                # Save changes
                if Model.is_app_changed(app_data.model)
                    Model.save_data(app_data)
                end
                Model.load_sim!(app_data.model)
                Model.config!(app_data)
            end

            Comm.send(sock, data)
        end
    end

    if gui_data.show_warning_dialog
        CImGui.OpenPopup("Warning!")
        if CImGui.BeginPopupModal("Warning!", C_NULL, CImGui.ImGuiWindowFlags_AlwaysAutoResize)
            CImGui.Text("RangeEnd > Duration. RangeEnd on Graph properties must be <= Duration.")
            CImGui.Separator()
            if CImGui.Button("OK", (100, 0))
                gui_data.show_warning_dialog = false
                CImGui.CloseCurrentPopup()
            end
            CImGui.SetItemDefaultFocus()
            CImGui.EndPopup()
        end
    end

    CImGui.SameLine()

    if CImGui.Button("Stop")
        # Get protocol
        data = app_data.basic_protocol

        # Populate
        data["From"] = "Client"
        data["To"] = "Server"
        data["Type"] = "Cmd"
        data["Data"] = "Stop"

        Comm.send(sock, data)
    end
    CImGui.SameLine()

    if CImGui.Button("Shutdown Server")
        # Get protocol
        data = app_data.basic_protocol

        # Populate
        data["From"] = "Client"
        data["To"] = "Server"
        data["Type"] = "Cmd"
        data["Data"] = "Shutdown Server"

        Comm.send(sock, data)
    end

    # Global panel ************************************************
    draw_global_panel(gui_data, app_data, sock)

    # Neuron panel ************************************************
    draw_simulation_panel(gui_data, app_data, sock)

    CImGui.End()
end


text:
############################################################################################
# !NOTE: TBD
# !NOTE: Most functions in ParticleFilter are not needed for a simple Kalmanfilter, so may just use its own directory for now.
############################################################################################
# Import sub-folder
# include("Core/Core.jl")

############################################################################################
# Export

ext: jl


text:
include("types.jl")

function movePiece(gameType::String, board::Array{Array{piece,1},1}, move_number::Int64, sourceX, sourceY, targetX, targetY, option, targetX2, targetY2, targetX3, targetY3)
    global capturedByOdd
    global capturedByEven

    sourceX = Int64(get(sourceX))
    sourceY = Int64(get(sourceY))
    targetX = Int64(get(targetX))
    targetY = Int64(get(targetY))

    if board[targetY][targetX] != empty # there is currently a piece in the target location
        board[targetY][targetX].side = move_number%2
        if move_number%2 == 0 # even side
            push!(capturedByEven, board[targetY][targetX])
        else # odd side
            push!(capturedByOdd, board[targetY][targetX])
        end
    end
    board[targetY][targetX] = board[sourceY][sourceX] # move piece at source to target, removing piece in process
    board[targetY][targetX].x = targetX # setting piece x
    board[targetY][targetX].y = targetY # setting piece y
    board[sourceY][sourceX] = empty #set source space to empty

    if !isnull(targetX2) && !isnull(targetY2)
        targetX2 = Int64(get(targetX2))
        targetY2 = Int64(get(targetY2))

        if targetX2 >= 1 && targetX2 <= length(board[1]) && targetY2 >= 1 && targetY2 <= length(board)
            if board[targetY2][targetX2] != empty # there is currently a piece in the target location
                board[targetY2][targetX2].side = move_number%2
                if move_number%2 == 0 # even side
                    push!(capturedByEven, board[targetY2][targetX2])
                else # odd side
                    push!(capturedByOdd, board[targetY2][targetX2])
                end
            end
            board[targetY2][targetX2] = board[targetY][targetX] # move piece at source to target, removing piece in process
            board[targetY2][targetX2].x = targetX2 # setting piece x
            board[targetY2][targetX2].y = targetY2 # setting piece y
            board[targetY][targetX] = empty #set source space to empty
        end
    end

    if !isnull(targetX3) && !isnull(targetY3)
        targetX3 = Int64(get(targetX3))
        targetY3 = Int64(get(targetY3))

        if targetX3 >= 1 && targetX3 <= length(board[1]) && targetY3 >= 1 && targetY3 <= length(board)
            if board[targetY3][targetX3] != empty # there is currently a piece in the target location
                board[targetY3][targetX3].side = move_number%2
                if move_number%2 == 0 # even side
                    push!(capturedByEven, board[targetY3][targetX3])
                else # odd side
                    push!(capturedByOdd, board[targetY3][targetX3])
                end
            end
            board[targetY3][targetX3] = board[targetY2][targetX2] # move piece at source to target, removing piece in process
            board[targetY3][targetX3].x = targetX3 # setting piece x
            board[targetY3][targetX3].y = targetY3 # setting piece y
            board[targetY2][targetX2] = empty #set source space to empty
        end
    end

    if length(board) == 16
        board = demon_burning(board)
    end

    if !isnull(option)  # promote piece
        if get(option) == "!"
            board[targetY][targetX] = promote(board[targetY][targetX], gameType)
            ##println  (board[targetY][targetX])
        end
    end
end

function dropPiece(board::Array{Array{piece,1},1}, move_number::Int64, option, targetX, targetY)
    option = lowercase(get(option))
    targetX = Int64(get(targetX))
    targetY = Int64(get(targetY))

    # this is unnecessary because a piece can't be dropped where there is already an existing piece,
    # but I'm doing it anyway so in case of an illegal move, the piece isn't lost (it's captured)

    if board[targetY][targetX] != empty # there is currently a piece in the target location
        board[targetY][targetX].side = move_number%2
        if move_number%2 == 0 # even side
            push!(capturedByEven, board[targetY][targetX])
        else # odd side
            push!(capturedByOdd, board[targetY][targetX])
        end
    end

    droppedPiece = piece(option, option, targetX, targetY, move_number%2, false)
    board[targetY][targetX] = droppedPiece
    removeFromDropPool(board, droppedPiece)
end

function removeFromDropPool(board::Array{Array{piece,1},1}, droppedPiece::piece)
    global capturedByEven
    global capturedByOdd

    if droppedPiece.side == 0 # even side
        i = findfirst(capturedByEven, board[droppedPiece.y][droppedPiece.x])
        if i > 0
            deleteat!(capturedByEven, i)
        end
    else # odd side
        i = findfirst(capturedByOdd, board[droppedPiece.y][droppedPiece.x])
        if i > 0
            deleteat!(capturedByOdd, i)
        end
    end
end

# for debugging purposes
function displayBoard(board::Array{Array{piece,1},1})
    boardLength = length(board)
    println("\n")
    print("   ")
    for i = 1:boardLength
        if i < 10
            print("     $i      ")
        else
            print("     $i     ")
        end
    end
    print("\n   ")
    for i = 1:(boardLength*12)
        print("-")
    end
    println("")
    for y = 1:boardLength
        print("  |")
        for x = 1:boardLength
            pieceName = board[y][x].name
            for i=length(pieceName)+1:9 # 9 chars in the longest name
                if i%2 == 0
                    pieceName = pieceName*" "
                else
                    pieceName = " "*pieceName
                end
            end
            if board[y][x].name == "king" && board[y][x].side == 0
                print_with_color(:green, " $pieceName ")
            elseif board[y][x].name == "king" && board[y][x].side == 1
                print_with_color(:yellow, " $pieceName ")
            elseif board[y][x].side == 1
                print_with_color(:blue, " $pieceName ")
            elseif board[y][x].side == 0
                print_with_color(:red, " $pieceName ")
            else
                print(" $pieceName ")
            end
            print("|")
        end
        print(" $y\n   ")
        for i = 1:(boardLength*12)
            print("-")
        end
        println("")
    end
end

# this function returns the best piece to be dropped and where to drop it
function pickPieceDrop(board::Array{Array{piece,1},1}, move_number::Int64, capturedByOdd, capturedByEven)

    ourPieces = []
    enemyPieces = []

    for y = 1:length(board)
        for x = 1:length(board)
            if board[y][x].side == move_number%2
                push!(ourPieces, board[y][x])
            else
                push!(enemyPieces, board[y][x])
            end
        end
    end

    if currentMove %2 == 0 # even player's turn
        dropBank = capturedByEven
    else
        dropBank = capturedByOdd
    end

    rankedPieces = ["demon","great","vice","hawk","rgeneral","eagle","queen","bgeneral","falcon","lion","soaring","csoldier","buffalo","dragon","horse","rook","bishop","vsoldier","ssoldier","vmover","smover","lance","chariot","king","phoenix","kirin","elephant","gold","leopard","tiger","silver","copper","iron","knigh","dog","pawn"]
    best = piece("", "", 0, 0, -1, false)
    for bestPiece in rankedPieces
        for apiece in dropBank
            if apiece.name == bestPiece
                best = apiece
                break
            end
        end
    end

    if best.side == -1
        return best, 0, 0
    end

    safeMoves = []
    for y in length(board)
        for x in length(board[1])
            if board[y][x].side != move_number%2 && board[y][x].side != -1
                for apiece in enemyPieces
                    if !inRange(board, move(move_number, "move", apiece.x, apiece.y, x, y, "", false, -1, -1, -1, -1))
                        push!(safeMoves, (x,y))
                    end
                end
            end
        end
    end
    srand()
    targetX, targetY = safeMoves[rand(1:length(safeMoves))]

    return best, targetX, targetY
end

#checks if sourcePiece can kill targetPiece
function inRange(board::Array{Array{piece,1},1}, amove::move)

    name = board[amove.sourcey][amove.sourcex].name
    side = board[amove.sourcey][amove.sourcex].side
    sourcex = amove.sourcex
    sourcey = amove.sourcey
    targetx = amove.targetx
    targety = amove.targety
    targetx2 = amove.targetx2
    targety2 = amove.targety2
    targetx3 = amove.targetx3
    targety3 = amove.targety3

    #println(name)
    #=println(board[sourcey][sourcex])
    if board[sourcey][sourcex].side == -1
        return false
    end=#
    if name == "cobra" && go_between(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "elephant"
        if side == 1 && elephant_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && elephant_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "pawn"
        #println("something 1")
        if side == 1 && pawn_black(board, sourcex, sourcey, targetx, targety)
            #println("something 2")
            return true
        elseif side == 0 && pawn_white(board, sourcex, sourcey, targetx, targety)
            #println("something 3")
            return true
        end
    elseif name == "gold"
        if side == 1 && gold_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && gold_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "smover" && side_mover(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "boar" && p_side_mover(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "vmover" && vertical_mover(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "ox" && p_vertical_mover(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "bishop" && bishop(board, sourcex, sourcey, targetx, targety)
        #println("something 4")
        return true
    elseif name == "horse" && dragon_horse(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "rook" && rook(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "dragon" && dragon_king(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "falcon"
        if side == 1 && falcon_black(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
            return true
        elseif side == 0 && falcon_white(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
            return true
        end
    elseif name == "soaring"
        if side == 1 && soaring_black(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
            return true
        elseif side == 0 && soaring_white(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
            return true
        end
    elseif name == "lance"
        if side == 1 && lance_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && lance_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "white"
        if side == 1 && p_lance_black(board, sourcex, sourcey, targetx, targety)
                return true
        elseif side == 0 && p_lance_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "chariot" && chariot(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "whale"
        if side == 1 && p_chariot_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && p_chariot_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "tiger"
        if side == 1 && tiger_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && tiger_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "stag" && p_tiger(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "leopard" && leopard(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "copper"
        if side == 1 && copper_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && copper_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "silver"
        if side == 1 && silver_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && silver_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "king" && king(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "kirin" && kirin(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "lion" && lion(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
        return true
    elseif name == "phoenix" && phoenix(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "queen" && queen(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "knight"
        if side == 1 && knight_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && knight_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "prince" && prince(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "vice" && vice(board, sourcex, sourcey, targetx, targety, targetx2, targety2, targetx3, targety3)
        return true
    elseif name == "great" && great(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "bgeneral" && bgeneral(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "rgeneral" && rgeneral(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "demon" && demon(board, sourcex, sourcey, targetx, targety, targetx2, targety2, targetx3, targety3)
        return true
    elseif name == "tetrarch" && tetrarch(board, sourcex, sourcey, targetx, targety, targetx2, targety2, targetx3, targety3)
        return true
    elseif name == "buffalo" && buffalo(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "csoldier" && csoldier(board, sourcex, sourcey, targetx, targety)
        return true
    elseif name == "ssoldier"
        if side == 1 && ssoldier_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && ssoldier_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "vsoldier"
        if side == 1 && vsoldier_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && vsoldier_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "iron"
        if side == 1 && iron_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && iron_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "eagle" && eagle(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
        return true
    elseif name == "hawk" && hawk(board, sourcex, sourcey, targetx, targety, targetx2, targety2)
        return true
    elseif name == "multi"
        if side == 1 && multi_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && multi_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    elseif name == "dog"
        if side == 1 && dog_black(board, sourcex, sourcey, targetx, targety)
            return true
        elseif side == 0 && dog_white(board, sourcex, sourcey, targetx, targety)
            return true
        end
    end
    return false
end

# return sourceX, sourceY, targetX, targetY of winning move
function checkForWin(board::Array{Array{piece,1},1}, ourPieces, enemyKing::piece)
    #check if ourPieces are within king kill range
    for apiece in ourPieces
        if inRange(board, move(-1, "move", apiece.x, apiece.y, enemyKing.x, enemyKing.y, "", false, -1, -1, -1, -1))
            #do this move to win
            return apiece.x, apiece.y, enemyKing.x, enemyKing.y
        end
    end
    return 0,0,0,0
end

# returns true if our king is in check; o/w false
function checkForCheck(board::Array{Array{piece,1},1}, enemyPieces, ourKing::piece)

    for aEnemyPiece in enemyPieces
        if inRange(board, move(-1, "move", aEnemyPiece.x, aEnemyPiece.y, ourKing.x, ourKing.y, "", false, -1, -1, -1, -1))
            return true
        end
    end
    return false
end

# check if a piece can block the check that king is in
# precondition: only 1 piece can currently assassinate our king
# return sourceX, sourceY, targetX, targetY of move that can block check; o/w returns 0,0,0,0
function checkForBlock(board::Array{Array{piece,1},1}, move_number::Int64)

    ourPieces = []
    killerPiece = piece("", "", 0, 0, -1, false) # opponent piece that threatens the life of our majesty
    ourKing = piece("", "", 0, 0, -1, false)

    for y = 1:length(board)
        for x = 1:length(board[1])
            if board[y][x].side == move_number%2
                if board[y][x].name == "king"
                    ourKing = duplicatePiece(board[y][x])
                end
                push!(ourPieces, board[y][x])
            end
        end
    end

    for y = 1:length(board)
        for x = 1:length(board[1])
            if (board[y][x].side != move_number%2) && (board[y][x].side != -1) && inRange(board, move(move_number, "move", board[y][x].x, board[y][x].x, ourKing.x, ourKing.y, "", false, -1, -1, -1, -1))
                killerPiece = board[y][x]
            end
        end
    end

    # loop thru board and make array of moves on killer piece's path
    # identify moves that are on path of king killing

    killerPath = [] # an array of coordinate tuples

    if killerPiece.name == "lance"
        # assert: y coordinates of king and lance must be same since lance can only move vertically
        if ourKing.x > killerPiece.x # king is to the right of the lance
            for i = killPiece.x+1:ourKing.x-1
                push!(killerPath, (i, killerPiece.y))
            end
        else # king is on top, lance can move up
            for i = ourKing.x+1:killerPiece.x-1
                push!(killerPath, (i, killerPiece.y))
            end
        end
    elseif killerPiece.name in ["rook", "dragon"]
        if ourKing.x == killerPiece.x
            if ourKing.y > killerPiece.y # king is on bottom, rook can move down
                for i = killPiece.y+1:ourKing.y-1
                    push!(killerPath, (killerPiece.x, i))
                end
            else # king is on top, rook can move up
                for i = ourKing.y+1:killerPiece.y-1
                    push!(killerPath, (killerPiece.x, i))
                end
            end
        elseif ourKing.y == killerPiece.y
            if ourKing.x > killerPiece.x # king is on left, rook can move left
                for i = killerPiece.x+1:ourKing.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            else # king is on right, rook can move right
                for i = ourKing.x+1:killerPiece.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            end
        end
    elseif killerPiece.name in ["bishop", "horse"]
        sourcex = killerPiece.x
        sourcey = killerPiece.y
        targetx = ourKing.x
        targety = ourKing.y
        if targetx < sourcex && targety < sourcey # target is NE of bishop
            i = targetx
            j = targety
            while i < sourcex-1 && j < sourcey-1
                i += 1
                j += 1
                push!(killerPath, (i, j))
            end
        elseif targetx < sourcex && targety > sourcey # target is SE of bishop
            i = targetx
            j = targety
            while i < sourcex-1 && j > sourcey+1
                i += 1
                j -= 1
                push!(killerPath, (i, j))
            end
        elseif targetx > sourcex && targety < sourcey # target is NW of bishop
            i = targetx
            j = targety
            while i > sourcex+1 && j < sourcey-1
                i -= 1
                j += 1
                push!(killerPath, (i, j))
            end
        elseif targetx > sourcex && targety > sourcey # target is SW of bishop
            i = targetx
            j = targety
            while i > sourcex+1 && j > sourcey+1
                i -= 1
                j -= 1
                push!(killerPath, (i, j))
            end
        end
    elseif killerPiece.name in ["chariot", "vmover", "stag"]
        if ourKing.x > killerPiece.x
            for i = killerPiece.x+1:ourKing.x-1
                push!(killerPath, (i, killerPiece.y))
            end
        else
            for i = ourKing.x+1:killerPiece.x-1
                push!(killerPath, (i, killerPiece.y))
            end
        end
    elseif killerPiece.name == "smover"
        if ourKing.y > killerPiece.y
            for i = killPiece.y+1:ourKing.y-1
                push!(killerPath, (killerPiece.x, i))
            end
        else
            for i = ourKing.y+1:killerPiece.y-1
                push!(killerPath, (killerPiece.x, i))
            end
        end
    elseif killerPiece.name == "whale"
        if ourKing.y == killerPiece.y
            if ourKing.x > killerPiece.x
                for i = killerPiece.x+1:ourKing.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            else
                for i = ourKing.x+1:killerPiece.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if killerPiece.side == 0
                if targetx < sourcex && targety > sourcey
                    i = targetx
                    j = targety
                    while i < sourcex-1 && j > sourcey+1
                        i += 1
                        j -= 1
                        push!(killerPath, (i, j))
                    end
                elseif targetx < sourcex && targety < sourcey # target is NE of bishop
                    i = targetx
                    j = targety
                    while i < sourcex-1 && j < sourcey-1
                        i += 1
                        j += 1
                        push!(killerPath, (i, j))
                    end
                end
            elseif killerPiece.side == 1
                if targetx > sourcex && targety < sourcey # target is NW of bishop
                    i = targetx
                    j = targety
                    while i > sourcex+1 && j < sourcey-1
                        i -= 1
                        j += 1
                        push!(killerPath, (i, j))
                    end
                elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                    i = targetx
                    j = targety
                    while i > sourcex+1 && j > sourcey+1
                        i -= 1
                        j -= 1
                        push!(killerPath, (i, j))
                    end
                end
            end
        end
    elseif killerPiece.name == "falcon"
        if (killerPiece.x == ourKing.x) || (killerPiece.y == ourKing.y)
            if ourKing.x == killerPiece.x
                if ourKing.y > killerPiece.y # king is on bottom, rook can move down
                    for i = killPiece.y+1:ourKing.y-1
                        push!(killerPath, (killerPiece.x, i))
                    end
                else # king is on top, rook can move up
                    for i = ourKing.y+1:killerPiece.y-1
                        push!(killerPath, (killerPiece.x, i))
                    end
                end
            elseif ourKing.y == killerPiece.y
                if killerPiece.side == 0 && (ourKing.x < killerPiece.x)
                    for i = ourKing.x+1:killerPiece.x-1
                        push!(killerPath, (i, ourKing.y))
                    end
                elseif killerPiece.side == 1 (ourKing.x > killerPiece.x)
                    for i = killerPiece.x+1:ourKing.x-1
                        push!(killerPath, (i, ourKing.y))
                    end
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if targetx < sourcex && targety < sourcey # target is NE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j < sourcey-1
                    i += 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx < sourcex && targety > sourcey # target is SE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j > sourcey+1
                    i += 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety < sourcey # target is NW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j < sourcey-1
                    i -= 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j > sourcey+1
                    i -= 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            end
        end
    elseif killerPiece.name == "soaring"
        if killerPiece.x == ourKing.x || killerPiece.y == ourKing.y
            if ourKing.x == killerPiece.x
                if ourKing.y > killerPiece.y # king is on bottom, rook can move down
                    for i = killPiece.y+1:ourKing.y-1
                        push!(killerPath, (killerPiece.x, i))
                    end
                else # king is on top, rook can move up
                    for i = ourKing.y+1:killerPiece.y-1
                        push!(killerPath, (killerPiece.x, i))
                    end
                end
            elseif ourKing.y == killerPiece.y
                if ourKing.x > killerPiece.x # king is on left, rook can move left
                    for i = killerPiece.x+1:ourKing.x-1
                        push!(killerPath, (i, killerPiece.y))
                    end
                else # king is on right, rook can move right
                    for i = ourKing.x+1:killerPiece.x-1
                        push!(killerPath, (i, killerPiece.y))
                    end
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if killerPiece.side == 0
                if targetx < sourcex && targety > sourcey
                    i = targetx
                    j = targety
                    while i < sourcex-1 && j > sourcey+1
                        i += 1
                        j -= 1
                        push!(killerPath, (i, j))
                    end
                elseif targetx < sourcex && targety < sourcey # target is NE of bishop
                    i = targetx
                    j = targety
                    while i < sourcex-1 && j < sourcey-1
                        i += 1
                        j += 1
                        push!(killerPath, (i, j))
                    end
                end
            elseif killerPiece.side == 1
                if targetx > sourcex && targety < sourcey # target is NW of bishop
                    i = targetx
                    j = targety
                    while i > sourcex+1 && j < sourcey-1
                        i -= 1
                        j += 1
                        push!(killerPath, (i, j))
                    end
                elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                    i = targetx
                    j = targety
                    while i > sourcex+1 && j > sourcey+1
                        i -= 1
                        j -= 1
                        push!(killerPath, (i, j))
                    end
                end
            end
        end
    elseif killerPiece.name == "ox"
        if killerPiece.y == ourKing.y
            if ourKing.x > killerPiece.x
                for i = killerPiece.x+1:ourKing.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            else
                for i = ourKing.x+1:killerPiece.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if targetx < sourcex && targety < sourcey # target is NE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j < sourcey-1
                    i += 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx < sourcex && targety > sourcey # target is SE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j > sourcey+1
                    i += 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety < sourcey # target is NW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j < sourcey-1
                    i -= 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j > sourcey+1
                    i -= 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            end
        end
    elseif killerPiece.name == "boar"
        if killerPiece.x == ourKing.x
            if ourKing.y > killerPiece.y
                for i = killPiece.y+1:ourKing.y-1
                    push!(killerPath, (killerPiece.x, i))
                end
            else
                for i = ourKing.y+1:killerPiece.y-1
                    push!(killerPath, (killerPiece.x, i))
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if targetx < sourcex && targety < sourcey # target is NE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j < sourcey-1
                    i += 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx < sourcex && targety > sourcey # target is SE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j > sourcey+1
                    i += 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety < sourcey # target is NW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j < sourcey-1
                    i -= 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j > sourcey+1
                    i -= 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            end
        end
    elseif killerPiece.name == "queen"
        if killerPiece.x == ourKing.x || killerPiece.y == ourKing.y
            if ourKing.x == killerPiece.x
                if ourKing.y > killerPiece.y # king is on bottom, rook can move down
                    for i = killPiece.y+1:ourKing.y-1
                        push!(killerPath, (killerPiece.x, i))
                    end
                else # king is on top, rook can move up
                    for i = ourKing.y+1:killerPiece.y-1
                        push!(killerPath, (killerPiece.x, i))
                    end
                end
            elseif ourKing.y == killerPiece.y
                if ourKing.x > killerPiece.x # king is on left, rook can move left
                    for i = killerPiece.x+1:ourKing.x-1
                        push!(killerPath, (i, killerPiece.y))
                    end
                else # king is on right, rook can move right
                    for i = ourKing.x+1:killerPiece.x-1
                        push!(killerPath, (i, killerPiece.y))
                    end
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if targetx < sourcex && targety < sourcey # target is NE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j < sourcey-1
                    i += 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx < sourcex && targety > sourcey # target is SE of bishop
                i = targetx
                j = targety
                while i < sourcex-1 && j > sourcey+1
                    i += 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety < sourcey # target is NW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j < sourcey-1
                    i -= 1
                    j += 1
                    push!(killerPath, (i, j))
                end
            elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                i = targetx
                j = targety
                while i > sourcex+1 && j > sourcey+1
                    i -= 1
                    j -= 1
                    push!(killerPath, (i, j))
                end
            end
        end
    elseif killerPiece.name == "white"
        if ourKing.y == killerPiece.y
            if ourKing.x > killerPiece.x
                for i = killerPiece.x+1:ourKing.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            else
                for i = ourKing.x+1:killerPiece.x-1
                    push!(killerPath, (i, killerPiece.y))
                end
            end
        else
            sourcex = killerPiece.x
            sourcey = killerPiece.y
            targetx = ourKing.x
            targety = ourKing.y
            if killerPiece.side == 0
                if targetx < sourcex && targety > sourcey
                    i = targetx
                    j = targety
                    while i < sourcex-1 && j > sourcey+1
                        i += 1
                        j -= 1
                        push!(killerPath, (i, j))
                    end
                elseif targetx < sourcex && targety < sourcey # target is NE of bishop
                    i = targetx
                    j = targety
                    while i < sourcex-1 && j < sourcey-1
                        i += 1
                        j += 1
                        push!(killerPath, (i, j))
                    end
                end
            elseif killerPiece.side == 1
                if targetx > sourcex && targety < sourcey # target is NW of bishop
                    i = targetx
                    j = targety
                    while i > sourcex+1 && j < sourcey-1
                        i -= 1
                        j += 1
                        push!(killerPath, (i, j))
                    end
                elseif targetx > sourcex && targety > sourcey # target is SW of bishop
                    i = targetx
                    j = targety
                    while i > sourcex+1 && j > sourcey+1
                        i -= 1
                        j -= 1
                        push!(killerPath, (i, j))
                    end
                end
            end
        end
    end

    saviourMoves = []
    # loop thru our pieces
        # check if any piece can move to killer pieces path - can use allowed_moves_drop()
            # add to array of saviour_moves
    for (x, y) in killerPath
        for apiece in ourPieces
            if inRange(board, move(move_number+1, "move", apiece.x, apiece.y, x, y, "", false, -1, -1, -1, -1))
                push!(saviourMoves, (apiece, (x,y)))
            end
        end
    end

    # pick lowest ranking piece's saviour move
    pieceRanks = reverse(["demon","great","vice","hawk","rgeneral","eagle","queen","bgeneral","falcon","lion","soaring","csoldier","buffalo","dragon","horse","rook","bishop","vsoldier","ssoldier","vmover","smover","lance","chariot","king","phoenix","kirin","elephant","gold","leopard","tiger","silver","copper","iron","knigh","dog","pawn"])

    for rank in pieceRanks
        for move in saviourMoves
            if rank == move[1].name
                # return sX, sY, tX, tY of saviour move; o/w 0,0,0,0
                return move[1].x, move[1].y, move[2][1], move[2][2]
            end
        end
    end

    return 0,0,0,0

end

#check whether king can run. Returns coordinates where king can run to if possible,
#else returns (0,0) if king cannot run
function checkForRun(board::Array{Array{piece,1},1}, move_number::Int64)

    boardLength = length(board)

    #king is in check, iterate through possible moves
    enemyPieces = []
    ourPieces = []
    ourKing = piece("", "", 0, 0, -1, false)

    for y = 1:length(board)
        for x = 1:length(board[1])
            if board[y][x].side == move_number%2
                if board[y][x].name == "king"
                    ourKing = board[y][x]
                end
                push!(ourPieces, board[y][x])
            elseif board[y][x].side != move_number%2 && board[y][x].side != -1
                push!(enemyPieces, board[y][x])
            end
        end
    end
    ##println  (enemyPieces)
    nonDeathMoves = []
    for y in -1:1 # y
        for x in -1:1 # x
            #create simulation king with available offsets
            simulateCheck = false # check if simulateKing is in check
            simulateKing = duplicatePiece(ourKing)
            simulateKing.x += x
            simulateKing.y += y
            if simulateKing.x > 0 && simulateKing.y > 0 && simulateKing.x <= boardLength && simulateKing.y <= boardLength # if location is not out of bounds
                if board[simulateKing.y][simulateKing.x].side != move_number%2  #if allied piece is not at location
                    for aEnemyPiece in enemyPieces
                        if inRange(board, move(move_number, "move", aEnemyPiece.x, aEnemyPiece.y, simulateKing.x, simulateKing.y, "", false, -1, -1, -1, -1))
                            simulateCheck = true
                        end
                    end
                    #if move results in a surviving king, push that move onto array
                    if simulateCheck == false
                        push!(nonDeathMoves,(simulateKing.x, simulateKing.y)) #pushing x,y coordinates as tuple
                    end
                end
            else
                simulateCheck = true
            end
        end
    end
    #if there are no moves that will let king survive, resign
    if length(nonDeathMoves) == 0
        #resign
        return 0, 0
    else
        # else make a random nondeath move from nonDeathMoves array
        srand()
        return targetX, targetY = nonDeathMoves[rand(1:length(nonDeathMoves))]
    end

end

function duplicateBoard(board::Array{Array{piece,1},1})
    boardLength = length(board)
    copy = [ [ empty for i = 1:boardLength ] for j = 1:boardLength ]
    for i in eachindex(board)
        for j in eachindex(board[i])
            copy[i][j]=duplicatePiece(board[i][j])
        end
    end
    return copy
end

function duplicatePiece(original::piece)
    return piece(original.original, original.name, original.x, original.y, original.side, original.promoted)
end

# returns promoted piece
function promote(oldPiece::piece, gameType::String)
    name = oldPiece.original
    x = oldPiece.x
    y = oldPiece.y
    side = oldPiece.side
    promoted = oldPiece.promoted

    newPiece = duplicatePiece(oldPiece)
    newPiece.promoted = true

    if promoted
        return newPiece
    end

    if gameType == "tenjiku"

        if name == "chariot"
            newPiece.name = "whale"
        elseif name == "tiger"
            newPiece.name = "stag" # flying stag
        elseif name == "silver"
            newPiece.name = "vmover"
        elseif name == "vmover"
            newPiece.name = "ox" # flying ox
        elseif name == "kirin"
            newPiece.name = "lion"
        elseif name == "lion"
            newPiece.name = "hawk"
        elseif name == "iron"
            newPiece.name = "vsoldier"
        elseif name == "vsoldier"
            newPiece.name = "csoldier"
        elseif name == "csoldier"
            newPiece.name = "tetrarch"
        elseif name == "pawn"
            newPiece.name = "gold"
        elseif name == "gold"
            newPiece.name = "rook"
        elseif name == "rook"
            newPiece.name = "dragon"
        elseif name == "dragon"
            newPiece.name = "soaring"
        elseif name == "soaring"
            newPiece.name = "rgeneral"
        elseif name == "rgeneral"
            newPiece.name = "great"
        elseif name == "elephant"
            newPiece.name = "prince"
        elseif name == "lance"
            newPiece.name = "white" # white horse
        elseif name == "dog"
            newPiece.name = "multi"
        elseif name == "copper"
            newPiece.name = "smover"
        elseif name == "smover"
            newPiece.name = "boar"
        elseif name == "phoenix"
            newPiece.name = "queen"
        elseif name == "queen"
            newPiece.name = "eagle"
        elseif name == "knight"
            newPiece.name = "ssoldier"
        elseif name == "ssoldier"
            newPiece.name = "buffalo"
        elseif name == "buffalo"
            newPiece.name = "demon"
        elseif name == "leopard"
            newPiece.name = "bishop"
        elseif name == "bishop"
            newPiece.name = "horse"
        elseif name == "horse"
            newPiece.name = "falcon"
        elseif name == "falcon"
            newPiece.name = "bgeneral"
        elseif name == "bgeneral"
            newPiece.name = "vice"
        else
            newPiece.promoted = false
        end

    elseif gameType == "chu"

        if name == "bishop"
            newPiece.name = "horse"
        elseif name == "tiger"
            newPiece.name = "stag"
        elseif name == "copper"
            newPiece.name = "smover"
        elseif name == "horse"
            newPiece.name = "falcon"
        elseif name == "dragon"
            newPiece.name = "soaring"
        elseif name == "elephant"
            newPiece.name = "prince"
        elseif name == "leopard"
            newPiece.name = "bishop"
        elseif name == "cobra" # go-between
            newPiece.name = "elephant"
        elseif name == "gold"
            newPiece.name = "rook"
        elseif name == "kirin"
            newPiece.name = "lion"
        elseif name == "lance"
            newPiece.name = "white"
        elseif name == "pawn"
            newPiece.name = "gold"
        elseif name == "phoenix"
            newPiece.name = "queen"
        elseif name == "chariot"
            newPiece.name = "whale"
        elseif name == "rook"
            newPiece.name = "dragon"
        elseif name == "smover"
            newPiece.name = "boar"
        elseif name == "silver"
            newPiece.name = "vmover"
        elseif name == "vmover"
            newPiece.name = "ox"
        else
            newPiece.promoted = false
        end

    elseif gameType == "standard" || gameType == "mini"

        if name == "rook"
            newPiece.name = "dragon"
        elseif name == "bishop"
            newPiece.name = "horse"
        elseif name == "silver"
            newPiece.name = "gold"
        elseif name == "knight"
            newPiece.name = "gold"
        elseif name == "lance"
            newPiece.name = "gold"
        elseif name == "pawn"
            newPiece.name = "gold"
        else
            newPiece.promoted = false
        end

    else
        newPiece.promoted = false
    end

    return newPiece
end

max_stars_repo_name: DarienFlamont/Shogi

max_issues_repo_name: DarienFlamont/Shogi

max_forks_repo_name: DarienFlamont/Shogi


text:
# TODO: add Coriolis vectors
import ..PlanetParameters: grav, planet_radius
export Orientation, NoOrientation, FlatOrientation, SphericalOrientation

abstract type Orientation
end

function vars_aux(m::Orientation, T)
  @vars begin
    Φ::T # gravitational potential
    ∇Φ::SVector{3,T}
  end
end

gravitational_potential(::Orientation, aux::Vars) = aux.orientation.Φ
∇gravitational_potential(::Orientation, aux::Vars) = aux.orientation.∇Φ
altitude(orientation::Orientation, aux::Vars) = gravitational_potential(orientation, aux) / grav
vertical_unit_vector(orientation::Orientation, aux::Vars) = ∇gravitational_potential(orientation, aux) / grav

"""
    NoOrientation

No gravitional force or potential.
"""
struct NoOrientation <: Orientation
end
function vars_aux(m::NoOrientation, T)
  @vars()
end
atmos_init_aux!(::NoOrientation, ::AtmosModel, aux::Vars, geom::LocalGeometry) = nothing
gravitational_potential(::NoOrientation, aux::Vars) = -zero(eltype(aux))
∇gravitational_potential(::NoOrientation, aux::Vars) = SVector{3,eltype(aux)}(0,0,0)
altitude(orientation::NoOrientation, aux::Vars) = -zero(eltype(aux))

"""
    SphericalOrientation <: Orientation

Gravity acts towards the origin `(0,0,0)`, and the gravitational potential is relative
to the surface of the planet.
"""
struct SphericalOrientation <: Orientation
end
function atmos_init_aux!(::SphericalOrientation, ::AtmosModel, aux::Vars, geom::LocalGeometry)
  normcoord = norm(aux.coord)
  aux.orientation.Φ = grav * (normcoord - planet_radius)
  aux.orientation.∇Φ = grav / normcoord .* aux.coord
end

"""
    FlatOrientation <: Orientation

Gravity acts in the third coordinate, and the gravitational potential is relative to
`coord[3] == 0`.
"""
struct FlatOrientation <: Orientation
  # for Coriolis we could add latitude?
end
function atmos_init_aux!(::FlatOrientation, ::AtmosModel, aux::Vars, geom::LocalGeometry)
  aux.orientation.Φ = grav * aux.coord[3]
  aux.orientation.∇Φ = SVector{3,eltype(aux)}(0,0,grav)
end

max_stars_repo_name: emassoud/CLIMA

max_issues_repo_name: emassoud/CLIMA

max_forks_repo_name: emassoud/CLIMA


text:
export CuDeviceArray

struct CuDeviceArray{T,N}
    ptr::Ptr{T}
    dims::NTuple{N,Cint}
    strides::NTuple{N,Cint}
end

function CuDeviceArray(x::CuArray)
    CuDeviceArray(pointer(x), Cint.(size(x)), Cint.(strides(x)))
end
function CuDeviceArray(x::CuSubArray)
    CuDeviceArray(pointer(x), Cint.(size(x)), Cint.(strides(x)))
end

Base.size(x::CuDeviceArray) = Int.(x.dims)
Base.length(x::CuDeviceArray) = Int(prod(x.dims))


text:
using OpenCL, CLBLAS, CLBlast, BenchmarkTools
@static if VERSION < v"0.7-"
    LA = Base.LinAlg
else
    using LinearAlgebra, Random, Printf
    LA = LinearAlgebra
end

CLBLAS.setup()

function run_gemm(m::Integer, n::Integer, k::Integer, T=Float32)
    srand(12345)
    A = rand(T, m, k)
    B = rand(T, k, n)
    C = rand(T, m, n)
    α = rand(T)
    β = rand(T)

    @printf("\nm = %d, n = %d, k = %d, eltype = %s\n", m, n, k, T)

    println("BLAS:")
    C_true = copy(C)
    LinAlg.BLAS.gemm!('N', 'N', α, A, B, β, C_true)
    CC = copy(C)
    display(@benchmark LinAlg.BLAS.gemm!($('N'), $('N'), $α, $A, $B, $β, $CC))
    println()

    for device in cl.devices()
        println("-"^70)
        @printf("Platform name   : %s\n", device[:platform][:name])
        @printf("Platform version: %s\n", device[:platform][:version])
        @printf("Device name     : %s\n", device[:name])
        @printf("Device type     : %s\n", device[:device_type])
        println()

        ctx = cl.Context(device)
        queue = cl.CmdQueue(ctx)

        println("CLBLAS:")
        A_cl = cl.CLArray(queue, A)
        B_cl = cl.CLArray(queue, B)
        C_cl = cl.CLArray(queue, C)
        CLBLAS.gemm!('N', 'N', α, A_cl, B_cl, β, C_cl)
        @assert cl.to_host(C_cl) ≈ C_true
        display(@benchmark CLBLAS.gemm!($('N'), $('N'), $α, $A_cl, $B_cl, $β, $C_cl))
        println()

        println("CLBlast:")
        A_cl = cl.CLArray(queue, A)
        B_cl = cl.CLArray(queue, B)
        C_cl = cl.CLArray(queue, C)
        CLBlast.gemm!('N', 'N', α, A_cl, B_cl, β, C_cl)
        @assert cl.to_host(C_cl) ≈ C_true
        display(@benchmark CLBlast.gemm!($('N'), $('N'), $α, $A_cl, $B_cl, $β, $C_cl))
        println()
    end
end

run_gemm(2^10, 2^10, 2^10, Float32)


text:
"""
    readData(path_to_data_folder, complete_trayek = true)
reads the data folder given into dataframes ready to be used.
the data folder must contain:
- khazanah (id, name, x_coor, y_coor, capacity, cjarak, cpeti, transit)
- trayek (u, v, moda)
- moda (name, capacity, cjarak, cpeti, transit)
- demand (location_id, period, pecahan, value)
- stock (location_id, pecahan, value)
by default completes the trayek by ensuring for every a -> b there exists b -> a.
"""
function readData(path::String, complete_trayek::Bool=true)
    khazanah = CSV.read(joinpath(path, "khazanah.csv"), DataFrame)
    demand = CSV.read(joinpath(path, "demand.csv"), DataFrame)
    stock = CSV.read(joinpath(path, "stock.csv"), DataFrame)
    trayek = CSV.read(joinpath(path, "trayek.csv"), DataFrame)
    moda = CSV.read(joinpath(path, "moda.csv"), DataFrame)

    if complete_trayek
        append!(trayek, DataFrame(u=trayek.v, v=trayek.u, moda=trayek.moda))
        unique!(trayek)
    end

    trayek = innerjoin(trayek, moda, on=:moda => :name)

    return khazanah, demand, stock, trayek
end


text:
using FrankWolfe
using LinearAlgebra
using Test
using SparseArrays

@testset "Testing Blended Pairwise Conditional Gradients" begin
    f(x) = norm(x)^2
    function grad!(storage, x)
        @. storage = 2x
        return nothing
    end
    lmo_prob = FrankWolfe.ProbabilitySimplexOracle(4)
    x0 = FrankWolfe.compute_extreme_point(lmo_prob, zeros(10))
    res_bpcg = FrankWolfe.blended_pairwise_conditional_gradient(
        f,
        grad!,
        lmo_prob,
        x0,
        max_iteration=6000,
        line_search=FrankWolfe.Adaptive(),
        verbose=false,
    )
    res_afw = FrankWolfe.away_frank_wolfe(
        f,
        grad!,
        lmo_prob,
        x0,
        max_iteration=6000,
        line_search=FrankWolfe.Adaptive(),
        print_iter=100,
        verbose=false,
    )
    @test res_afw[3] ≈ res_bpcg[3]
    @test norm(res_afw[1] - res_bpcg[1]) ≈ 0 atol=1e-6
    res_bpcg2 = FrankWolfe.blended_pairwise_conditional_gradient(
        f,
        grad!,
        lmo_prob,
        x0,
        max_iteration=6000,
        line_search=FrankWolfe.Adaptive(),
        verbose=false,
        lazy=true
    )
    @test res_bpcg2[3] ≈ res_bpcg[3] atol=1e-5
end


text:
using Test

using RingSignature

@testset "Smoke" begin
    N = 8
    msg1 = Vector{UInt8}("XKeyScore allows the NSA to read anyone's email in the world.")
    msg2 = Vector{UInt8}("The NSA can spy on you through Angry Birds.")

    ctx = RingContext(N, 1024)
    for i in 1:N
        s1 = ring_sign(ctx, msg1, i)
        s2 = ring_sign(ctx, msg2, i)
        @test ring_verify(ctx, msg1, s1) && ring_verify(ctx, msg2, s2)
        @test !ring_verify(ctx, msg1, s2) && !ring_verify(ctx, msg2, s1)
    end
end

max_stars_repo_name: gyk/TrivialSolutions

max_issues_repo_name: gyk/TrivialSolutions

max_forks_repo_name: gyk/TrivialSolutions


text: println("Hello world to $(length(ARGS) > 0 ? join(ARGS, "-") : "you")!")

max_stars_repo_name: MiroK/seminar-julia

max_issues_repo_name: MiroK/seminar-julia

max_forks_repo_name: MiroK/seminar-julia


text:
include("./LatticeQCD.jl")
using .LatticeQCD
using Random
using Dates
using JLD

function test()
    Random.seed!(111)
    A = rand(ComplexF64,4,4)*4
    A = A'*A
    n = 4
    ϕ = ComplexF64[1,2,3,4]
    ϕr =  LatticeQCD.calc_exactvalue(n,A,ϕ)
    println(ϕ'*ϕr)

    ϕr2 =  LatticeQCD.calc_Anϕ(n,A,ϕ)
    println(ϕ'*ϕr2)

    #LatticeQCD.calc_det(n,A,ϕ)
end

test()


text:
using LatBo: Simulation, SandBox
using LatBo.Indices: index
using LatBo.LB: Homogeneous, equilibrium, Initializer
import LatBo.LB.initialize

type MockInitializer <: Initializer
    value
end
function initialize(init::MockInitializer, sim::Simulation, site::Integer)
    sim.populations[:, site] = init.value
end

facts("Initialization") do
    const lattice = :D2Q9
    sim = SandBox(lattice, (4, 4))

    context("Homogeneous momentum and density") do
        const ρ₀ = Float64(0.5)
        const μ₀ = Float64[1, 2]
        const feq = equilibrium(:D2Q9, ρ₀, μ₀)
        const start = Int64[3, 3]

        initializer = Homogeneous(ρ₀, μ₀)
        sim.populations[:] = 0
        initialize(initializer, sim, start)
        @fact sim.populations[:, index(sim.indexing, start)] --> roughly(feq)
        @fact sum(abs(sim.populations)) --> roughly(sum(abs(feq)))
    end

    context("Loop over all sites") do
        sim.playground[:] = 1
        sim.playground[5] = 2
        sim.initializers = Dict(
            1 => MockInitializer(0), 2 => MockInitializer(1))

        sim.populations[:] = -1
        initialize(sim)

        @fact any(sim.populations == -1) --> false
        @fact sim.populations[:, 5] --> roughly(ones(sim.populations[:, 1]))
    end
end


text:
#!/usr/bin/env julia
#
# Script to create a sysimage with all of Trixi's dependencies and, optionally, Trixi itself.
# Note: You need to have `OrdinaryDiffEq`, `Plots`, and `Trixi2Vtk` installed as packages in the
# general environment.
#
# After the sysimage has been generated, you can use it by starting Julia with
#
#     julia --sysimage=path/to/new/sysimage
#
# Usage:
#
#     julia build_sysimage.jl
#     [TRIXI_SYSIMAGE_PATH=...] [TRIXI_SYSIMAGE_INCLUDE_TRIXI=...] julia build_sysimage.jl
#
# Optional environment variables:
#
#   TRIXI_SYSIMAGE_PATH:
#       Path where the resulting sysimage will be stored.
#       (default: `TrixiSysimage.<ext>` where `<ext>` is `.so`, `.dylib`, or `.dll`)
#
#   TRIXI_SYSIMAGE_INCLUDE_TRIXI:
#       If "no", "1", or "false" (all case-insensitive), only Trixi's direct dependencies  +
#       `OrdinaryDiffEq`, `Plots`, and `Trixi2Vtk` are stored in the sysimage. This is useful when
#       doing development with Trixi and only the startup time due to dependencies should be
#       reduced. If "yes", "1", or "true" (all case-insensitive), `Trixi` itself is included. Note
#       that in this case it is not possible to change existing functionality in Trixi anymore
#       (e.g., overwriting methods etc. will not work).
#       (default: `no`)
#
# Examples:
#
#   To include Trixi in the sysimage that should be created as `Trixi.so`, execute this script as
#   follows:
#
#       TRIXI_SYSIMAGE_PATH=Trixi.so TRIXI_SYSIMAGE_INCLUDE_TRIXI=yes julia build_sysimage.jl
#
# Special thanks to the people at the CliMA project with the ClimateMachine.jl package
# (https://github.com/CliMA/ClimateMachine.jl), from which most of this code is inspired!

using Pkg, Libdl

@info "Creating sysimage for Trixi..."
start_time = time()

# Create a temporary environment to install all necessary packages without modifying
# the users environment
Pkg.activate(temp=true)

# Add package compiler, Trixi, and additional packages that shall be built into the sysimage
Pkg.add("PackageCompiler")
Pkg.add("Trixi")

# Note that all packages built into a sysimage need to be in the current project as
# direct dependencies. Hence, we add direct dependencies of Trixi as direct dependencies
# of the current temporary project if we do not want to bundle Trixi into the sysimage.
packages = Symbol[:OrdinaryDiffEq, :Plots, :Trixi2Vtk]
if lowercase(get(ENV, "TRIXI_SYSIMAGE_INCLUDE_TRIXI", "no")) in ("yes", "1", "true")
  # If Trixi is to be included, just add it to the list
  push!(packages, :Trixi)
else
  # Otherwise, figure out all direct dependencies and add them instead
  # Inspired by: https://github.com/CliMA/ClimateMachine.jl/blob/8c57fb55acc20ee824ea37478395a7cb07c5a93c/.dev/systemimage/climate_machine_image.jl
  trixi_uuid = Base.UUID("a7f1ee26-1774-49b1-8366-f1abc58fbfcb")
  append!(packages, Symbol[Symbol(v) for v in keys(Pkg.dependencies()[trixi_uuid].dependencies)])
end

map(Pkg.add ∘ string, packages)
Pkg.precompile()

# Collect remaining arguments
sysimage_path = get(ENV, "TRIXI_SYSIMAGE_PATH", joinpath(@__DIR__, "TrixiSysimage." * Libdl.dlext))
precompile_execution_file = joinpath(@__DIR__, "precompile_execution_file.jl")

# Create system image
@info "Included packages: $packages"
@info "Sysimage path: $sysimage_path"
@info "Precompile execution file: $precompile_execution_file"

using PackageCompiler
PackageCompiler.create_sysimage(
  packages,
  sysimage_path=sysimage_path,
  precompile_execution_file=precompile_execution_file,
  cpu_target=PackageCompiler.default_app_cpu_target()
)

duration = time() - start_time
@info "Done. Created sysimage in $duration seconds."


text:
using KernelFunctions
using MLDataUtils
using Zygote
using Flux
using Distributions, LinearAlgebra
using Plots

Flux.@functor SqExponentialKernel
Flux.@functor ScaleTransform
Flux.@functor KernelSum
Flux.@functor Matern32Kernel

xmin = -3;
xmax = 3;
x = range(xmin, xmax; length=100)
x_test = range(xmin, xmax; length=300)
x, y = noisy_function(sinc, x; noise=0.1)
X = reshape(x, :, 1)
X_test = reshape(x_test, :, 1)
k = SqExponentialKernel(1.0)#+Matern32Kernel(2.0)
λ = [-1.0]
function f(x, k, λ)
    return kernelmatrix(k, x, X; obsdim=1) *
           inv(kernelmatrix(k, X; obsdim=1) + exp(λ[1]) * I) *
           y
end
f(X, k, 1.0)
loss(k, λ) = ŷ -> sum(y - ŷ) / length(y) + exp(λ[1]) * norm(ŷ)(f(X, k, λ))
loss(k, λ)
ps = Flux.params(k)
push!(ps, λ)
opt = Flux.Momentum(0.1)
##
for i in 1:10
    grads = Zygote.gradient(() -> loss(k, λ), ps)
    Flux.Optimise.update!(opt, ps, grads)
    p = Plots.scatter(x, y; lab="data", title="Loss = $(loss(k,λ))")
    Plots.plot!(x_test, f(X_test, k, λ); lab="Prediction", lw=3.0)
    display(p)
end


text:
export hhlcircuit, hhlproject!, hhlsolve, HHLCRot
import YaoArrayRegister.u1rows!

"""
    HHLCRot{N, NC} <: PrimitiveBlock{N}

Controlled rotation gate used in HHL algorithm, applied on N qubits.

    * cbits: control bits.
    * ibit:: the ancilla bit.
    * C_value:: the value of constant "C", should be smaller than the spectrum "gap".
"""
struct HHLCRot{N, NC, T} <: PrimitiveBlock{N}
    cbits::Vector{Int}
    ibit::Int
    C_value::T
    HHLCRot{N}(cbits::Vector{Int}, ibit::Int, C_value::T) where {N, T} = new{N, length(cbits), T}(cbits, ibit, C_value)
end

@inline function hhlrotmat(λ::Real, C_value::Real)
    b = C_value/λ
    a = sqrt(1-b^2)
    a, -b, b, a
end

function YaoBlocks._apply!(reg::ArrayReg, hr::HHLCRot{N, NC, T}) where {N, NC, T}
    mask = bmask(hr.ibit)
    step = 1<<(hr.ibit-1)
    step_2 = step*2
    nbit = nqubits(reg)
    for j = 0:step_2:size(reg.state, 1)-step
        for i = j+1:j+step
            λ = bfloat(readbit(i-1, hr.cbits...), nbits=nbit-1)
            if λ >= hr.C_value
                u = hhlrotmat(λ, hr.C_value)
                YaoArrayRegister.u1rows!(state(reg), i, i+step, u...)
            end
        end
    end
    reg
end

"""
    hhlproject!(all_bit::ArrayReg, n_reg::Int) -> Vector

project to aiming state |1>|00>|u>, and return |u> vector.
"""
function hhlproject!(all_bit::ArrayReg, n_reg::Int)
    all_bit |> focus!(1:(n_reg+1)...) |> select!(1) |> state |> vec
end

"""
Function to build up a HHL circuit.
"""
function hhlcircuit(UG, n_reg::Int, C_value::Real)
    n_b = nqubits(UG)
    n_all = 1 + n_reg + n_b
    pe = PEBlock(UG, n_reg, n_b)
    cr = HHLCRot{n_reg+1}([2:n_reg+1...], 1, C_value)
    chain(n_all, subroutine(n_all, pe, [2:n_all...,]), subroutine(n_all, cr, [1:(n_reg+1)...,]), subroutine(n_all, pe', [2:n_all...,]))
end

"""
    hhlsolve(A::Matrix, b::Vector) -> Vector

solving linear system using HHL algorithm. Here, A must be hermitian.
"""
function hhlsolve(A::Matrix, b::Vector, n_reg::Int, C_value::Real)
    if !ishermitian(A)
        throw(ArgumentError("Input matrix not hermitian!"))
    end
    UG = matblock(exp(2π*im.*A))

    # Generating input bits
    all_bit =  join(ArrayReg(b), zero_state(n_reg), zero_state(1))

    # Construct HHL circuit.
    circuit = hhlcircuit(UG, n_reg, C_value)

    # Apply bits to the circuit.
    apply!(all_bit, circuit)

    # Get state of aiming state |1>|00>|u>.
    hhlproject!(all_bit, n_reg) ./ C_value
end


text:
function ground(color)
    (args...) -> begin
        background(color)
        sethue("white")
    end
end

@testset "postprocess_frames_flow" begin

    function postprocess_frames_flow(frames)
        [reverse(frames); reverse(frames)]
    end

    n_nopostprocess = 100
    nopostprocessvideo = Video(200, 200)
    Background(1:n_nopostprocess, ground("black"))
    circ = Object(1:25, JCircle(Point(-20, -20), 20, action = :fill, color = "white"))
    circ = Object(26:50, JCircle(Point(20, 20), 20, action = :fill, color = "white"))
    circ = Object(51:75, JCircle(Point(-20, -20), 20, action = :fill, color = "white"))
    circ = Object(76:100, JCircle(Point(20, 20), 20, action = :fill, color = "white"))
    render(
        nopostprocessvideo,
        tempdirectory = "images/withoutpostprocessing",
        pathname = "",
    )

    postprocessvideo = Video(200, 200)
    Background(-24:25, ground("black"))
    circ = Object(-24:0, JCircle(Point(20, 20), 20, action = :fill, color = "white"))
    circ = Object(1:25, JCircle(Point(-20, -20), 20, action = :fill, color = "white"))
    render(
        postprocessvideo,
        tempdirectory = "images/withpostprocessing",
        pathname = "",
        postprocess_frames_flow = postprocess_frames_flow,
    )

    for frame in [10, 30, 50, 70, 90, 100]
        png_name = lpad(string(frame), 10, "0")
        @test_reference "images/withpostprocessing/$png_name.png" load(
            "images/withoutpostprocessing/$png_name.png",
        )
    end

    for i in 1:n_nopostprocess
        rm("images/withpostprocessing/$(lpad(i, 10, "0")).png")
        rm("images/withoutpostprocessing/$(lpad(i, 10, "0")).png")
    end
    rm("images/withpostprocessing/", recursive = true)
    rm("images/withoutpostprocessing/", recursive = true)
end

@testset "postprocess_frame" begin

    function postprocess_frame(frame_image, frame, frames)
        h(x) = RGB(x.r, 1.0, x.b)
        return h.(frame_image)
    end

    n_frames = 50
    onepostprocessvideo = Video(200, 200)
    Background(1:n_frames, ground(RGB(0.0, 1.0, 0.0)))
    circ = Object(
        1:25,
        JCircle(Point(-20, -20), 20, action = :fill, color = RGB(1.0, 1.0, 0.0)),
    )
    circ = Object(
        26:50,
        JCircle(Point(20, 20), 20, action = :fill, color = RGB(1.0, 1.0, 0.0)),
    )

    render(
        onepostprocessvideo,
        tempdirectory = "images/withoutpostprocessing",
        pathname = "",
    )

    twopostprocessvideo = Video(200, 200)
    Background(1:n_frames, ground("black"))
    circ = Object(1:25, JCircle(Point(-20, -20), 20, action = :fill, color = "red"))
    circ = Object(26:50, JCircle(Point(20, 20), 20, action = :fill, color = "red"))
    render(
        twopostprocessvideo,
        tempdirectory = "images/withpostprocessing",
        pathname = "",
        postprocess_frame = postprocess_frame,
    )

    for frame in [5, 15, 25, 35, 45, 50]
        png_name = lpad(string(frame), 10, "0")
        @test_reference "images/withoutpostprocessing/$png_name.png" load(
            "images/withpostprocessing/$png_name.png",
        )
    end

    for i in 1:n_frames
        rm("images/withoutpostprocessing/$(lpad(i, 10, "0")).png")
        rm("images/withpostprocessing/$(lpad(i, 10, "0")).png")
    end
    rm("images/withoutpostprocessing/", recursive = true)
    rm("images/withpostprocessing/", recursive = true)
end

@testset "postprocess_frame cropped padded" begin

    function postprocess_pad(frame_image, idx, frames)
        return if idx > 25
            frame_image[1:100, 1:100]
        else
            frame_image
        end
    end

    n_frames = 50
    padvideo = Video(200, 200)
    Background(1:n_frames, ground(RGB(0.0, 1.0, 0.0)))

    render(
        padvideo,
        tempdirectory = "images",
        postprocess_frame = postprocess_pad,
        pathname = "",
    )

    for frame in [5, 15, 25]
        png_no_pad = lpad(string(frame), 10, "0")
        png_pad = lpad(string(frame + 25), 10, "0")
        @test_reference "images/$png_no_pad.png" load("images/$png_pad.png")
    end

    for i in 1:n_frames
        rm("images/$(lpad(i, 10, "0")).png")
    end
    rm("images/", recursive = true)

    function postprocess_crop(frame_image, idx, frames)
        return if idx > 25
            repeat([frame_image[1, 1]], 300, 300)
        else
            frame_image
        end
    end

    cropvideo = Video(200, 200)
    Background(1:n_frames, ground("black"))
    render(
        cropvideo,
        tempdirectory = "images",
        pathname = "",
        postprocess_frame = postprocess_crop,
    )

    for frame in [5, 15, 25]
        png_no_crop = lpad(string(frame), 10, "0")
        png_crop = lpad(string(frame + 25), 10, "0")
        @test_reference "images/$png_no_crop.png" load("images/$png_crop.png")
    end

    for i in 1:n_frames
        rm("images/$(lpad(i, 10, "0")).png")
    end
    rm("images/", recursive = true)
end

@testset "postprocess_frame and postprocess_frames_flow" begin

    function ground_double_color(c11, c12, c21, c22, framenumber, thr)
        if framenumber <= thr
            background(c11)
            sethue(c12)
        else
            background(c21)
            sethue(c22)
        end
    end

    function postprocess_frame(frame_image, idx, frames)
        h(x) = RGB(x.r, 1.0, x.b)
        return if idx <= 50
            h.(frame_image)
        else
            frame_image
        end
    end

    function postprocess_frames_flow(frames)
        [frames; reverse(frames)]
    end

    n_nopostprocess = 100
    nopostprocessvideo = Video(200, 200)
    Background(
        1:n_nopostprocess,
        (x, y, frame) ->
            ground_double_color(RGB(0.0, 1.0, 0.0), "white", "black", "red", frame, 50),
    )
    circ = Object(
        1:25,
        JCircle(Point(-20, -20), 20, action = :fill, color = RGB(0.0, 1.0, 1.0)),
    )
    circ = Object(
        26:50,
        JCircle(Point(20, 20), 20, action = :fill, color = RGB(0.0, 1.0, 1.0)),
    )
    circ = Object(51:75, JCircle(Point(20, 20), 20, action = :fill, color = "blue"))
    circ = Object(76:100, JCircle(Point(-20, -20), 20, action = :fill, color = "blue"))
    render(
        nopostprocessvideo,
        tempdirectory = "images/withoutpostprocessing",
        pathname = "",
    )

    n_postprocess = 50
    postprocessvideo = Video(200, 200)
    Background(1:n_postprocess, ground("black"))
    circ = Object(1:25, JCircle(Point(-20, -20), 20, action = :fill, color = "blue"))
    circ = Object(26:50, JCircle(Point(20, 20), 20, action = :fill, color = "blue"))
    render(
        postprocessvideo,
        tempdirectory = "images/withpostprocessing",
        pathname = "",
        postprocess_frames_flow = postprocess_frames_flow,
        postprocess_frame = postprocess_frame,
    )

    for frame in [10, 30, 50, 70, 90, 100]
        png_name = lpad(string(frame), 10, "0")
        @test_reference "images/withpostprocessing/$png_name.png" load(
            "images/withoutpostprocessing/$png_name.png",
        )
    end

    for i in 1:n_nopostprocess
        rm("images/withpostprocessing/$(lpad(i, 10, "0")).png")
        rm("images/withoutpostprocessing/$(lpad(i, 10, "0")).png")
    end
    rm("images/withpostprocessing/", recursive = true)
    rm("images/withoutpostprocessing/", recursive = true)
end

@testset "postprocess_frames_flow sanity check" begin
    h(x) = [x; 50]
    change_first(x) = x[10:end]
    n_frames = 20
    video = Video(200, 200)
    Background(1:n_frames, ground("black"))
    circ = Object(1:20, JCircle(Point(-20, -20), 20, action = :fill, color = "white"))

    @test_throws ErrorException render(video, pathname = "", postprocess_frames_flow = h)
end

@testset "crop" begin

    function gen_im(height, width)
        @imagematrix begin
            background("black")
            sethue("white")
            circle(O, 20, :fill)
            box(O, 50, 50, :stroke)
        end height width
    end

    h_w_1 = [(200, 200), (150, 150), (151, 151), (200, 200)]
    h_w_2 = [(100, 100), (59, 59), (67, 67), (49, 49)]

    for idx in 1:length(h_w_1)
        im1 = Javis.crop(gen_im(h_w_1[idx]...), h_w_2[idx]...)
        im2 = gen_im(h_w_2[idx]...)
        @test size(im1) == size(im2)
    end

end


text:
#  Copyright 2017, Oscar Dowson

export binexpand, bincontract, bitsrequired

# Cache these for speed
const log2inv = 1 / log(2)
# dereferencing an array is faster than a 2^x call
const _2i_ = Int[2^(i-1) for i in 1:floor(Int, log(typemax(Int)) * log2inv)+1]
const _2i_L = length(_2i_)

function binexpand!(y::Vector{Int}, x::Int)
    if x < 0
        error("Values to be expanded must be nonnegative. Currently x = $x.")
    end
    @inbounds for i in length(y):-1:1
        k = _2i_[i]
        if x >= k
            y[i] = 1
            x -= k
        end
    end
    if x > 0
        error("Unable to expand binary. Overflow of $x.")
    end
end

function bitsrequired(x::Int)
    floor(Int, log(x) * log2inv) + 1
end
function bitsrequired(x::Float64, eps::Float64=0.1)
    xx = round(Int, x / eps)
    floor(Int, log(xx) * log2inv) + 1
end

"""
    binexpand(x::Int; length::Int=-1, maximum::Real=-1)

Returns an array of 0/1 coefficients for the binary expansion of `x`.
If trailing zeroes are needed, use `length` to specify the length of the output.
"""
function binexpand(x::Int; length::Int=-1, maximum::Real=-1)
    x < 0 && error("Cannot perform binary expansion on a negative number.")
    if maximum != -1
        if length != -1
            warn("Length is being ignored.")
        end
        length = bitsrequired(floor(Int, maximum))
    end
    if length == -1
        y = zeros(Int, bitsrequired(x))
    else
        y = zeros(Int, length)
    end
    binexpand!(y, x)
    y
end

"""
    binexpand(x::Float64, eps::Float64=0.1; length::Int=-1, maximum::Real=-1)

Returns an array of 0/1 coefficients for the binary expansion of `x`.
If trailing zeroes are needed, use `length` to specify the length of the output.
"""
function binexpand(x::Float64, eps::Float64=0.1; length::Int=-1, maximum::Real=-1)
    x < 0 && error("Cannot perform binary expansion on a negative number.")
    if eps <= 0.0
        error("Epsilon tolerance for Float binary expansion must be strictly greater than 0.")
    end
    xx = round(Int, x / eps)
    if maximum != -1
        if length != -1
            warn("Length is being ignored.")
        end
        length = bitsrequired(floor(Int, maximum / eps))
    end
    binexpand(xx, length=length)
end

function bincontract_2i_(y::Vector{T}) where T
    x = zero(T)
    @inbounds for i in 1:length(y)
        x += _2i_[i] * y[i]
    end
    x
end
function bincontract_pow(y::Vector{T}) where T
    x = zero(T)
    @inbounds for i in 1:length(y)
        x += 2^(i-1) * y[i]
    end
    x
end

"""
    bincontract{T}(y::Vector{T})

For vector `y`, evaluates ∑ᵢ 2ⁱ⁻¹yᵢ.
"""
function bincontract(y::Vector{T}) where T
    if length(y) < _2i_L
        bincontract_2i_(y)
    else
        bincontract_pow(y)
    end
end

function bincontract(::Type{Float64}, y::Vector{T}, eps::Float64=0.1) where T
    if eps <= 0
        error("Epsilon tolerance for Float binary contraction must be strictly greater than 0.")
    end
    xx = bincontract(y)
    xx * eps
end


text:
# Autogenerated wrapper script for ngspice_jll for aarch64-linux-musl
export libngspice, ngspice

JLLWrappers.@generate_wrapper_header("ngspice")
JLLWrappers.@declare_library_product(libngspice, "libngspice.so.0")
JLLWrappers.@declare_executable_product(ngspice)
function __init__()
    JLLWrappers.@generate_init_header()
    JLLWrappers.@init_library_product(
        libngspice,
        "lib/libngspice.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_executable_product(
        ngspice,
        "bin/ngspice",
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
using NiLang, NiLang.AD
using Test

@testset "check grad" begin
    for opm in [PlusEq, MinusEq]
        @test check_grad(opm(identity), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(*), (1.0, 2.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(+), (1.0, 2.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(-), (1.0, 2.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(^), (1.0, 2.0, 2); verbose=true, iloss=1)
        @test check_grad(opm(^), (1.0, 2.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(inv), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(sqrt), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(abs), (1.0, -2.0); verbose=true, iloss=1)
        @test check_grad(opm(abs2), (1.0, -2.0); verbose=true, iloss=1)
        @test check_grad(opm(exp), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(log), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(sin), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(sinh), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(asin), (1.0, 0.2); verbose=true, iloss=1)
        @test check_grad(opm(cos), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(cosh), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(acos), (1.0, 0.2); verbose=true, iloss=1)
        @test check_grad(opm(tan), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(tanh), (1.0, 2.0); verbose=true, iloss=1)
        @test check_grad(opm(atan), (1.0, -2.0); verbose=true, iloss=1)
        @test check_grad(opm(atan), (1.0, -2.0, 1.5); verbose=true, iloss=1)
        @test check_grad(opm(convert), (Fixed43(0.5), 2.0); verbose=true, iloss=1)
        @test check_grad(opm(/), (1.0, 2.0, 2.0); verbose=true, iloss=1)
        @test_broken check_grad(opm(÷), (1.0, 2.0, 2.0); verbose=true, iloss=1)
        @test gradient(opm(sqrt), (1.0, 0.0); iloss=1)[2] == 0
    end
    @test check_grad(-, (1.0,); verbose=true, iloss=1)
    @test check_grad(NEG, (1.0,); verbose=true, iloss=1)
    @test check_grad(INV, (3.0,); verbose=true, iloss=1)
    @test check_grad(AddConst(2.0), (3.0,); verbose=true, iloss=1)
    @test check_grad(SubConst(2.0), (3.0,); verbose=true, iloss=1)
    @test check_grad(INC, (1.0,); verbose=true, iloss=1)
    @test check_grad(DEC, (1.0,); verbose=true, iloss=1)
    @test check_grad(ROT, (1.0, 2.0, 2.0); verbose=true, iloss=1)
    @test check_grad(ROT, (1.0, 2.0, 2.0); verbose=true, iloss=2)
    @test check_grad(IROT, (1.0, 2.0, 2.0); verbose=true, iloss=1)
    @test check_grad(IROT, (1.0, 2.0, 2.0); verbose=true, iloss=2)
    @test check_grad(HADAMARD, (3.0, 2.0); verbose=true, iloss=1)
    @test check_grad(HADAMARD, (3.0, 2.0); verbose=true, iloss=2)
end

@testset "sincos" begin
    @i function f(s, c, x)
        (s, c) += sincos(x)
    end
    @test check_grad(f, (1.0, 2.0, 2.0); verbose=true, iloss=1)
    @test check_grad(f, (1.0, 2.0, 2.0); verbose=true, iloss=2)
end

@testset "AD over pop" begin
    @i function mean(out!, x)
        anc ← zero(out!)
        for i=1:length(x)
            anc += x[i]
        end
        out! += anc / (@const length(x))
        PUSH!(anc)
    end

    @test check_grad(mean, (0.0, [1,2,3.0, 4.0]); iloss=1)
end

@testset "AD over pipe" begin
    @i function mean(out!, anc, x)
        for i=1:length(x)
            ⊕(identity)(anc, x[i])
            SWAP(anc, x[i])
        end
        out! += anc / (@const length(x))
    end

    @test check_grad(mean, (0.0, 0.0, [1,2,3.0, 4.0]); iloss=1, verbose=true)
end

@testset "push, load data" begin
    stack = []
    val = PUSH!(stack, [1,2,3])[2]
    @test val == Int[]
    val = PUSH!(stack, 3.0)[2]
    @test val == 0.0
    PUSH!(stack, 3.0)
    @test_throws InvertibilityError POP!(stack, GVar(3.0))
    PUSH!(stack, 3.0)
    @test POP!(stack, GVar(0.0))[2] == GVar(3.0)
    x = [1.0, 2.0, 3.0]
    PUSH!(stack, x)
    @test POP!(stack, empty(x))[2] == GVar.([1,2,3.0])
    x = [1.0, 2.0, 3.0]
    PUSH!(stack, x)
    @test POP!(stack, empty(x))[2] == [1,2,3.0]
end

@testset "dataviews" begin
    @i function f(z, y, x)
        y += cos(x |> INV)
        z += tan(y |> AddConst(4.0))
        z += y * (x |> NEG |> SubConst(0.5) |> INV)
        z += sin(x |> INV)
    end
    @test check_grad(f, (0.2, 0.5, 0.8); iloss=1)
end


text:
include("../src/FiberNlse.jl")
using .FiberNlse
# Simulation dimension
Nₜ, Nₗ = (1000,1000);

# Fiber properties
L = 5km; # Fiber length
fib2 = FiberNlse.smf28(L)
fib1 = FiberNlse.Fiber(0, fib2.α, fib2.γ,L)

b=FiberNlse.Bundle([FiberNlse.edfa(15,15)], 1000)
# Signal properties
T = 200*ps; # Signal duration
λ = 1550*nm; # Wavelength
τ = 5*ps; # Pulse duration
N = 1 # Soliton number
sims,t,l = FiberNlse.configure(b,Nₜ, T, λ);
# Input construction
Pp = 1e-3#abs((sims[1].β2/fib1.γ/τ^2)*N^2) # Soliton power
Ψₒ = @. sqrt(Pp)/cosh(t/τ) # Soliton formula
S=FiberNlse.simulate(sims,Ψₒ,false);

# Visualization
using Plots
gr()
heatmap(l/km, t/ps,abs2.(S'))


text:
# Julia1_3.3.jl Tasks/Coroutines and Channels
#
# Using Tasks
s1() = sum(i for i=1:1000000) # function to sum 1 to 1000
s1() = sum(1:1000000)         # shorthand for the same thing
st=Task(s1)       # turn function s1 into task st
schedule(st)      # schedule task to run
istaskstarted(st) # true if started

istaskdone(st)    # true if done

st.result    # get results

# returns name and address of currently running task
current_task()
# yield() causes the scheduler to switch to the
# next scheduled Task.
# yield() if called by a task, will restart that task
yield()

# Using Channels using a coroutine
in1=open("data1.csv") # Opening a test data file
c=Channel{Int64}(16)  # defining a 16 word FIFO buffer
function getdata()    # defining a function getdata() a coroutine
    while true        # inf while loop
        s=readline(in1)             # read line as String
        if length(s)==0; break; end # if null loop done
        v=[parse(Int64,ss) for ss in split(s)] #Int64 vector
        for n in v; put!(c,n); end  # put ea # in channel c
    end
end
gt=Task(getdata) # make getdata into a task
schedule(gt)     #schedule it
if isready(c); take!(c); end         # take an Int64 from channel c

current_task()   # what is the currently running task

close(in1)       # Close data file


text:
#
# Writing Julia dictionaries to YAML files is implemented with multiple dispatch and recursion:
# Depending on the value type, Julia chooses the appropriate _print function, which may add a
# level of recursion.
#

"""
    write_file(path, data, prefix="")

Write some data (e.g. a dictionary or an array) to a YAML file.
"""
write_file(path::AbstractString, data::Any, prefix::AbstractString="") =
    open(path, "w") do io
        write(io, data, prefix)
    end

"""
    write([io], data, prefix="")

Write a YAML representation of some data (e.g. a dictionary or an array) to an IO stream,
if provided, or return a string of that representation.
"""
function write(io::IO, data::Any, prefix::AbstractString="")
    print(io, prefix) # print the prefix, e.g. a comment at the beginning of the file
    _print(io, data) # recursively print the data
end

function write(data::Any, prefix::AbstractString="")
    io = IOBuffer()
    write(io, data, prefix)
    return String(take!(io))
end

"""
    yaml(data)

Return a YAML-formatted string of the `data`.
"""
yaml(data::Any) = write(data)

# recursively print a dictionary
_print(io::IO, dict::AbstractDict, level::Int=0, ignore_level::Bool=false) =
    if length(dict) > 0
        for (i, pair) in enumerate(dict)
            _print(io, pair, level, ignore_level ? i == 1 : false) # ignore indentation of first pair
        end
    else
        @warn "Writing an empty $(typeof(dict)), which might be parsed as nothing"
        print(io, "\n") # https://github.com/JuliaData/YAML.jl/issues/81
    end

# recursively print an array
_print(io::IO, arr::AbstractVector, level::Int=0, ignore_level::Bool=false) =
    for (i, elem) in enumerate(arr)
        if typeof(elem) <: AbstractVector # vectors of vectors must be handled differently
            print(io, _indent("-\n", level))
            _print(io, elem, level + 1)
        else
            print(io, _indent("- ", level))   # print the sequence element identifier '-'
            _print(io, elem, level + 1, true) # print the value directly after
        end
    end

# print a single key-value pair
function _print(io::IO, pair::Pair, level::Int=0, ignore_level::Bool=false)
    key = if typeof(pair[1]) == Nothing
        "null" # this is what the YAML parser interprets as 'nothing'
    else
        string(pair[1]) # any useful case
    end
    print(io, _indent(key * ":", level, ignore_level)) # print the key
    if (typeof(pair[2]) <: AbstractDict || typeof(pair[2]) <: AbstractVector)
        print(io, "\n") # a line break is needed before a recursive structure
    else
        print(io, " ") # a whitespace character is needed before a single value
    end
    _print(io, pair[2], level + 1) # print the value
end

# _print a single string
_print(io::IO, str::AbstractString, level::Int=0, ignore_level::Bool=false) =
    if occursin('\n', strip(str)) || occursin('"', str)
        if endswith(str, "\n\n")   # multiple trailing newlines: keep
            println(io, "|+")
            str = str[1:end-1]     # otherwise, we have one too many
        elseif endswith(str, "\n") # one trailing newline: clip
            println(io, "|")
        else                       # no trailing newlines: strip
            println(io, "|-")
        end
        indent = repeat("  ", max(level, 1))
        for line in split(str, "\n")
            println(io, indent, line)
        end
    else
        println(io, repr(MIME("text/plain"), str)) # quote and escape
    end

# handle NaNs and Infs
_print(io::IO, val::Float64, level::Int=0, ignore_level::Bool=false) =
    if isfinite(val)
        println(io, string(val)) # the usual case
    elseif isnan(val)
        println(io, ".NaN") # this is what the YAML parser interprets as NaN
    elseif val == Inf
        println(io, ".inf")
    elseif val == -Inf
        println(io, "-.inf")
    end

_print(io::IO, val::Nothing, level::Int=0, ignore_level::Bool=false) =
    println(io, "~") # this is what the YAML parser interprets as nothing

# _print any other single value
_print(io::IO, val::Any, level::Int=0, ignore_level::Bool=false) =
    println(io, string(val)) # no indentation is required

# add indentation to a string
_indent(str::AbstractString, level::Int, ignore_level::Bool=false) =
    repeat("  ", ignore_level ? 0 : level) * str


text:
"""
    State

Abstract supertype for all sampled states: `state <: State`.

# Examples
## Find all states that may be sampled

```julia-repl
julia> subtypes(State)

6-element Vector{Any}:
Bogoliubov
Coherent
Crescent
Fock
Squeezed
Thermal
```

## Create and sample a particular state (vacuum)

```julia-repl
julia> s = Fock(0)
Fock(0)
julia> wigner(s,100)
┌ Warning: Fock state sampling for W is only valid for n ≫ 1.
```

Here a warning is generated since Fock sampling is not well defined for small `n`.

A simpler way to sample the vacuum is

```julia-repl
julia> s = Coherent(0)
Coherent(0.0 + 0.0im)  # type conversion to ComplexF64.

julia> wigner(s,100)
(ComplexF64[0.33820868828162637 + 0.4407579103538181im, 0.057183146091823775 - 0.2772571883006981im, ...
```
generating two vectors of sampled points `α,α⁺` in the complex plane. In this case, `α = conj(α⁺)`, as we are not working with a doubled phase space.
"""
abstract type State end

"""
    Coherent(β)

Create a coherent state with complex amplitude `β ∈ ℂ`.
"""
struct Coherent <: State
    β::Complex{Float64}
end

"""
    Fock(n)

Create a Fock state for particle number `n ∈ ℕ₀`.
"""
struct Fock <: State
    n::Int64
end

"""
    Crescent(β,ϵ,q)

Create a Cresecent state with parameters `β`, `ϵ`, `q`.
"""
struct Crescent <: State
    β::Complex{Float64}
    ϵ::Complex{Float64}
    q::Float64
end

"""
    Squeezed(β,ϵ)

Create a Squeezed state with parameters `β`, `ϵ`.
"""
struct Squeezed <: State
    β::Complex{Float64}
    ϵ::Complex{Float64}
end

"""
    Thermal(β,n̄)

Create a Thermal state with parameters `β`, `n̄`.
"""
struct Thermal <: State
    β::Complex{Float64}
    n̄::Float64
end

"""
    Bogoliubov(u,v,n̄)

Create a Bogoliubov state with parameters `u`, `v`, `n̄`.
"""
struct Bogoliubov <: State
    u::Complex{Float64}
    v::Complex{Float64}
    n̄::Float64
end


text:
# ============================================================
# Universal Boltzmann Equation
# ============================================================

include("solver_step.jl")


text:
"""parent of StatePoint2D, StatePoint3D"""

abstract type StatePoint <: AbsState end

function gen_collide(q::State, rads::Vector{Float64})::Function where {State<:StatePoint}
    """collision function for point robots"""
    N = length(rads)

    f(q_i_from::State, q_i_to::State, q_j_from::State, q_j_to::State, i::Int64, j::Int64) =
        begin
            return dist(q_i_from, q_i_to, q_j_from, q_j_to) < rads[i] + rads[j]
        end

    f(q_i::State, q_j::State, i::Int64, j::Int64) = begin
        return dist(q_i, q_j) < rads[i] + rads[j]
    end

    f(Q_from::Vector{Node{State}}, Q_to::Vector{Node{State}}) = begin
        for i = 1:N, j = i+1:N
            if f(Q_from[i].q, Q_to[i].q, Q_from[j].q, Q_to[j].q, i, j)
                return true
            end
        end
        return false
    end

    f(Q::Vector{Node{State}}, q_to::State, i::Int64) = begin
        q_from = Q[i].q
        for j = 1:N
            j != i && dist(q_from, q_to, Q[j].q) < rads[i] + rads[j] && return true
        end
        return false
    end

    return f
end


text:
# out3 =#
#    th_weighted_filter_coefficients.m   ver 1.2  October 20, 2012
#
#    Butterworth 6th order
#
function th_weighted_filter_coefficients(f,dt,iband,iflag)
#
## disp(" filter coefficients ");
#
L=6;
#
## freq=f;
#
iflag=iflag*1;
#
a=zeros(4,4);
b=zeros(4,5);
#
#
#*** normalize the frequency ***
#
## disp(" normalize the frequency ");
targ=pi*f*dt;
om=tan(targ);
#
#*** solve for the poles *******
#
## disp(" calculate poles ");
#
s_complex=complex(zeros(2*L,1));
#
for k=1:(2*L)
#
	arg = (2. * k +L-1)*pi/(2. * L);
#
    s_complex[k] = cos(arg) + 1im*sin(arg);
#
end
#
#  plot transfer function magnitude
#
for i=1:200
#
    arg = (i-1)/40.;
#
    h_complex = -real(s_complex[1]) + 1i*( arg - imag(s_complex[1]));
#
    for jk=1:(L-1)
#
        theta_complex = -real(s_complex[jk]) + 1i*( arg - imag(s_complex[jk]));
#
        temp_complex = h_complex*theta_complex;
#
	    h_complex = temp_complex;
#
    end
#
##    x_complex=1./h_complex;
#
##     h_complex=x_complex;
#
##    a1 = freq*arg;
#
##    a2=sqrt( (real(h_complex))^2 + (imag(h_complex))^2 );
#
##    a3 = (a2^2);
#
#    fprintf(pFile[3],"\n #lf #lf #lf", a1, a2, a3);
#
end
#
#*** solve for alpha values ****
#
alpha = 2*real(s_complex);
#
#*** solve for filter coefficients **
#
om2=(om^2);
#
if( iband == 1 )
#
    for k=1:(Int(L/2))
#
        den = om2-alpha[k]*om+1.;
#
	    a[k,1]=0.;
	    a[k,2]=2. * (om2 -1.)/den;
        a[k,3]=(om2 +alpha[k]*om+ 1.)/den;
#
	    b[k,1]=om2/den;
        b[k,2]=2. * b[k,1];
        b[k,3]=b[k,1];
#
    end
#
else
#
    for k=1:(Int(L/2))
#
        den = 1. -alpha[k]*om +om2;
#
	    a[k,1]=0.;
	    a[k,2]=2. * (-1. + om2)/den;
        a[k,3]=( 1. +alpha[k]*om+ om2)/den;
#
	    b[k,1]= 1. / den;
        b[k,2]=-2. * b[k,1];
        b[k,3]=    b[k,1];
    end
#
end
#
#*** check stability ****************
#
als=0.5e-06;
#
als=als*6.;
#
# out3=print("\n stability reference threshold= #14.7e ", als);
## disp(out3);
#
for i=1:Int(L/2)
#
    at1= -a[i,2];
    at2= -a[i,3];
#
    # out3 = print("\n stability coordinates: (#12.7g, #14.7g) ",at1,at2);
##     disp(out3);
#
    h2=at2;
#
    a1=h2-1.;
    d3=at1-a1;
 #
    a1=1. -h2;
    d2=a1-at1;
    d1=at2+1.;
#
    # out3 = print(" d1=#14.5g  d2=#14.5g  d3=#14.5g",d1,d2,d3);
##     disp(out3);
#
    dlit=d1;
#
    if(dlit > d2)
        dlit=d2;
    end
    if(dlit > d3)
        dlit=d3;
    end
#
    # out3 = print("\n stage #ld     dlit= #14.5g ",i, dlit);
##     disp(out3);
#
    if(dlit > als)
##	    disp("  good stability");
    end
    if( (dlit < als) && (dlit > 0.))
##        disp("  marginally unstable ");
    end
    if(dlit < 0.)
        println("  warning: unstable filter ");
        iflag=905;
    end
end
## disp(" ");
# out3 = print(" iflag=#d ",iflag);
## disp(out3);

return (a,b,iflag)
end


text:
# This file was generated, do not modify it. # hide
r1 = range(lgb, :num_iterations, lower=50, upper=100)
r2 = range(lgb, :min_data_in_leaf, lower=2, upper=10)
r3 = range(lgb, :learning_rate, lower=1e-1, upper=1e0)
tm = TunedModel(model=lgb, tuning=Grid(resolution=5),
                resampling=CV(rng=StableRNG(123)), ranges=[r1,r2,r3],
                measure=rms)
mtm = machine(tm, features, targets)
fit!(mtm, rows=train);