text:
#
# Tests depend on a running server at localhost:27017,
# and will create a database named "mongoc".
#
# Start a fresh MongoDB instance with:
#
# ```
# $ mkdir db
# $ mongod --dbpath ./db
# ```
#

import Mongoc

using Test
using Dates

const DB_NAME = "mongoc"

@testset "MongoDB" begin

    client = Mongoc.Client()

    @testset "Destroy" begin
        cli = Mongoc.Client()
        db = cli["database"]
        coll = db["collection"]

        Mongoc.destroy!(coll)
        Mongoc.destroy!(db)
        Mongoc.destroy!(cli)
    end

    @testset "Types" begin
        bson = Mongoc.BSON()
        @test_throws Mongoc.BSONError Mongoc.Client("////invalid-url")

        try
            Mongoc.Client("////invalid-url")
        catch err
            @test isa(err, Mongoc.BSONError)
            io = IOBuffer()
            showerror(io, err)
        end

        @test client.uri == "mongodb://localhost:27017"
        Mongoc.set_appname!(client, "Runtests")
        db = client[DB_NAME]
        coll = db["new_collection"]

        io = IOBuffer()
        show(io, bson)
        show(io, client)
        show(io, db)
        show(io, coll)
        show(io, Mongoc.BSONCode("function() = 1"))
        show(io, Mongoc.QUERY_FLAG_TAILABLE_CURSOR)
    end

    @testset "Connection" begin

        @testset "ping" begin
            bson_ping_result = Mongoc.ping(client)
            @test haskey(bson_ping_result, "ok")
            @test Mongoc.as_json(Mongoc.ping(client)) == """{ "ok" : 1.0 }"""
        end

        @testset "Server Status" begin
            bson_server_status = Mongoc.command_simple(client["admin"], Mongoc.BSON("""{ "serverStatus" : 1 }"""))
            println("Server Mongo Version: ", bson_server_status["version"])
        end

        @testset "error print" begin
            error_happened = false
            try
                Mongoc.command_simple(client["hey"], Mongoc.BSON("""{ "you" : 1 }"""))
            catch e
                println(IOBuffer(), e)
                error_happened = true
            end

            @test error_happened
        end

        @testset "new_collection" begin
            coll = client[DB_NAME]["new_collection"]

            @testset "Insert One with generated OID" begin
                io = IOBuffer()
                result = push!(coll, Mongoc.BSON("""{ "hello" : "world" }"""))
                @test isa(result, Mongoc.InsertOneResult)
                show(io, result)
                @test result.inserted_oid != nothing
                first_inserted_oid = result.inserted_oid
                @test Mongoc.as_json(result.reply) == """{ "insertedCount" : 1 }"""
                result = push!(coll, Mongoc.BSON("""{ "hey" : "you" }"""))
                show(io, result)
                @test result.inserted_oid != nothing
                @test result.inserted_oid != first_inserted_oid
                @test Mongoc.as_json(result.reply) == """{ "insertedCount" : 1 }"""
            end

            @testset "Insert One with custom OID" begin
                io = IOBuffer()
                bson = Mongoc.BSON("_id" => 123, "out" => "there")
                result = push!(coll, bson)
                show(io, result)
                @test result.inserted_oid == nothing
                @test Mongoc.as_json(result.reply) == """{ "insertedCount" : 1 }"""
            end

            bson = Mongoc.BSON()
            bson["hey"] = "you"

            bson["zero_date"] = DateTime(0)
            bson["date_2018"] = DateTime(2018)

            result = push!(coll, bson)
            @test Mongoc.as_json(result.reply) == """{ "insertedCount" : 1 }"""

            i = 0
            for bson in coll
                @test haskey(bson, "hello") || haskey(bson, "hey") || haskey(bson, "out")
                @test haskey(bson, "_id")
                i += 1
            end
            @test i == length(coll)

            i = 0
            for bson in Mongoc.find(coll, Mongoc.BSON("""{ "hello" : "world" }"""))
                i += 1
            end
            @test i == 1

            @testset "collection command_simple" begin
                result = Mongoc.command_simple(coll, Mongoc.BSON("""{ "collStats" : "new_collection" }"""))
                @test result["ok"] == 1
            end

            empty!(coll)
        end

        @testset "find_databases" begin
            found = false
            for obj in Mongoc.find_databases(client)
                if obj["name"] == DB_NAME
                    found = true
                end
            end
            @test found

            @test DB_NAME ∈ Mongoc.get_database_names(client)
        end

        @testset "catch cursor error" begin
            # issue #15
            invalid_client = Mongoc.Client("mongodb://invalid_url")
            collection = invalid_client["db_name"]["collection_name"]
            @test_throws Mongoc.BSONError Mongoc.find_one(collection, Mongoc.BSON(""" { "a" : 1 } """))
        end

        @static if !Sys.iswindows() # skipping binary tests for windows
            @testset "Binary data" begin
                coll = client[DB_NAME]["new_collection"]
                bsonDoc = Mongoc.BSON()
                testdata = rand(UInt8, 100)
                bsonDoc["someId"] = "1234"
                bsonDoc["bindata"] = testdata
                result = push!(coll, bsonDoc)
                @test Mongoc.as_json(result.reply) == """{ "insertedCount" : 1 }"""

                # read data out and confirm
                selector = Mongoc.BSON("""{ "someId": "1234" }""")
                results = Mongoc.find_one(coll,  selector)

                @test results["bindata"] == testdata
            end
        end

        @testset "find_collections" begin
            for obj in Mongoc.find_collections(client["local"])
                @test obj["name"] == "startup_log"
            end

            @test Mongoc.get_collection_names(client["local"]) == [ "startup_log" ]
        end

        @testset "BulkOperation" begin
            coll = client[DB_NAME]["new_collection"]
            bulk_operation = Mongoc.BulkOperation(coll)
            Mongoc.destroy!(bulk_operation)
            bulk_2 = Mongoc.BulkOperation(coll) # will be freed by GC
        end

        @testset "Cleanup" begin
            coll = client[DB_NAME]["new_collection"]
            Mongoc.drop(coll)
        end

        @testset "insert_many" begin
            collection = client[DB_NAME]["insert_many"]
            vector = Vector{Mongoc.BSON}()
            push!(vector, Mongoc.BSON("""{ "hey" : "you" }"""))
            push!(vector, Mongoc.BSON("""{ "out" : "there" }"""))
            push!(vector, Mongoc.BSON("""{ "count" : 3 }"""))

            result = append!(collection, vector)
            @test isa(result, Mongoc.BulkOperationResult)
            @test result.reply["nInserted"] == 3
            for oid in result.inserted_oids
                @test oid != nothing
            end
            io = IOBuffer()
            show(io, result)
            @test length(collection) == 3
            @test length(collect(collection)) == 3

            Mongoc.drop(collection)
        end

        @testset "bulk_replace_one" begin
            collection = client[DB_NAME]["replace_many"]
            push!(collection, Mongoc.BSON("""{ "x": 1, "y": 100 }"""))
            push!(collection, Mongoc.BSON("""{ "x": 2, "y": 200 }"""))
            push!(collection, Mongoc.BSON("""{ "x": 3, "y": 300 }"""))

            bulk = Mongoc.BulkOperation(collection)
            Mongoc.bulk_replace_one!(
                bulk,
                Mongoc.BSON("""{ "x": 1 }"""),
                Mongoc.BSON("""{ "x": 1, "y": -100 }"""),
            )
            Mongoc.bulk_replace_one!(
                bulk,
                Mongoc.BSON("""{ "x": 2 }"""),
                Mongoc.BSON("""{ "x": 2, "y": -200 }"""),
            )
            Mongoc.bulk_replace_one!(
                bulk,
                Mongoc.BSON("""{ "x": 4 }"""),
                Mongoc.BSON("""{ "x": 4, "y": 400 }""");
                options = Mongoc.BSON("""{ "upsert": true }""")
            )
            result = Mongoc.execute!(bulk)
            @test result.reply["nInserted"] == 0
            @test result.reply["nMatched"] == 2
            @test result.reply["nModified"] == 2
            @test result.reply["nUpserted"] == 1
            @test length(collection) == 4
            @test length(collect(collection)) == 4

            Mongoc.drop(collection)
        end

        @testset "delete_one" begin
            collection = client[DB_NAME]["delete_one"]
            doc = Mongoc.BSON("""{ "to" : "delete", "hey" : "you" }""")
            doc2 = Mongoc.BSON("""{ "to" : "keep", "out" : "there" }""")
            insert_result = push!(collection, doc)
            oid = insert_result.inserted_oid
            push!(collection, doc2)

            selector = Mongoc.BSON()
            selector["_id"] = oid
            @test length(collection, selector) == 1
            result = Mongoc.delete_one(collection, selector)
            @test result["deletedCount"] == 1
            @test length(collection, selector) == 0

            Mongoc.drop(collection)
        end

        @testset "delete_many" begin
            collection = client[DB_NAME]["delete_many"]
            result = append!(collection, [ Mongoc.BSON("""{ "first" : 1, "delete" : true }"""), Mongoc.BSON("""{ "second" : 2, "delete" : true }"""), Mongoc.BSON("""{ "third" : 3, "delete" : false }""") ])
            @test length(collection) == 3
            result = Mongoc.delete_many(collection, Mongoc.BSON("""{ "delete" : true }"""))
            @test result["deletedCount"] == 2
            @test length(collection) == 1
            result = Mongoc.delete_many(collection, Mongoc.BSON())
            @test result["deletedCount"] == 1
            @test isempty(collection)
            Mongoc.drop(collection)
        end

        @testset "update_one, update_many" begin
            collection = client[DB_NAME]["update_one"]
            append!(collection, [ Mongoc.BSON("""{ "first" : 1, "delete" : true }"""), Mongoc.BSON("""{ "second" : 2, "delete" : true }"""), Mongoc.BSON("""{ "third" : 3, "delete" : false }""") ])
            @test length(collection) == 3

            selector = Mongoc.BSON("""{ "delete" : false }""")
            update = Mongoc.BSON("""{ "\$set" : { "delete" : true, "new_field" : 1 } }""")
            result = Mongoc.update_one(collection, selector, update)

            @test result["modifiedCount"] == 1
            @test result["matchedCount"] == 1
            @test result["upsertedCount"] == 0

            updated_bson = Mongoc.find_one(collection, Mongoc.BSON("""{ "third" : 3 }"""))
            @test updated_bson != nothing
            @test updated_bson["delete"] == true
            @test updated_bson["new_field"] == 1

            selector = Mongoc.BSON("""{ "delete" : true }""")
            update = Mongoc.BSON("""{ "\$set" : { "delete" : false } }""")
            result = Mongoc.update_many(collection, selector, update)
            @test result["modifiedCount"] == 3
            @test result["matchedCount"] == 3
            @test result["upsertedCount"] == 0

            for doc in Mongoc.find(collection)
                @test doc["delete"] == false
            end

            @test Mongoc.find_one(collection, Mongoc.BSON("""{ "delete" : true }""")) == nothing

            Mongoc.drop(collection)
        end

        @testset "replace_one" begin
            collection = client[DB_NAME]["replace_one"]
            append!(collection, [ Mongoc.BSON("""{ "first" : 1, "delete" : true }"""), Mongoc.BSON("""{ "second" : 2, "delete" : true }"""), Mongoc.BSON("""{ "third" : 3, "delete" : false }""") ])
            @test length(collection) == 3

            selector = Mongoc.BSON("""{ "delete" : false }""")
            replacement = Mongoc.BSON("""{ "third" : 3, "new_field" : 1 }""")
            result = Mongoc.replace_one(collection, selector, replacement)

            @test result["modifiedCount"] == 1
            @test result["matchedCount"] == 1
            @test result["upsertedCount"] == 0

            replaced_bson = Mongoc.find_one(collection, Mongoc.BSON("""{ "third" : 3 }"""))
            @test replaced_bson !== nothing
            @test !haskey(replaced_bson, "delete")
            @test replaced_bson["new_field"] == 1

            Mongoc.drop(collection)
        end

        @testset "aggregation, map_reduce" begin

            @testset "QueryFlags" begin
                qf_composite = Mongoc.QUERY_FLAG_PARTIAL | Mongoc.QUERY_FLAG_NO_CURSOR_TIMEOUT
                @test qf_composite & Mongoc.QUERY_FLAG_PARTIAL == Mongoc.QUERY_FLAG_PARTIAL
                @test qf_composite & Mongoc.QUERY_FLAG_NO_CURSOR_TIMEOUT == Mongoc.QUERY_FLAG_NO_CURSOR_TIMEOUT
            end

            # reproducing the examples at https://docs.mongodb.com/manual/aggregation/
            docs = [
                Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 500, "status" : "A" }"""),
                Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 250, "status" : "A" }"""),
                Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "A" }"""),
                Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 300, "status" : "D" }""")
            ]

            database = client[DB_NAME]
            collection = database["aggregation_example"]
            append!(collection, docs)
            @test length(collection) == 4

            # Aggregation
            let
                bson_pipeline = Mongoc.BSON("""
                    [
                        { "\$match" : { "status" : "A" } },
                        { "\$group" : { "_id" : "\$cust_id", "total" : { "\$sum" : "\$amount" } } }
                    ]""")

                # Response should be
                #   BSON("{ "_id" : "B212", "total" : 200 }")
                #   BSON("{ "_id" : "A123", "total" : 750 }")
                for doc in Mongoc.aggregate(collection, bson_pipeline)
                    if doc["_id"] == "A123"
                        @test doc["total"] == 750
                    elseif doc["_id"] == "B212"
                        @test doc["total"] == 200
                    else
                        # shouldn't get in here
                        @test false
                    end
                end
            end

            # map_reduce
            let
                input_collection_name = "aggregation_example"
                mapper = Mongoc.BSONCode(""" function() { emit( this.cust_id, this.amount ); } """)
                reducer = Mongoc.BSONCode(""" function(key, values) { return Array.sum( values ) } """)
                output_collection_name = "order_totals"
                query = Mongoc.BSON("""{ "status" : "A" }""")

                map_reduce_command = Mongoc.BSON()
                map_reduce_command["mapReduce"] = input_collection_name
                map_reduce_command["map"] = mapper
                map_reduce_command["reduce"] = reducer
                map_reduce_command["out"] = output_collection_name
                map_reduce_command["query"] = query

                result = Mongoc.read_command(database, map_reduce_command)
                @test result["result"] == "order_totals"
                @test result["ok"] == 1.0

                for doc in Mongoc.find(database["order_totals"])
                   if doc["_id"] == "A123"
                        @test doc["value"] == 750
                    elseif doc["_id"] == "B212"
                        @test doc["value"] == 200
                    else
                        # shouldn't get in here
                        @test false
                    end
                end

               # Response should be
               # BSON("{ "_id" : "A123", "value" : 750.0 }")
               # BSON("{ "_id" : "B212", "value" : 200.0 }")
            end

            Mongoc.drop(collection)
        end
    end

    @testset "find and modify" begin
        @testset "create/destroy opts" begin
            opts = Mongoc.FindAndModifyOptsBuilder()
            Mongoc.destroy!(opts)
        end

        @testset "set opts" begin
            opts = Mongoc.FindAndModifyOptsBuilder()
            opts.update = Mongoc.BSON("""{ "\$set" : { "position" : "striker" }}""")
            opts.sort = Mongoc.BSON("""{ "age" : -1 }""")
            opts.fields = Mongoc.BSON("""{ "goals" : 1 }""")
            opts.flags = Mongoc.FIND_AND_MODIFY_FLAG_UPSERT | Mongoc.FIND_AND_MODIFY_FLAG_RETURN_NEW
        end

        @testset "main function" begin
            collection = client[DB_NAME]["find_and_modify"]

            docs = [
                Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 500, "status" : "A" }"""),
                Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 250, "status" : "A" }"""),
                Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "A" }"""),
                Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 300, "status" : "D" }""")
            ]

            append!(collection, docs)

            @testset "update simple" begin
                query = Mongoc.BSON("amount" => 500)

                reply = Mongoc.find_and_modify(
                    collection,
                    query,
                    update = Mongoc.BSON("""{ "\$set" : { "status" : "N" } }"""),
                    flags = Mongoc.FIND_AND_MODIFY_FLAG_RETURN_NEW # will return the new version of the document
                )

                let
                    modified_doc = reply["value"]
                    @test modified_doc["status"] == "N"
                end

                let
                    modified_doc = Mongoc.find_one(collection, Mongoc.BSON("amount" => 500))
                    @test modified_doc["status"] == "N"
                end
            end

            @testset "upsert and return new" begin
                query = Mongoc.BSON("""{ "cust_id" : "C555", "amount" : 10, "status" : "X" }""")

                reply = Mongoc.find_and_modify(
                    collection,
                    query,
                    update = Mongoc.BSON("""{ "\$set" : { "status" : "S" } }"""),
                    flags = Mongoc.FIND_AND_MODIFY_FLAG_UPSERT | Mongoc.FIND_AND_MODIFY_FLAG_RETURN_NEW
                )

                let
                    new_document = reply["value"]
                    @test new_document["cust_id"] == "C555"
                    @test new_document["amount"] == 10
                    @test new_document["status"] == "S"
                end
            end

            @testset "update sorted with selected fields" begin
                query = Mongoc.BSON("""{ "amount" : { "\$lt" : 300 } }""")
                update = Mongoc.BSON("""{ "\$set" : { "status" : "Z" } }""")
                fields = Mongoc.BSON("""{ "amount" : 1, "status" : 1 }""")
                sort = Mongoc.BSON("""{ "amount" : 1 }""")

                reply = Mongoc.find_and_modify(
                    collection,
                    query,
                    update=update,
                    sort=sort,
                    fields=fields,
                    flags=Mongoc.FIND_AND_MODIFY_FLAG_RETURN_NEW)

                let
                    new_document = reply["value"]
                    @test new_document["amount"] == 10
                    @test new_document["status"] == "Z"
                    @test !haskey(new_document, "cust_id")
                end
            end

            Mongoc.drop(collection)
        end
    end

    @testset "find one and delete" begin
        collection = client[DB_NAME]["find_one_and_delete"]

        docs = [
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 500, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 250, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 300, "status" : "D" }""")
        ]

        append!(collection, docs)

        @testset "delete by filter" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")

            doc = Mongoc.find_one_and_delete(collection, query)

            @test !isnothing(doc)
            @test doc["cust_id"] == "B212"
            @test doc["amount"] == 200
        end

        @testset "nothing result when not found" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")

            doc = Mongoc.find_one_and_delete(collection, query)

            @test isnothing(doc)
        end

        @testset "delete with sort" begin
            query = Mongoc.BSON("""{ "cust_id" : "A123" }""")
            options = Mongoc.BSON("""{ "sort" : {"amount" : 1 } }""")

            doc = Mongoc.find_one_and_delete(collection, query, options=options)

            @test !isnothing(doc)
            @test doc["cust_id"] == "A123"
            @test doc["amount"] == 250
        end

        @testset "delete with projection" begin
            query = Mongoc.BSON("""{ "cust_id" : "A123" }""")
            options = Mongoc.BSON("""{ "projection": { "amount" : 0 } }""")

            doc = Mongoc.find_one_and_delete(collection, query, options=options)

            @test !isnothing(doc)
            @test doc["cust_id"] == "A123"
            @test !haskey(doc, "amount")
        end

        Mongoc.drop(collection)
    end

    @testset "find one and replace" begin
        collection = client[DB_NAME]["find_one_and_replace"]

        docs = [
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 500, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 250, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 300, "status" : "D" }""")
        ]

        append!(collection, docs)

        @testset "replace by filter" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")
            replacement = Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "B" }""")

            doc = Mongoc.find_one_and_replace(collection, query, replacement)

            @test doc["cust_id"] == "B212"
            @test doc["amount"] == 200
            # Returns original document
            @test doc["status"] == "A"
        end

        @testset "replace with sort" begin
            query = Mongoc.BSON("""{ "cust_id" : "A123" }""")
            replacement = Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 275, "status" : "B" }""")
            options = Mongoc.BSON("""{ "sort" : {"amount": 1 } }""")

            doc = Mongoc.find_one_and_replace(collection, query, replacement, options=options)

            @test doc["cust_id"] == "A123"
            @test doc["amount"] == 250
            # Returns original document
            @test doc["status"] == "A"
        end

        @testset "return new document" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")
            replacement = Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "C" }""")
            options = Mongoc.BSON("""{ "returnNewDocument" : true }""")

            doc = Mongoc.find_one_and_replace(collection, query, replacement, options=options)

            @test doc["cust_id"] == "B212"
            @test doc["amount"] == 200
            # Returns new document
            @test doc["status"] == "C"
        end

        @testset "returns nothing if it does not exist" begin
            query = Mongoc.BSON("""{ "cust_id" : "C313" }""")
            replacement = Mongoc.BSON("""{ "cust_id" : "C313", "amount" : 400, "status" : "A" }""")

            doc = Mongoc.find_one_and_replace(collection, query, replacement)
            @test isnothing(doc)
        end

        @testset "returns nothing if it does not exist and returning new document" begin
            query = Mongoc.BSON("""{ "cust_id" : "C313" }""")
            replacement = Mongoc.BSON("""{ "cust_id" : "C313", "amount" : 400, "status" : "A" }""")
            options = Mongoc.BSON("""{ "returnNewDocument" : true }""")

            doc = Mongoc.find_one_and_replace(collection, query, replacement, options=options)
            @test isnothing(doc)
        end

        @testset "upsert" begin
            query = Mongoc.BSON("""{ "cust_id" : "C313" }""")
            replacement = Mongoc.BSON("""{ "cust_id" : "C313", "amount" : 400, "status" : "A" }""")
            options = Mongoc.BSON("""{ "upsert" : true }""")

            doc = Mongoc.find_one_and_replace(collection, query, replacement, options=options)
            @test isnothing(doc)

            replacement = Mongoc.BSON("""{ "cust_id" : "C313", "amount" : 400, "status" : "B" }""")
            doc = Mongoc.find_one_and_replace(collection, query, replacement, options=options)
            @test !isnothing(doc)
        end

        @testset "throws if operator in replacement" begin
            query = Mongoc.BSON("""{"cust_id" : "B212"}""")
            replacement = Mongoc.BSON("""{ "\$set" : {"cust_id" : "B212", "amount" : 200, "status" : "C" } }""")

            @test_throws ArgumentError Mongoc.find_one_and_replace(collection, query, replacement)
        end

        Mongoc.drop(collection)
    end

    @testset "find one and update" begin
        collection = client[DB_NAME]["find_one_and_update"]

        docs = [
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 500, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 250, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "A" }"""),
            Mongoc.BSON("""{ "cust_id" : "A123", "amount" : 300, "status" : "D" }""")
        ]

        append!(collection, docs)

        @testset "update by filter" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")
            update = Mongoc.BSON("""{"\$set" : { "status" : "B" } }""")

            doc = Mongoc.find_one_and_update(collection, query, update)

            @test doc["cust_id"] == "B212"
            @test doc["amount"] == 200
            # Returns original document
            @test doc["status"] == "A"
        end

        @testset "update with sort" begin
            query = Mongoc.BSON("""{ "cust_id" : "A123" }""")
            update = Mongoc.BSON("""{ "\$set" : { "status" : "B", "amount" : 275 } }""")
            options = Mongoc.BSON("""{ "sort": {"amount": 1 } }""")

            doc = Mongoc.find_one_and_update(collection, query, update, options=options)

            @test doc["cust_id"] == "A123"
            @test doc["amount"] == 250
            # Returns original document
            @test doc["status"] == "A"
        end

        @testset "return new document" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")
            update = Mongoc.BSON("""{ "\$set" : { "status" : "C" } }""")
            options = Mongoc.BSON("""{ "returnNewDocument" : true}""")

            doc = Mongoc.find_one_and_update(collection, query, update, options=options)

            @test doc["cust_id"] == "B212"
            @test doc["amount"] == 200
            # Returns new document
            @test doc["status"] == "C"
        end

        @testset "returns nothing if it does not exist" begin
            query = Mongoc.BSON("""{ "cust_id" : "C313" }""")
            update = Mongoc.BSON("""{ "\$set" : { "cust_id" : "C313", "amount" : 400, "status" : "A" } }""")

            doc = Mongoc.find_one_and_update(collection, query, update)
            @test isnothing(doc)
        end

        @testset "returns nothing if it does not exist and returning new document" begin
            query = Mongoc.BSON("""{ "cust_id" : "C313" }""")
            update = Mongoc.BSON("""{ "\$set" : { "cust_id" : "C313", "amount" : 400, "status" : "A" } }""")
            options = Mongoc.BSON("""{ "returnNewDocument" : true }""")

            doc = Mongoc.find_one_and_update(collection, query, update, options=options)
            @test isnothing(doc)
        end

        @testset "upsert" begin
            query = Mongoc.BSON("""{ "cust_id" : "C313" }""")
            update = Mongoc.BSON("""{ "\$setOnInsert" : { "cust_id" : "C313", "amount" : 400 }, "\$set" : { "status" : "A" } }""")
            options = Mongoc.BSON("""{ "upsert" : true }""")

            doc = Mongoc.find_one_and_update(collection, query, update, options=options)
            @test isnothing(doc)

            update = Mongoc.BSON("""{ "\$setOnInsert" : { "cust_id" : "C313", "amount" : 400 }, "\$set" : { "status" : "B" } }""")
            doc = Mongoc.find_one_and_update(collection, query, update, options=options)
            @test !isnothing(doc)
        end

        @testset "throws if no operator in update" begin
            query = Mongoc.BSON("""{ "cust_id" : "B212" }""")
            update = Mongoc.BSON("""{ "cust_id" : "B212", "amount" : 200, "status" : "C" }""")

            @test_throws ArgumentError Mongoc.find_one_and_update(collection, query, update)
        end

        Mongoc.drop(collection)
    end

    @testset "command" begin
        database = client[DB_NAME]
        collection_name = "index_collection"
        collection = database[collection_name]

        let
            items = [
                    Mongoc.BSON("_id" => 1, "group" => "g1"),
                    Mongoc.BSON("_id" => 2, "group" => "g1"),
                    Mongoc.BSON("_id" => 3, "group" => "g2")
                ]

            append!(collection, items)
            @test length(collection) == 3
        end

        @testset "database write_command" begin
            create_indexes_cmd = Mongoc.BSON(
                    "createIndexes" => collection_name,
                    "indexes" => [ Mongoc.BSON("key" => Mongoc.BSON("group" => 1), "name" => "group_index") ]
                )
            reply = Mongoc.write_command(database, create_indexes_cmd)
            @test reply["ok"] == 1
        end

        @testset "database read_command" begin
            reply = Mongoc.read_command(client["admin"], Mongoc.BSON("""{ "serverStatus" : 1 }"""))
            @test reply["ok"] == 1
        end

        Mongoc.drop(collection)
    end

    @testset "Users" begin
        # creates admin user - https://docs.mongodb.com/manual/tutorial/enable-authentication/
        @test Mongoc.has_database(client, DB_NAME) # at this point, DB_NAME should exist
        database = client[DB_NAME]

        user_name = "myUser"
        pass = "abc123"
        roles = Mongoc.BSON()

        if Mongoc.has_user(database, user_name)
            Mongoc.remove_user(database, user_name)
        end

        Mongoc.add_user(database, user_name, pass, roles)
        Mongoc.remove_user(database, user_name)
        @test !Mongoc.has_user(database, user_name)
    end

    @testset "Session Options" begin
        opt = Mongoc.SessionOptions()
        @test Mongoc.get_casual_consistency(opt)
        Mongoc.set_casual_consistency!(opt, false)
        @test !Mongoc.get_casual_consistency(opt)
    end

    server_version = Mongoc.get_server_mongodb_version(client)

    if server_version < v"3.6"
        @warn("MongoDB server version $server_version does not support Sessions. Skipping tests.")
    else
        @testset "Session" begin
            session = Mongoc.Session(client)
            db = session[DB_NAME]
            collection = db["session_collection"]
            push!(collection, Mongoc.BSON("""{ "try-insert" : 1 }"""))
            Mongoc.drop(collection)
        end
    end

    @testset "Drop Database" begin
        Mongoc.drop(client[DB_NAME])
    end

    @testset "GridFS" begin
        @testset "Create/Destroy" begin
            db = client[DB_NAME]
            bucket = Mongoc.Bucket(db)
            Mongoc.destroy!(bucket)
        end

        @testset "Stream from filepath" begin
            fp = joinpath(@__DIR__, "replica_set_initiate.js")
            @assert isfile(fp)
            io = Mongoc.MongoStreamFile(fp)
            @test isopen(io)
            Mongoc.close(io)
            @test !isopen(io)
            Mongoc.destroy!(io)
        end

        @testset "Upload/Download/Find/Delete file" begin
            db = client[DB_NAME]
            bucket = Mongoc.Bucket(db)
            local_fp = joinpath(@__DIR__, "replica_set_initiate.js")
            @assert isfile(local_fp)
            original_str = read(local_fp, String)

            remote_filename = "remote_replica_set_initiate.js"

            @testset "Upload" begin
                Mongoc.upload(bucket, remote_filename, local_fp)
            end

            @test !isempty(bucket)

            download_filepath = joinpath(@__DIR__, "tmp_replica_set_initiate.js")

            @testset "Download to file" begin
                try
                    Mongoc.download(bucket, remote_filename, download_filepath)

                    let
                        tmp_str = read(download_filepath, String)
                        @test original_str == tmp_str
                    end
                finally
                    isfile(download_filepath) && rm(download_filepath)
                end
            end

            @testset "transfer_to_buffer!" begin
                @testset "empty buffer" begin
                    buff = UInt8[]
                    pos = 0
                    data = UInt8[1,2,0,0]
                    nr = 2

                    @test Mongoc.nb_free(buff, pos) == 0
                    @test Mongoc.nb_to_fill(buff, pos, nr) == 0
                    @test Mongoc.nb_to_append(buff, pos, nr) == 2
                    Mongoc.transfer_to_buffer!(buff, pos, data, nr)
                    @test buff == UInt8[1,2]
                end

                @testset "increase buffer" begin
                    buff = UInt8[1,2,0,0]
                    pos = 2
                    data = UInt8[3,4,5,6]
                    nr = 3
                    @test Mongoc.nb_free(buff, pos) == 2
                    @test Mongoc.nb_to_fill(buff, pos, nr) == 2
                    @test Mongoc.nb_to_append(buff, pos, nr) == 1
                    Mongoc.transfer_to_buffer!(buff, pos, data, nr)
                    @test buff == UInt8[1,2,3,4,5]
                end

                @testset "big buffer" begin
                    buff = UInt8[1,0,0,0]
                    pos = 1
                    data = UInt8[2,3,4,5]
                    nr = 1
                    Mongoc.transfer_to_buffer!(buff, pos, data, nr)
                    @test buff == UInt8[1,2,0,0]
                end
            end

            @testset "Download to stream" begin
                Mongoc.open_download_stream(bucket, remote_filename) do io
                    @test isopen(io)
                    tmp_str = read(io, String)
                    @test original_str == tmp_str
                end
            end

            @testset "Find and Delete" begin
                cursor = Mongoc.find(bucket)
                found = false
                for doc in cursor
                    @test !found
                    found = true

                    @test doc["filename"] == remote_filename
                    Mongoc.delete(bucket, doc)
                end

                @test isempty(bucket)
            end

            @testset "Upload and Delete with id" begin

                Mongoc.upload(bucket, remote_filename, local_fp, file_id="my_id")

                found = false
                for doc in Mongoc.find(bucket, Mongoc.BSON("_id" => "my_id"))
                    found = true
                end
                @test found

                @test !isempty(bucket)
                empty!(bucket)
                @test isempty(bucket)
            end

            @testset "open upload stream - text" begin
                remote_filename = "uploaded_file.txt"

                io = Mongoc.open_upload_stream(bucket, remote_filename)
                msg = "hey you out there"
                write(io, msg)
                close(io)

                Mongoc.open_download_stream(bucket, remote_filename) do io
                    @test isopen(io)
                    tmp_str = read(io, String)
                    @test msg == tmp_str
                end

                empty!(bucket)
            end

            @testset "open upload stream - bytes" begin
                data = rand(UInt8, 3_000_000)
                remote_filename = "uploaded.data"
                io = Mongoc.open_upload_stream(bucket, remote_filename)
                write(io, data)
                close(io)

                Mongoc.open_download_stream(bucket, remote_filename) do io
                    @test isopen(io)
                    downloaded_data = read(io)
                    @test downloaded_data == data
                end

                empty!(bucket)
            end

            @testset "upload abort" begin
                remote_filename = "uploaded_file.txt"

                io = Mongoc.open_upload_stream(bucket, remote_filename)
                msg = "hey you out there"
                write(io, msg)
                Mongoc.abort_upload(io)
                close(io)
                @test isempty(bucket)
            end
        end
    end
end


text:
module toggleThatSwapBlock

using ..Ahorn, Maple

@mapdef Entity "FrostHelper/ToggleSwapBlock" ToggleSwapBlock(x1::Integer, y1::Integer, x2::Integer=x1+16, y2::Integer=y1, width::Integer=16, height::Integer=16, directory::String="objects/swapblock", speed::Integer=360, renderBG::Bool=false, moveSFX::String="event:/game/05_mirror_temple/swapblock_move", moveEndSFX::String="event:/game/05_mirror_temple/swapblock_move_end")

function swapFinalizer(entity)
    x, y = Ahorn.position(entity)

    width = Int(get(entity.data, "width", 8))
    height = Int(get(entity.data, "height", 8))

    entity.data["nodes"] = [(x + width, y)]
end

const placements = Ahorn.PlacementDict(
    "Toggle Swap Block (Frost Helper)" => Ahorn.EntityPlacement(
        ToggleSwapBlock,
        "rectangle",
        Dict{String, Any}(),
        swapFinalizer
    )
)

Ahorn.nodeLimits(entity::ToggleSwapBlock) = 1, 1

Ahorn.minimumSize(entity::ToggleSwapBlock) = 16, 16
Ahorn.resizable(entity::ToggleSwapBlock) = true, true

function Ahorn.selection(entity::ToggleSwapBlock)
    x, y = Ahorn.position(entity)
    stopX, stopY = Int.(entity.data["nodes"][1])

    width = Int(get(entity.data, "width", 8))
    height = Int(get(entity.data, "height", 8))

    return [Ahorn.Rectangle(x, y, width, height), Ahorn.Rectangle(stopX, stopY, width, height)]
end

frame = "objects/swapblock/blockRed"
trailFrame = "objects/swapblock/target"
midResource = "objects/swapblock/midBlockRed00"

function renderTrail(ctx, x::Number, y::Number, width::Number, height::Number)
    tilesWidth = div(width, 8)
    tilesHeight = div(height, 8)

    for i in 2:tilesWidth - 1
        Ahorn.drawImage(ctx, trailFrame, x + (i - 1) * 8, y + 2, 6, 0, 8, 6)
        Ahorn.drawImage(ctx, trailFrame, x + (i - 1) * 8, y + height - 8, 6, 14, 8, 6)
    end

    for i in 2:tilesHeight - 1
        Ahorn.drawImage(ctx, trailFrame, x + 2, y + (i - 1) * 8, 0, 6, 6, 8)
        Ahorn.drawImage(ctx, trailFrame, x + width - 8, y + (i - 1) * 8, 14, 6, 6, 8)
    end

    for i in 2:tilesWidth - 1, j in 2:tilesHeight - 1
        Ahorn.drawImage(ctx, trailFrame, x + (i - 1) * 8, y + (j - 1) * 8, 6, 6, 8, 8)
    end

    Ahorn.drawImage(ctx, trailFrame, x + width - 8, y + 2, 14, 0, 6, 6)
    Ahorn.drawImage(ctx, trailFrame, x + width - 8, y + height - 8, 14, 14, 6, 6)
    Ahorn.drawImage(ctx, trailFrame, x + 2, y + 2, 0, 0, 6, 6)
    Ahorn.drawImage(ctx, trailFrame, x + 2, y + height - 8, 0, 14, 6, 6)
end

function renderSwapBlock(ctx::Ahorn.Cairo.CairoContext, x::Number, y::Number, width::Number, height::Number)
    midSprite = Ahorn.getSprite(midResource, "Gameplay")

    tilesWidth = div(width, 8)
    tilesHeight = div(height, 8)

    for i in 2:tilesWidth - 1
        Ahorn.drawImage(ctx, frame, x + (i - 1) * 8, y, 8, 0, 8, 8)
        Ahorn.drawImage(ctx, frame, x + (i - 1) * 8, y + height - 8, 8, 16, 8, 8)
    end

    for i in 2:tilesHeight - 1
        Ahorn.drawImage(ctx, frame, x, y + (i - 1) * 8, 0, 8, 8, 8)
        Ahorn.drawImage(ctx, frame, x + width - 8, y + (i - 1) * 8, 16, 8, 8, 8)
    end

    for i in 2:tilesWidth - 1, j in 2:tilesHeight - 1
        Ahorn.drawImage(ctx, frame, x + (i - 1) * 8, y + (j - 1) * 8, 8, 8, 8, 8)
    end

    Ahorn.drawImage(ctx, frame, x, y, 0, 0, 8, 8)
    Ahorn.drawImage(ctx, frame, x + width - 8, y, 16, 0, 8, 8)
    Ahorn.drawImage(ctx, frame, x, y + height - 8, 0, 16, 8, 8)
    Ahorn.drawImage(ctx, frame, x + width - 8, y + height - 8, 16, 16, 8, 8)

    Ahorn.drawImage(ctx, midSprite, x + div(width - midSprite.width, 2), y + div(height - midSprite.height, 2))
end

function Ahorn.renderSelectedAbs(ctx::Ahorn.Cairo.CairoContext, entity::ToggleSwapBlock, room::Maple.Room)
    sprite = get(entity.data, "sprite", "block")
    startX, startY = Int(entity.data["x"]), Int(entity.data["y"])
    stopX, stopY = Int.(entity.data["nodes"][1])

    width = Int(get(entity.data, "width", 32))
    height = Int(get(entity.data, "height", 32))

    renderSwapBlock(ctx, stopX, stopY, width, height)
    Ahorn.drawArrow(ctx, startX + width / 2, startY + height / 2, stopX + width / 2, stopY + height / 2, Ahorn.colors.selection_selected_fc, headLength=6)
end

function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::ToggleSwapBlock, room::Maple.Room)
    sprite = get(entity.data, "sprite", "block")

    startX, startY = Int(entity.data["x"]), Int(entity.data["y"])
    stopX, stopY = Int.(entity.data["nodes"][1])

    width = Int(get(entity.data, "width", 32))
    height = Int(get(entity.data, "height", 32))

    renderTrail(ctx, min(startX, stopX), min(startY, stopY), abs(startX - stopX) + width, abs(startY - stopY) + height)
    renderSwapBlock(ctx, startX, startY, width, height)
end

end

ext: jl

max_stars_repo_name: JaThePlayer/FrostHelper

max_issues_repo_name: JaThePlayer/FrostHelper

max_forks_repo_name: JaThePlayer/FrostHelper


text:
# Using Clenshaw's method to evaulate tensor-product Chebyshev polynomials

@generated function clenshaw_recursion(weights::Array{T,N},x::T) where {T,N}

  first_term = :( p = Array{T}(undef,Base.tail(size(weights))) )

  i_vars = Array{Symbol}(undef,N)
  for i = 1:N
    i_vars[i] = Symbol("i$i")
  end

  inner_term = :( z = zeros(T,size(weights,1)+2);
                  for $(i_vars[1]) in size(weights,1):-1:1;
                    z[$(i_vars[1])] = weights[$(i_vars...)]+2*x*z[$(i_vars[1])+1]-z[$(i_vars[1])+2];
                  end;
                  p[$(i_vars[2:N]...)] = z[1]-x*z[2]
                  )

  outer_term = inner_term
  for i = N:-1:2
    outer_term = :( for $(i_vars[i]) = 1:size(weights,$i);
                      $outer_term;
                    end
                    )
  end

  final = :( $first_term;
             $outer_term;
             return p
             )

  return final

end

function clenshaw_evaluate(weights::Array{T,N},x::Array{T,1},domain=[ones(T,1,N);-ones(T,1,N)]) where {T <: AbstractFloat,N}

  for i = 1:N
    normalized_x = normalize_node(x[i],domain[:,i])
    weights = clenshaw_recursion(weights,normalized_x)
  end

  return weights[1]

end

function clenshaw_evaluate(weights::Array{T,N},domain=[ones(T,1,N);-ones(T,1,N)]) where {T <: AbstractFloat,N}

  function goo(x::Array{T,1}) where {T <: AbstractFloat}

    return clenshaw_evaluate(weights,x,domain)

  end

  return goo

end

max_issues_repo_name: RJDennis/ChebyshevApprox

max_forks_repo_name: RJDennis/ChebyshevApprox


text:
using QuasiCopula, LinearAlgebra, Random, GLM
using DataFrames, Statistics
using BenchmarkTools, Test

BLAS.set_num_threads(1)
Threads.nthreads()

p = 3    # number of fixed effects, including intercept
m = 1    # number of variance components
# true parameter values
#   βtrue = ones(p)
Random.seed!(12345)
# try next
βtrue = rand(Uniform(-2, 2), p)
θtrue = [0.5]

d = Poisson()
link = LogLink()
D = typeof(d)
Link = typeof(link)
T = Float64

samplesize = 10000
ni = 25

gcs = Vector{GLMCopulaVCObs{T, D, Link}}(undef, samplesize)

Γ = θtrue[1] * ones(ni, ni)

# for reproducibility I will simulate all the design matrices here
Random.seed!(12345)
X_samplesize = [randn(ni, p - 1) for i in 1:samplesize]

for i in 1:samplesize
    X = [ones(ni) X_samplesize[i]]
    η = X * βtrue
    μ = exp.(η)
    vecd = Vector{DiscreteUnivariateDistribution}(undef, ni)
    for i in 1:ni
        vecd[i] = Poisson(μ[i])
    end
    nonmixed_multivariate_dist = NonMixedMultivariateDistribution(vecd, Γ)
    # simuate single vector y
    y = Vector{Float64}(undef, ni)
    res = Vector{Float64}(undef, ni)
    rand(nonmixed_multivariate_dist, y, res)
    V = [ones(ni, ni)]
    gcs[i] = GLMCopulaVCObs(y, X, V, d, link)
end

gcm = GLMCopulaVCModel(gcs)
# precompile
println("precompiling Poisson VCM fit")
gcm2 = deepcopy(gcm);
QuasiCopula.fit!(gcm2, IpoptSolver(print_level = 0, max_iter = 20));

fittime = @elapsed QuasiCopula.fit!(gcm, IpoptSolver(print_level = 5, max_iter = 100, tol = 10^-8, limited_memory_max_history = 50, accept_after_max_steps = 4, hessian_approximation = "limited-memory"))
@show fittime
@show gcm.β
@show gcm.θ
@show gcm.∇β
@show gcm.∇θ

loglikelihood!(gcm, true, true)
vcov!(gcm)
@show QuasiCopula.confint(gcm)
# mse and time under our model
mseβ, mseθ = MSE(gcm, βtrue, θtrue)
@show mseβ
@show mseθ

@test mseβ < 0.01
@test mseθ < 0.01

println("checking memory allocation for Poisson VCM")
logl_gradient_memory = @benchmark loglikelihood!($gcm.data[1], $gcm.β, $gcm.θ, true, false)
# logl_gradient_memory = @benchmark loglikelihood!($gcm, true, false)
@test logl_gradient_memory.memory == 0.0


text:
@testset "FunctionGraph" begin
    @jsf foo(t) = t^2+2t+1
    fg = functiongraph(foo, a=1, b=5, strokeColor="blue")
    @test fg isa J.FunctionGraph
    @test fg.f.name == :foo
    @test fg.a == 1
    @test fg.b == 5
    @test fg.opts[:strokeColor] == "blue"

    # str
    brd = board("brd")
    sfg = J.str(fg, brd)
    @test occursin("function foo(t){return (Math.pow(t,2)+(2*t)+1)};", sfg)
    @test occursin("""brd.create('functiongraph', [function(t){return foo(t);}, 1, 5], {"strokeColor":"blue"});""", sfg)
end

@testset "ParamCurve" begin
    @jsf f1(t) = t - sin(t)
    @jsf f2(t) = 1 - cos(t)
    pc = parametriccurve(f1, f2; a=0, b=10, dash=2)
    @test pc isa J.Curve
    @test pc.x isa J.JSFun
    @test pc.y isa J.JSFun
    @test pc.a isa Real
    @test pc.b isa Real
    @test pc.opts[:dash] == 2
    pc2 = pcurve(f1,f2)
    @test isnothing(pc2.opts)
    @test pc2.a == -10
    @test pc2.b == 10

    # str
    b = board("b")
    spc = J.str(pc, b)
    @test occursin("function f1(t){return (t-sin(t))};function f2(t){return (1-cos(t))};", spc)
    @test occursin("""b.create('curve', [function(t){return f1(t);}, function(t){return f2(t);}, 0, 10], {"dash":2});""", spc)
end

@testset "DataPlot" begin
    x = [1,2,3]
    y = [1,2,3]
    dp = dataplot(x, y)
    @test dp.x == [1,2,3]
    @test dp.y == [1,2,3]
    @test isnothing(dp.opts)
    x = [1,2]
    @test_throws DimensionMismatch dataplot(x, y)

    # str
    b = board("b")
    sdp = J.str(dp, b)
    @test sdp == "b.create('curve', [[1,2,3], [1,2,3]], {});"
end

@testset "plot" begin
    # plot(fun opts...)
    @jsf f1(t) = t - sin(t)
    p = plot(f1; strokeColor="blue")
    @test p isa J.FunctionGraph
    sp = J.str(p, board("b", xlim=[-5,5]))
    @test occursin("function f1(t){return (t-sin(t))};", sp)
    @test occursin("""b.create('functiongraph', [function(t){return f1(t);}, -5, 5], {"strokeColor":"blue"});""", sp)

    # plot fun, fun
    @jsf f2(t) = cos(t)
    p = plot(f1, f2; a=0, b=10)
    @test p isa J.ParametricCurve
    @test p.x == f1
    @test p.y == f2
    @test p.a == 0
    @test p.b == 10

    # plot arr, fun
    p = plot(range(0, 1, length=10), f2)
    @test p isa J.DataPlot
    @test p.x == range(0, 1, length=10)
    @test p.y == f2
end


text:
# Autogenerated wrapper script for H2AgModel_jll for x86_64-linux-gnu-libgfortran3
export h2ag111_friction, h2ag111_pes

using CompilerSupportLibraries_jll
JLLWrappers.@generate_wrapper_header("H2AgModel")
JLLWrappers.@declare_library_product(h2ag111_friction, "h2ag111_friction.so")
JLLWrappers.@declare_library_product(h2ag111_pes, "h2ag111_pes.so")
function __init__()
    JLLWrappers.@generate_init_header(CompilerSupportLibraries_jll)
    JLLWrappers.@init_library_product(
        h2ag111_friction,
        "lib/h2ag111_friction.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_library_product(
        h2ag111_pes,
        "lib/h2ag111_pes.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text: @cdef :PyIter_Next PyPtr (PyPtr,)


text:
# we write an improved version of binarySearch that evaluates func fewer times
# and checks if there is definitely a root in the initial interval
function binarySearchV2(func, low, high, tol)

  # we now also store the values of func at low and high
  f_low = func(low)
  f_high = func(high)

  # we check if the initial interval definitely contains a root
  if f_low * f_high > 0
      error("func(low) and func(high) must have different sign")
  end

  # the while loop is similar to before
  while abs(high - low)/2 > tol * abs(low + high)/2
    mid = (low + high)/2

    # we only have one evaluation of func per loop
    f_mid = func(mid)

    if f_high * f_mid > 0
        high = mid
        f_high = f_mid
        # in this case f_low stays the same
    else
        low = mid
        f_low = f_mid
        # in this case f_high stays the same
    end
  end

  return (low + high)/2
end

max_stars_repo_path: 1a/Root Finding/binarySearchV2.jl

max_issues_repo_path: 1a/Root Finding/binarySearchV2.jl

max_forks_repo_path: 1a/Root Finding/binarySearchV2.jl


text:
using SafeTestsets

@safetestset "Binary trend tests" begin include("binary_trend.jl") end


text:
using LinearAlgebra
using SparseArrays
using Plots

m = 10
x = LinRange(0,1,m+2) # easier to define eigs on [0,1]
xint = x[2:end-1]
h = x[2]-x[1]
A = (1/h^2) * spdiagm(0=>2*ones(m),-1=>-ones(m-1),1=>-ones(m-1))

λ,V = eigen(Matrix(A))
# scatter(xint,V[:,1])

function normalize_cols!(A)
    for i = 1:size(A,2)
        A[:,i] /= maximum(A[:,i])
    end
end
normalize_cols!(V)

λex = @. 2/h^2 * (1-cos((1:m)*pi*h))
Vex = hcat((sin.(k*pi*xint) for k = 1:m)...)
normalize_cols!(Vex)

# plot(xint,V[:,1] .- Vex[:,1])
# scatter(λ - λex)


text:
#= Fornberg algorithm

Implements the Fornberg (1988) algorithm
(https://doi.org/10.1090/S0025-5718-1988-0935077-0), adapted from the
DiffEqOperators module.
=#
"""
    calculate_weights(m, n, s)

Return finite difference weights. Notation follows that of Fornberg, used in
Mathematica as well:
https://reference.wolfram.com/language/tutorial/NDSolveMethodOfLines.html

# Arguments
* `m::Int`: order of the derivative
* `n::Int`: number of grid intervals enclosed in the stencil
* `s::Int`: number of grid intervals between the point at which the derivative
            is approximated and the leftmost edge of the stencil. centred
            formulas always have s=n/2.
"""
function calculate_weights(m::Int, n::Int, s::Int)
    stencil_length = n + 1

    # dummy array with the relative coordinates of the stencil (eg. central
    # differences need coordinates centred at 0)
    x  = -s : (stencil_length - s - 1)
    # point in the array 'x' for which we need the coefficients
    x0 = x[1] + s

    N = length(x)
    @assert m < N "Not enough points for the requested order."

    c1 = 1
    c4 = x[1] - x0
    C = zeros(Rational{Int}, N, m+1)
    C[1,1] = 1
    @inbounds for i in 1:N-1
        i1 = i + 1
        mn = Base.min(i, m)
        c2 = 1
        c5 = c4
        c4 = x[i1] - x0
        for j in 0:i-1
            j1 = j + 1
            c3 = x[i1] - x[j1]
            c2 *= c3
            if j == i-1
                for s in mn:-1:1
                    s1 = s + 1
                    C[i1,s1] = c1*(s*C[i,s] - c5*C[i,s1]) // c2
                end
                C[i1,1] = -c1*c5*C[i,1] // c2
           end
            for s in mn:-1:1
                s1 = s + 1
                C[j1,s1] = (c4*C[j1,s1] - s*C[j1,s]) // c3
            end
            C[j1,1] = c4 * C[j1,1] // c3
        end
        c1 = c2
    end

    #=
    Fix the problem of numerical instability which occurs when the sum of the
    stencil_coefficients is not exactly 0:
https://scicomp.stackexchange.com/questions/11249/numerical-derivative-and-finite-difference-coefficients-any-update-of-the-fornb

    Stack Overflow answer on this issue:
    http://epubs.siam.org/doi/pdf/10.1137/S0036144596322507 - Modified Fornberg Algorithm
    =#

    _C = C[:,end]
    _C[div(N,2)+1] -= sum(_C)
    return _C
end


text:
# fft_convolve.jl

using BenchmarkTools: @btime
using SPECTrecon: plan_psf
using SPECTrecon: fft_conv!, fft_conv_adj!

function fft_conv_time()
    M = 200
    N = 64
    T = Float32
    img = zeros(T, M, N)
    img[20:150, 20:40] .= rand(131,21)
    output = similar(img)
    nx_psf = 5
    ker = ones(T, nx_psf, nx_psf) / nx_psf^2
    plan = plan_psf(M, N, nx_psf; nthread = 1, T = T)[1]

    println("fft_conv")
    @btime fft_conv!($output, $img, $ker, $plan)
    # 565.631 μs (0 allocations: 0 bytes)
    println("fft_conv_adj")
    @btime fft_conv_adj!($output, $img, $ker, $plan)
    # 561.371 μs (0 allocations: 0 bytes)
    nothing
end

# run all functions, time may vary on different machines, but should be all zero allocation.
fft_conv_time()


text:
using SteamTables
using Unitful
using Test

mysignif(x, n) = round(x; sigdigits = n)
function mysignif(x::Q, n::Int) where Q <: Quantity
    y = Quantity(round(x.val, sigdigits = n), unit(x))
    return y
end

const TestDigits = 6 # number of significant digits to test selected functions to

@testset "Region 1, forwards equations for P and T              " begin
    include("testreg1.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 1, backwards equations for P and h             " begin
    include("testreg1Ph.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 1, backwards equations for P and s             " begin
    include("testreg1Ps.jl")
end
@testset "Region 2, forwards equations for P and T              " begin
    include("testreg2.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 2a, backwards equations for P and h            " begin
    include("testreg2aPh.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 2b, backwards equations for P and h            " begin
    include("testreg2bPh.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 2c, backwards equations for P and h            " begin
    include("testreg2cPh.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 2a, backwards equations for P and s            " begin
    include("testreg2aPs.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
#@test mysignif(SpecificG(8.0,  0.600_484_040E3), TestDigits)  ≈ mysignif(SpecificG_Ps(8.0,  6.0), TestDigits)
@testset "Region 2b, backwards equations for P and s            " begin
    include("testreg2bPs.jl")
end

# The free energies have lower consistency between the forward and backwards equations. Check to fewer significant digits.
@testset "Region 2c, backwards equations for P and s            " begin
    include("testreg2cPs.jl")
end

# Region 3 is specified in terms of density rather than pressure. The utility functions fix this by solving
# for the pressure. This does introduce some small error, which means we should check to fewer significant digits.
# For consistency the checks here are done to the same number of digits as for the free energies, although the
# accuracy here will be better.
@testset "Region 3, forwards equations for P and T              " begin
    include("testreg3.jl")
end

@testset "Region 4 - saturation pressure from temperature       " begin
    include("testreg4T.jl")
end

@testset "Region 4 - saturation temperature from pressure       " begin
    include("testreg4P.jl")
end

@testset "Region 5 - forwards equations for P and T             " begin
    include("testreg5.jl")
end


text:
### Generic interface ###

# Arrays
mmap_array{T,N}(::Type{T}, dims::NTuple{N,Int}, s::IO) = mmap_array(T, dims, s, position(s))

msync{T}(A::Array{T}) = msync(pointer(A), length(A)*sizeof(T))

# BitArrays
mmap_bitarray{N}(::Type{Bool}, dims::NTuple{N,Int}, s::IOStream, offset::FileOffset) =
    mmap_bitarray(dims, s, offset)
mmap_bitarray{N}(::Type{Bool}, dims::NTuple{N,Int}, s::IOStream) = mmap_bitarray(dims, s, position(s))
mmap_bitarray{N}(dims::NTuple{N,Int}, s::IOStream) = mmap_bitarray(dims, s, position(s))

msync(B::BitArray) = msync(pointer(B.chunks), length(B.chunks)*sizeof(Uint64))

### UNIX implementation ###

@unix_only begin
# Low-level routines
# These are needed for things like MAP_ANONYMOUS
function mmap(len::Integer, prot::Integer, flags::Integer, fd, offset::Integer)
    const pagesize::Int = ccall(:jl_getpagesize, Clong, ())
    # Check that none of the computations will overflow
    if len > typemax(Int)-pagesize
        error("requested size is too large")
    end
    # Set the offset to a page boundary
    offset_page::FileOffset = ifloor(offset/pagesize)*pagesize
    len_page::Int = (offset-offset_page) + len
    # Mmap the file
    p = ccall(:jl_mmap, Ptr{Void}, (Ptr{Void}, Csize_t, Cint, Cint, Cint, FileOffset), C_NULL, len_page, prot, flags, fd, offset_page)
    systemerror("memory mapping failed", int(p) == -1)
    # Also return a pointer that compensates for any adjustment in the offset
    return p, int(offset-offset_page)
end

# Before mapping, grow the file to sufficient size
# (Required if you're going to write to a new memory-mapped file)
#
# Note: a few mappable streams do not support lseek. When Julia
# supports structures in ccall, switch to fstat.
function mmap_grow(len::Integer, prot::Integer, flags::Integer, fd::Integer, offset::FileOffset)
    const SEEK_SET::Cint = 0
    const SEEK_CUR::Cint = 1
    const SEEK_END::Cint = 2
    # Save current file position so we can restore it later
    cpos = ccall(:jl_lseek, FileOffset, (Cint, FileOffset, Cint), fd, 0, SEEK_CUR)
    systemerror("lseek", cpos < 0)
    filelen = ccall(:jl_lseek, FileOffset, (Cint, FileOffset, Cint), fd, 0, SEEK_END)
    systemerror("lseek", filelen < 0)
    if (filelen < offset + len)
        systemerror("pwrite", ccall(:jl_pwrite, Cssize_t, (Cint, Ptr{Void}, Uint, FileOffset), fd, int8([0]), 1, offset + len - 1) < 1)
    end
    cpos = ccall(:jl_lseek, FileOffset, (Cint, FileOffset, Cint), fd, cpos, SEEK_SET)
    systemerror("lseek", cpos < 0)
    return mmap(len, prot, flags, fd, offset)
end

function munmap(p::Ptr,len::Integer)
    systemerror("munmap", ccall(:munmap,Cint,(Ptr{Void},Int),p,len) != 0)
end

const MS_ASYNC = 1
const MS_INVALIDATE = 2
const MS_SYNC = 4
function msync(p::Ptr, len::Integer, flags::Integer)
    systemerror("msync", ccall(:msync, Cint, (Ptr{Void}, Csize_t, Cint), p, len, flags) != 0)
end
msync(p::Ptr, len::Integer) = msync(p, len, MS_SYNC)

# Higher-level functions
# Determine a stream's read/write mode, and return prot & flags
# appropriate for mmap
# We could use isreadonly here, but it's worth checking that it's readable too
function mmap_stream_settings(s::IO)
    const PROT_READ::Cint = 1
    const PROT_WRITE::Cint = 2
    const MAP_SHARED::Cint = 1
    const F_GETFL::Cint = 3
    mode = ccall(:fcntl,Cint,(Cint,Cint),fd(s),F_GETFL)
    systemerror("fcntl F_GETFL", mode == -1)
    mode = mode & 3
    if mode == 0
        prot = PROT_READ
    elseif mode == 1
        prot = PROT_WRITE
    else
        prot = PROT_READ | PROT_WRITE
    end
    if prot & PROT_READ == 0
        error("mmap requires read permissions on the file (choose r+)")
    end
    flags = MAP_SHARED
    return prot, flags, (prot & PROT_WRITE) > 0
end

# Mmapped-array constructor
function mmap_array{T,N,TInt<:Integer}(::Type{T}, dims::NTuple{N,TInt}, s::IO, offset::FileOffset; grow::Bool=true)
    prot, flags, iswrite = mmap_stream_settings(s)
    len = prod(dims)*sizeof(T)
    if len > typemax(Int)
        error("file is too large to memory-map on this platform")
    end
    if iswrite && grow
        pmap, delta = mmap_grow(len, prot, flags, fd(s), offset)
    else
        pmap, delta = mmap(len, prot, flags, fd(s), offset)
    end
    A = pointer_to_array(pointer(T, uint(pmap)+delta), dims)
    finalizer(A,x->munmap(pmap,len+delta))
    return A
end

end

### Windows implementation ###
@windows_only begin
# Mmapped-array constructor
function mmap_array{T,N,TInt<:Integer}(::Type{T}, dims::NTuple{N,TInt}, s::IO, offset::FileOffset)
    shandle = _get_osfhandle(RawFD(fd(s)))
    if int(shandle.handle) == -1
        error("could not get handle for file to map")
    end
    ro = isreadonly(s)
    flprotect = ro ? 0x02 : 0x04
    len = prod(dims)*sizeof(T)
    if len > typemax(Int)
        error("file is too large to memory-map on this platform")
    end
    szarray = convert(Csize_t, len)
    szfile = szarray + convert(Csize_t, offset)
    mmaphandle = ccall(:CreateFileMappingA, stdcall, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Cint, Cint, Cint, Ptr{Void}), shandle.handle, C_NULL, flprotect, szfile>>32, szfile&0xffffffff, C_NULL)
    if mmaphandle == C_NULL
        error("could not create file mapping")
    end
    access = ro ? 4 : 2
    viewhandle = ccall(:MapViewOfFile, stdcall, Ptr{Void}, (Ptr{Void}, Cint, Cint, Cint, Csize_t), mmaphandle, access, offset>>32, offset&0xffffffff, szarray)
    if viewhandle == C_NULL
        error("could not create mapping view")
    end
    A = pointer_to_array(pointer(T, viewhandle), dims)
    finalizer(A, x->munmap(viewhandle, mmaphandle))
    return A
end

function munmap(viewhandle::Ptr, mmaphandle::Ptr)
    status = bool(ccall(:UnmapViewOfFile, stdcall, Cint, (Ptr{Void},), viewhandle))
    status |= bool(ccall(:CloseHandle, stdcall, Cint, (Ptr{Void},), mmaphandle))
    if !status
        error("could not unmap view")
    end
end

function msync(p::Ptr, len::Integer)
    status = bool(ccall(:FlushViewOfFile, stdcall, Cint, (Ptr{Void}, Csize_t), p, len))
    if !status
        error("could not msync")
    end
end

end

# Mmapped-bitarray constructor
function mmap_bitarray{N,TInt<:Integer}(dims::NTuple{N,TInt}, s::IOStream, offset::FileOffset)
    iswrite = !isreadonly(s)
    n = 1
    for d in dims
        if d < 0
            error("invalid dimension size")
        end
        n *= d
    end
    nc = num_bit_chunks(n)
    if nc > typemax(Int)
        error("file is too large to memory-map on this platform")
    end
    chunks = mmap_array(Uint64, (nc,), s, offset)
    if iswrite
        chunks[end] &= @_msk_end n
    else
        if chunks[end] != chunks[end] & @_msk_end n
            error("the given file does not contain a valid BitArray of size ", join(dims, 'x'), " (open with \"r+\" mode to override)")
        end
    end
    B = BitArray{N}(ntuple(N,i->0)...)
    B.chunks = chunks
    B.len = n
    if N != 1
        B.dims = dims
    end
    return B
end

max_stars_repo_name: Maple-Wang/julia

max_issues_repo_name: Maple-Wang/julia

max_forks_repo_name: Maple-Wang/julia


text:
using Test
using Quiqbox: tryIncluding, @compareLength, hasBoolRelation, markUnique, flatten,
               alignNumSign, symbolReplace, splitTerm, groupedSort, mapPermute, Pf, itself
using Quiqbox
using Symbolics
using Suppressor: @capture_out

@testset "Tools.jl" begin

    # function tryIncluding
    local isIncluded
    errStr = @capture_out begin isIncluded = tryIncluding("someMod") end
    @test isIncluded == false
    pkgDir = @__DIR__
    @test length(errStr) > length(@capture_out tryIncluding("someMod", subModulePath=""))

    # macro @compareLength
    @test try @compareLength [1] [1,2] "a" "b"; catch; true end

    # function hasBoolRelation
    @test  hasBoolRelation(===, 1, 1) == (1 === 1)
    @test !hasBoolRelation(===, [1,2], [1,2])
    @test  hasBoolRelation(===, [1,2], [1,2], decomposeNumberCollection=true)
    @test !hasBoolRelation(===, [1,2], (1,2), decomposeNumberCollection=true)
    @test  hasBoolRelation(===, [1,2], (1,2), decomposeNumberCollection=true,
                           ignoreContainer=true)
    @test !hasBoolRelation(===, [1 x->x^2], [1 x->abs(x)])
    @test  hasBoolRelation(===, [1 x->x^2], [1 x->abs(x)], ignoreFunction=true)

    # function markUnique
    @test markUnique([1,3,2,2,5]) == ([1,2,3,3,4], [1,3,2,5])

    # function flatten
    @test [(1,2), 3, [3,4]] |> flatten == [1,2,3,3,4]

    # function alignNumSign
    @test alignNumSign(-1) == "-1"
    @test alignNumSign( 1) == " 1"

    # function symbolReplace
    @test symbolReplace(:sombol, "o"=>"y", count=1) == :symbol

    # function splitTerm
    Symbolics.@variables X Y Z
    vec0 = splitTerm(Num(1))
    @test ( string.(vec0) .== string.([Num(1)]) ) |> prod
    vec1 = splitTerm(X)
    @test ( string.(vec1) .== string.([X]) ) |> prod
    vec2 = splitTerm(X^2)
    @test ( string.(vec2) .== string.([X^2]) ) |> prod
    vec3 = splitTerm(X*Y*Z)
    @test ( string.(vec3) .== string.([X*Y*Z]) ) |> prod
    vec4 = splitTerm(X^2 - X*Y - Z^2)
    @test ( string.(vec4) .== string.([X^2, -(Z^2), -X*Y]) ) |> prod
    @test ([vec0, vec1, vec2, vec3, vec4] .|> length) == [1,1,1,1,3]
    @test ([vec0, vec1, vec2, vec3, vec4] |> eltype) ==  Vector{Num}

    # function groupedSort
    a = [rand(1:5, 2) for i=1:20]
    a2 = groupedSort(a)
    pushfirst!(a2, [[0,0]])
    for i in 2:length(a2)
        if length(a2[i]) > 1
            @test hasEqual(a2[i]...)
        end
        @test a2[i][1][1] >= a2[i-1][1][1]
    end

    # function mapPermute
    bl1 = true
    bl2 = true
    bl3 = true
    mapPool = [x->x^2, abs, x->-x]
    for i=1:10
        arr = rand(50)
        bs1 = genBasisFunc.([[rand(1:2), rand(1:3), rand(1:3)] for i=1:20],
                               [(rand(0.5:0.5:2.5), rand(-0.1:0.2:0.5)) for i=1:20])
        bs2 = genBasisFunc.([[rand(1:2), rand(1:3), rand(1:3)] for i=1:20],
                            [GaussFunc(   genExponent(rand( 0.5:0.5:2.5),
                                                      mapPool[rand(1:3)]),
                                       genContraction(rand(-0.1:0.2:0.5),
                                                      mapPool[rand(1:3)])) for i=1:20])
        bl1 *= (sortperm(arr) == mapPermute(arr, sort))
        bl2 *= hasIdentical(bs1[mapPermute(bs1, sortBasisFuncs)], sortBasisFuncs(bs1))
        bl3 *= hasIdentical(bs2[mapPermute(bs2, sortBasisFuncs)], sortBasisFuncs(bs2))
    end
    @test bl1
    @test bl2
    @test bl3

    # struct Pf
    @test Pf(-1.5, abs)(-2) == -3.0
    @test Pf(-1.0, Pf(-1.5, abs))(-2) == 3.0
    @test Pf(1.5, Val(:abs))(-2) == 3.0
    @test Pf(-1.0, Val(Pf{-1.5, :abs}))(-2) == 3.0
    @test typeof(Pf(-1.5, abs))(-2) == -3.0

    @test Pf(-1.0, Pf(-1.5, itself))(-2) == -3.0
    @test Pf(1.5, Val(:itself))(-2) == -3.0
    @test Pf(-1.0, Val(Pf{-1.5, :itself}))(-2) == -3.0
    @test typeof(Pf(-1.5, itself))(-2) == 3.0
end


text:
# # Run some GitForge function, warning on error but still returning the value.
macro gf(ex::Expr)
    quote
        let result = $(esc(ex))
            GitForge.exception(result) === nothing ||
                @warn "API request failed" exception=GitForge.exception(result)
            GitForge.value(result)
        end
    end
end

# Split a repo path into its owner and name.
function splitrepo(url::AbstractString)
    pieces = split(HTTP.URI(url).path, "/"; keepempty=false)
    owner = join(pieces[1:end-1], "/")
    name = pieces[end]
    return owner, name
end

# Look up a repository.
getrepo(::GitLabAPI, owner::AbstractString, name::AbstractString) =
    @gf get_repo(PROVIDERS["gitlab"].client, owner, name)
getrepo(f::GitHubAPI, owner::AbstractString, name::AbstractString) =
    @gf get_repo(f, owner, name)

# Check for a user's authorization to release a package.
# The criteria is simply whether the user is a collaborator for user-owned repos,
# or whether they're an organization member or collaborator for organization-owned repos.
isauthorized(u, repo) = false
function isauthorized(u::User{GitHub.User}, repo::GitHub.Repo)
    repo.private && return false
    hasauth = if repo.organization === nothing
        @gf is_collaborator(u.forge, repo.owner.login, repo.name, u.user.login)
    else
        # First check for organization membership, and fall back to collaborator status.
        ismember = @gf is_member(u.forge, repo.organization.login, u.user.login)
        something(ismember, false) ||
            @gf is_collaborator(u.forge, repo.organization.login, repo.name, u.user.login)
    end
    return something(hasauth, false)
end

function isauthorized(u::User{GitLab.User}, repo::GitLab.Project)
    repo.visibility == "private" && return false
    forge = PROVIDERS["gitlab"].client
    hasauth = if repo.namespace.kind == "user"
        @gf is_collaborator(forge, repo.owner.username, repo.name, u.user.id)
    else
        # Same as above: group membership then collaborator check.
        ismember = @gf is_member(forge, repo.namespace.full_path, u.user.id)
        something(ismember, false) ||
            @gf is_collaborator(u.forge, repo.organization.login, repo.name, u.user.id)
    end
    return something(hasauth, false)
end

# Get the raw Project.toml text from a repository.
function gettoml(f::GitHubAPI, repo::GitHub.Repo, ref::AbstractString)
    fc = @gf get_file_contents(f, repo.owner.login, repo.name, "Project.toml"; ref=ref)
    return fc === nothing ? nothing : String(base64decode(strip(fc.content)))
end

function gettoml(::GitLabAPI, repo::GitLab.Project, ref::AbstractString)
    forge = PROVIDERS["gitlab"].client
    fc = @gf get_file_contents(forge, repo.id, "Project.toml"; ref=ref)
    return fc === nothing ? nothing : String(base64decode(fc.content))
end

function getcommithash(f::GitHubAPI, repo::GitHub.Repo, ref::AbstractString)
    commit = @gf get_commit(f, repo.owner.login, repo.name, ref)
    return commit === nothing ? nothing : commit.sha
end

function getcommithash(f::GitLabAPI, repo::GitLab.Project, ref::AbstractString)
    forge = PROVIDERS["gitlab"].client
    commit = @gf get_commit(forge, repo.id, ref)
    return commit === nothing ? nothing : commit.id
end

# Get a repo's clone URL.
cloneurl(r::GitHub.Repo) = r.clone_url
cloneurl(r::GitLab.Project) = r.http_url_to_repo

# Get a repo's tree hash.
function gettreesha(f::GitHubAPI, r::GitHub.Repo, ref::AbstractString)
    branch = @gf get_branch(f, r.owner.login, r.name, ref)
    return branch === nothing ? nothing : branch.commit.commit.tree.sha
end

function gettreesha(::GitLabAPI, r::GitLab.Project, ref::AbstractString)
    url = cloneurl(r)

    if REGISTRY[] isa Registry{GitLabAPI}
        # For private repositories, we need to insert the token into the URL.
        host = HTTP.URI(url).host
        token = CONFIG["gitlab"]["token"]
        url = replace(url, host => "oauth2:$token@$host")
    end

    return try
        mktempdir() do dir
            dest = joinpath(dir, r.name)
            run(`git clone $url $dest`)
            match(r"tree (.*)", readchomp(`git -C $dest show $ref --format=raw`))[1]
        end
    catch ex
        println(get_backtrace(ex))
        @debug "Exception while getting tree SHA"
        nothing
    end
end

function ensure_already_exists(f::Function, resp::HTTP.Response, status::Int)
    resp.status == status || return false
    data = JSON.parse(String(copy(resp.body)))
    any(e -> occursin("already exists", e), f(data))
end

"""
    make_registration_request(
        registry::Registry{F},
        branch::AbstractString,
        title::AbstractString,
        body::AbstractString,
    ) where F <: GitForge.Forge
Try to create a pull request. If pull request already exists update the title and body.

Parameters:
- `registry`: The registry to create/update the pull request on
- `branch`: The head of the pull request
- `title`
- `body`

Returns:
A GitForge.Result object
"""
make_registration_request

function make_registration_request(
    r::Registry{GitLabAPI},
    branch::AbstractString,
    title::AbstractString,
    body::AbstractString,
)
    repoid = r.repo.id
    base = r.repo.default_branch
    result = create_pull_request(
        r.forge, repoid;
        source_branch=branch,
        target_branch=base,
        title=title,
        description=body,
        remove_source_branch=true,
    )
    ex = GitForge.exception(result)
    ex === nothing && return result
    resp = GitForge.response(result)
    if !ensure_already_exists(data -> get(data, "message", String[]), resp, 409)
        @error "Exception making registration request" repoid=repoid base=base head=branch
        return result
    end

    prs = get_pull_requests(r.forge, repoid; source_branch=branch, target_branch=base, state="opened")
    val = GitForge.value(prs)
    @assert length(val) == 1
    prid = first(val).iid
    return update_pull_request(r.forge, repoid, prid; title=title, body=body)
end

function make_registration_request(
    r::Registry{GitHubAPI},
    branch::AbstractString,
    title::AbstractString,
    body::AbstractString,
)
    owner = r.repo.owner.login
    repo = r.repo.name
    base = r.repo.default_branch
    result = create_pull_request(
        r.forge, owner, repo;
        head=branch,
        base=base,
        title=title,
        body=body,
    )
    ex = GitForge.exception(result)
    ex === nothing && return result
    resp = GitForge.response(result)
    exists = ensure_already_exists(resp, 422) do data
        map(e -> get(e, "message", ""), get(data, "errors", []))
    end
    if !exists
        @error "Exception making registration request" owner=owner repo=repo base=base head=branch
        return result
    end

    prs = get_pull_requests(r.forge, owner, repo; head="$owner:$branch", base=base, state="open")
    val = GitForge.value(prs)
    @assert length(val) == 1
    prid = first(val).number
    return update_pull_request(r.forge, owner, repo, prid; title=title, body=body)
end

# Get the web URL of various Git things.
web_url(pr::GitHub.PullRequest) = pr.html_url
web_url(mr::GitLab.MergeRequest) = mr.web_url
web_url(u::GitHub.User) = u.html_url
web_url(u::GitLab.User) = u.web_url
web_url(r::GitHub.Repo) = r.html_url
web_url(r::GitLab.Project) = r.web_url

# Get a user's @ mention.
mention(u::GitHub.User) = "@$(u.login)"
mention(u::GitLab.User) = "@$(u.username)"

# Get a user's representation for a registry PR.
# If the registry is from the same provider, mention the user, otherwise use the URL.
display_user(u::U) where U =
    (parentmodule(typeof(REGISTRY[].repo)) === parentmodule(U) ? mention : web_url)(u)


text:
import MKL
using SafeTestsets: @safetestset

@time @safetestset "layers" begin include("layers.jl") end
@time @safetestset "affine" begin include("affine.jl") end
@time @safetestset "binary_white_rbm" begin include("binary_white_rbm.jl") end


text:
check_radius(r) = r < 0 && throw(ArgumentError("the query radius r must be ≧ 0"))

"""
    inrange(tree::NNTree, points, radius [, sortres=false]) -> indices

Find all the points in the tree which is closer than `radius` to `points`. If
`sortres = true` the resulting indices are sorted.
"""
function inrange(tree::NNTree,
                 points::Vector{T},
                 radius::Number,
                 sortres=false) where {T <: AbstractVector}
    check_input(tree, points)
    check_radius(radius)

    idxs = [Vector{Int}() for _ in 1:length(points)]

    for i in 1:length(points)
        inrange_point!(tree, points[i], radius, sortres, idxs[i])
    end
    return idxs
end

function inrange_point!(tree, point, radius, sortres, idx)
    _inrange(tree, point, radius, idx)
    if tree.reordered
        @inbounds for j in 1:length(idx)
            idx[j] = tree.indices[idx[j]]
        end
    end
    sortres && sort!(idx)
    return
end

function inrange(tree::NNTree{V}, point::AbstractVector{T}, radius::Number, sortres=false) where {V, T <: Number}
    check_input(tree, point)
    check_radius(radius)
    idx = Int[]
    inrange_point!(tree, point, radius, sortres, idx)
    return idx
end

function inrange(tree::NNTree{V}, point::AbstractMatrix{T}, radius::Number, sortres=false) where {V, T <: Number}
    dim = size(point, 1)
    npoints = size(point, 2)
    if isbitstype(T)
        new_data = copy_svec(T, point, Val(dim))
    else
        new_data = SVector{dim,T}[SVector{dim,T}(point[:, i]) for i in 1:npoints]
    end
    inrange(tree, new_data, radius, sortres)
end


text:
include("load.jl")
TestFunctionRunnerTests.runtests()


text:
include("libieeep1788_tests_bool.jl")
include("libieeep1788_tests_cancel.jl")
include("libieeep1788_tests_elem.jl")
include("libieeep1788_tests_mul_rev.jl")
include("libieeep1788_tests_num.jl")
include("libieeep1788_tests_overlap.jl")
include("libieeep1788_tests_rec_bool.jl")
include("libieeep1788_tests_rev.jl")
include("libieeep1788_tests_set.jl")


text:
# This file is a part of BAT.jl, licensed under the MIT License (MIT).

"""
    abstract type ENSBound

*Experimental feature, not part of stable public API.*

Abstract type for the bounds of the sampling region used by EllipsoidalNestedSampling.
"""
abstract type ENSBound end

"""
    struct BAT.ENSNoBounds <: ENSBound

*Experimental feature, not part of stable public API.*

No bounds means that the whole volume from the unit Cube is used to find new points.
"""
struct ENSNoBounds <: ENSBound end

"""
    struct BAT.ENSEllipsoidBound <: ENSBound

*Experimental feature, not part of stable public API.*

Ellipsoid bound means that a n-dimensional ellipsoid limits the sampling volume.
"""
struct ENSEllipsoidBound <: ENSBound end

"""
    struct BAT.ENSMultiEllipsoidBound <: ENSBound

*Experimental feature, not part of stable public API.*

Multi ellipsoid bound means that there are multiple elliposid in an optimal clustering are used to limit the sampling volume.
"""
struct ENSMultiEllipsoidBound <: ENSBound end

function ENSBounding(bound::ENSNoBounds)
    return Bounds.NoBounds
end

function ENSBounding(bound::ENSEllipsoidBound)
    return Bounds.Ellipsoid
end

function ENSBounding(bound::ENSMultiEllipsoidBound)
    return Bounds.MultiEllipsoid
end

function ENSBounding(bound::ENSBound) # If nothing ist choosen
    return Bounds.Ellipsoid           # the bound is Ellipsoid
end


text:
using HDF5

fn = joinpath(tempdir(),"test.h5")

fid = h5open(fn, "w")
g = g_create(fid, "shoe")
d = d_create(g, "foo", datatype(Float64), ((10,20),(100,200)), "chunk", (1,1))
#println("d is size current $(map(int,HDF5.get_dims(d)[1])) max $(map(int,HDF5.get_dims(d)[2]))")
dims, max_dims = HDF5.get_dims(d)
@assert dims==(uint64(10),uint64(20))
@assert max_dims == (uint64(100),uint64(200))
set_dims!(d, (100,150))
dims, max_dims = HDF5.get_dims(d)
@assert dims==(uint64(100),uint64(150))
@assert max_dims == (uint64(100),uint64(200))
d[1,1:5]=[1.1231,1.313,5.123,2.231,4.1231]
set_dims!(d, (1,5))
@assert size(d) == (1,5)
#println("d is size current $(map(int,HDF5.get_dims(d)[1])) max $(map(int,HDF5.get_dims(d)[2]))")
b = d_create(fid, "b", Int, ((1000,),(-1,)), "chunk", (100,)) #-1 is equivalent to typemax(Hsize) as far as I can tell
#println("b is size current $(map(int,HDF5.get_dims(b)[1])) max $(map(int,HDF5.get_dims(b)[2]))")
b[1:200] = ones(200)
dims, max_dims = HDF5.get_dims(b)
@assert dims == (uint64(1000),)
@assert max_dims == (HDF5.MAXIMUM_DIM,)
set_dims!(b, (10000,))
dims, max_dims = HDF5.get_dims(b)
@assert dims == (uint64(10000),)
@assert max_dims == (HDF5.MAXIMUM_DIM,)
#println("b is size current $(map(int,HDF5.get_dims(b)[1])) max $(map(int,HDF5.get_dims(b)[2]))")
# b[:] = [1:10000] # gave error no method endof(HDF5Dataset{PlainHDF5File},),
# so I defined endof(dset::HDF5Dataset) = length(dset), and exported endof
# but that didn't fix the error, despite the endof function working
# d[1] produces error ERROR: Wrong number of indices supplied, should datasets support linear indexing?
b[1:10000] = [1:10000]
#println(b[1:100])

close(fid)

fid = h5open(fn, "r")
d_again = fid["shoe/foo"]
dims, max_dims = HDF5.get_dims(d_again)
@assert dims==(uint64(1),uint64(5))
@assert max_dims == (uint64(100),uint64(200))
@assert (sum(d_again[1,1:5])-sum([1.1231,1.313,5.123,2.231,4.1231])) == 0
#println("d is size current $(map(int,HDF5.get_dims(re_d)[1])) max $(map(int,HDF5.get_dims(re_d)[2]))")
@assert fid["b"][1:10000] == [1:10000]
b_again = fid["b"]
dims, max_dims = HDF5.get_dims(b_again)
@assert dims == (uint64(10000),)
@assert max_dims == (HDF5.MAXIMUM_DIM,)
#println("b is size current $(map(int,HDF5.get_dims(b)[1])) max $(map(int,HDF5.get_dims(b)[2]))")

close(fid)


text:
"""
    ribbon(x, y, yerror)

Plots a filled area centered along the line specified
by `x` and `y`, with thickness specified by `error`.
"""
@recipe(Ribbon) do scene
    Theme(;
        default_theme(scene, Band)...,
        color = theme(scene, :color),
        fillalpha = 0.2
    )
end

_get(t::Tuple, i) = t[i]
_get(t, i) = t

function _get_broadcast(y, t, i)
    v = _get(t, i)
    err = v isa AbstractVector ? _get.(v, i) : fill!(similar(y), v)
    y .+ (-1)^i .* err
end

function plot!(p::Ribbon)
    x, y = p[1:2]
    yerr = p[3]
    ylow = lift(_get_broadcast, y, yerr, Node(1))
    yhigh = lift(_get_broadcast, y, yerr, Node(2))

    theme = copy(Theme(p))
    theme[:color] = lift(combine_color_alpha, Theme(p)[:color], Theme(p)[:fillalpha])
    plot!(p, Band, theme, x, ylow, yhigh)
end

max_stars_repo_name: piever/StatMakie

max_issues_repo_name: piever/StatMakie

max_forks_repo_name: piever/StatMakie


text:
__precompile__(true)

# SimpleAiboWebAPI

module SimpleAiboWebAPI

# Basic APIs

include("basic.jl")

# Advanced APIs

include("advanced.jl")

end


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

mutable struct ApplicationGatewayPropertiesFormat <: SwaggerModel
    sku::Any # spec type: Union{ Nothing, ApplicationGatewaySku } # spec name: sku
    sslPolicy::Any # spec type: Union{ Nothing, ApplicationGatewaySslPolicy } # spec name: sslPolicy
    operationalState::Any # spec type: Union{ Nothing, String } # spec name: operationalState
    gatewayIPConfigurations::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayIPConfiguration} } # spec name: gatewayIPConfigurations
    authenticationCertificates::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayAuthenticationCertificate} } # spec name: authenticationCertificates
    sslCertificates::Any # spec type: Union{ Nothing, Vector{ApplicationGatewaySslCertificate} } # spec name: sslCertificates
    frontendIPConfigurations::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayFrontendIPConfiguration} } # spec name: frontendIPConfigurations
    frontendPorts::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayFrontendPort} } # spec name: frontendPorts
    probes::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayProbe} } # spec name: probes
    backendAddressPools::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayBackendAddressPool} } # spec name: backendAddressPools
    backendHttpSettingsCollection::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayBackendHttpSettings} } # spec name: backendHttpSettingsCollection
    httpListeners::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayHttpListener} } # spec name: httpListeners
    urlPathMaps::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayUrlPathMap} } # spec name: urlPathMaps
    requestRoutingRules::Any # spec type: Union{ Nothing, Vector{ApplicationGatewayRequestRoutingRule} } # spec name: requestRoutingRules
    webApplicationFirewallConfiguration::Any # spec type: Union{ Nothing, ApplicationGatewayWebApplicationFirewallConfiguration } # spec name: webApplicationFirewallConfiguration
    resourceGuid::Any # spec type: Union{ Nothing, String } # spec name: resourceGuid
    provisioningState::Any # spec type: Union{ Nothing, String } # spec name: provisioningState

    function ApplicationGatewayPropertiesFormat(;sku=nothing, sslPolicy=nothing, operationalState=nothing, gatewayIPConfigurations=nothing, authenticationCertificates=nothing, sslCertificates=nothing, frontendIPConfigurations=nothing, frontendPorts=nothing, probes=nothing, backendAddressPools=nothing, backendHttpSettingsCollection=nothing, httpListeners=nothing, urlPathMaps=nothing, requestRoutingRules=nothing, webApplicationFirewallConfiguration=nothing, resourceGuid=nothing, provisioningState=nothing)
        o = new()
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("sku"), sku)
        setfield!(o, Symbol("sku"), sku)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("sslPolicy"), sslPolicy)
        setfield!(o, Symbol("sslPolicy"), sslPolicy)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("operationalState"), operationalState)
        setfield!(o, Symbol("operationalState"), operationalState)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("gatewayIPConfigurations"), gatewayIPConfigurations)
        setfield!(o, Symbol("gatewayIPConfigurations"), gatewayIPConfigurations)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("authenticationCertificates"), authenticationCertificates)
        setfield!(o, Symbol("authenticationCertificates"), authenticationCertificates)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("sslCertificates"), sslCertificates)
        setfield!(o, Symbol("sslCertificates"), sslCertificates)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("frontendIPConfigurations"), frontendIPConfigurations)
        setfield!(o, Symbol("frontendIPConfigurations"), frontendIPConfigurations)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("frontendPorts"), frontendPorts)
        setfield!(o, Symbol("frontendPorts"), frontendPorts)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("probes"), probes)
        setfield!(o, Symbol("probes"), probes)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("backendAddressPools"), backendAddressPools)
        setfield!(o, Symbol("backendAddressPools"), backendAddressPools)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("backendHttpSettingsCollection"), backendHttpSettingsCollection)
        setfield!(o, Symbol("backendHttpSettingsCollection"), backendHttpSettingsCollection)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("httpListeners"), httpListeners)
        setfield!(o, Symbol("httpListeners"), httpListeners)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("urlPathMaps"), urlPathMaps)
        setfield!(o, Symbol("urlPathMaps"), urlPathMaps)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("requestRoutingRules"), requestRoutingRules)
        setfield!(o, Symbol("requestRoutingRules"), requestRoutingRules)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("webApplicationFirewallConfiguration"), webApplicationFirewallConfiguration)
        setfield!(o, Symbol("webApplicationFirewallConfiguration"), webApplicationFirewallConfiguration)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("resourceGuid"), resourceGuid)
        setfield!(o, Symbol("resourceGuid"), resourceGuid)
        validate_property(ApplicationGatewayPropertiesFormat, Symbol("provisioningState"), provisioningState)
        setfield!(o, Symbol("provisioningState"), provisioningState)
        o
    end
end # type ApplicationGatewayPropertiesFormat

const _property_map_ApplicationGatewayPropertiesFormat = Dict{Symbol,Symbol}(Symbol("sku")=>Symbol("sku"), Symbol("sslPolicy")=>Symbol("sslPolicy"), Symbol("operationalState")=>Symbol("operationalState"), Symbol("gatewayIPConfigurations")=>Symbol("gatewayIPConfigurations"), Symbol("authenticationCertificates")=>Symbol("authenticationCertificates"), Symbol("sslCertificates")=>Symbol("sslCertificates"), Symbol("frontendIPConfigurations")=>Symbol("frontendIPConfigurations"), Symbol("frontendPorts")=>Symbol("frontendPorts"), Symbol("probes")=>Symbol("probes"), Symbol("backendAddressPools")=>Symbol("backendAddressPools"), Symbol("backendHttpSettingsCollection")=>Symbol("backendHttpSettingsCollection"), Symbol("httpListeners")=>Symbol("httpListeners"), Symbol("urlPathMaps")=>Symbol("urlPathMaps"), Symbol("requestRoutingRules")=>Symbol("requestRoutingRules"), Symbol("webApplicationFirewallConfiguration")=>Symbol("webApplicationFirewallConfiguration"), Symbol("resourceGuid")=>Symbol("resourceGuid"), Symbol("provisioningState")=>Symbol("provisioningState"))
const _property_types_ApplicationGatewayPropertiesFormat = Dict{Symbol,String}(Symbol("sku")=>"ApplicationGatewaySku", Symbol("sslPolicy")=>"ApplicationGatewaySslPolicy", Symbol("operationalState")=>"String", Symbol("gatewayIPConfigurations")=>"Vector{ApplicationGatewayIPConfiguration}", Symbol("authenticationCertificates")=>"Vector{ApplicationGatewayAuthenticationCertificate}", Symbol("sslCertificates")=>"Vector{ApplicationGatewaySslCertificate}", Symbol("frontendIPConfigurations")=>"Vector{ApplicationGatewayFrontendIPConfiguration}", Symbol("frontendPorts")=>"Vector{ApplicationGatewayFrontendPort}", Symbol("probes")=>"Vector{ApplicationGatewayProbe}", Symbol("backendAddressPools")=>"Vector{ApplicationGatewayBackendAddressPool}", Symbol("backendHttpSettingsCollection")=>"Vector{ApplicationGatewayBackendHttpSettings}", Symbol("httpListeners")=>"Vector{ApplicationGatewayHttpListener}", Symbol("urlPathMaps")=>"Vector{ApplicationGatewayUrlPathMap}", Symbol("requestRoutingRules")=>"Vector{ApplicationGatewayRequestRoutingRule}", Symbol("webApplicationFirewallConfiguration")=>"ApplicationGatewayWebApplicationFirewallConfiguration", Symbol("resourceGuid")=>"String", Symbol("provisioningState")=>"String")
Base.propertynames(::Type{ ApplicationGatewayPropertiesFormat }) = collect(keys(_property_map_ApplicationGatewayPropertiesFormat))
Swagger.property_type(::Type{ ApplicationGatewayPropertiesFormat }, name::Symbol) = Union{Nothing,eval(Meta.parse(_property_types_ApplicationGatewayPropertiesFormat[name]))}
Swagger.field_name(::Type{ ApplicationGatewayPropertiesFormat }, property_name::Symbol) =  _property_map_ApplicationGatewayPropertiesFormat[property_name]

const _allowed_ApplicationGatewayPropertiesFormat_operationalState = ["Stopped", "Starting", "Running", "Stopping"]

function check_required(o::ApplicationGatewayPropertiesFormat)
    true
end

function validate_property(::Type{ ApplicationGatewayPropertiesFormat }, name::Symbol, val)
    if name === Symbol("operationalState")
        Swagger.validate_param(name, "ApplicationGatewayPropertiesFormat", :enum, val, _allowed_ApplicationGatewayPropertiesFormat_operationalState)
    end
end


text:
include("./src/game.jl")

print(Game())


text:
#=
This file is auto-generated. Do not edit.
=#
"""
    mutable struct Match <: Edit
        on::Regex
        input::Symbol
        output::Array{Symbol,1}
    end

Extract values from the specified column into a column or columns based on the specified regular expression.

# Arguments
- `on::Regex`: string indicating where to split
- `input::Symbol`: column to split
- `output::Array{Symbol,1}`: column names to label text surrounding the split
"""
mutable struct Match <: Edit
    "string indicating where to split"
    on::Regex
    "column to split"
    input::Symbol
    "column names to label text surrounding the split"
    output::Array{Symbol,1}
end

function Match(; on, input, output, )
    Match(on, input, output, )
end

"""Get [`Match`](@ref) `on`."""
get_on(value::Match) = value.on
"""Get [`Match`](@ref) `input`."""
get_input(value::Match) = value.input
"""Get [`Match`](@ref) `output`."""
get_output(value::Match) = value.output

"""Set [`Match`](@ref) `on`."""
set_on!(value::Match, val) = value.on = val
"""Set [`Match`](@ref) `input`."""
set_input!(value::Match, val) = value.input = val
"""Set [`Match`](@ref) `output`."""
set_output!(value::Match, val) = value.output = val

max_stars_repo_name: matbesancon/SLiDE

max_issues_repo_name: matbesancon/SLiDE

max_forks_repo_name: matbesancon/SLiDE


text:
macro CSI_str(str)
    return :(string("\x1b[", $(esc(str)), "m"))
end

const TYPE_COLOR = CSI"36"
const NO_COLOR = CSI"0"
issparse(H::AbstractHamiltonian) = typeof(H) <: AbstractSparseHamiltonian

"""
    function unit_scale(u)

Determine the value of ``1/ħ``. Return ``2π`` if `u` is `:h`; and return 1 if `u` is `:ħ`.
"""
function unit_scale(u)
    if u == :h
        return 2π
    elseif u == :ħ
        return 1
    else
        throw(ArgumentError("The unit can only be :h or :ħ."))
    end
end

"""
    function allequal(x; rtol = 1e-6, atol = 1e-6)

Check if all elements in `x` are equal upto an absolute error tolerance `atol` and relative error tolerance `rtol`.
"""
@inline function allequal(x; rtol=1e-6, atol=1e-6)
    length(x) < 2 && return true
    e1 = x[1]
    i = 2
    @inbounds for i = 2:length(x)
        isapprox(x[i], e1, rtol=rtol, atol=atol) || return false
    end
    return true
end

function numargs(f)
    numparam = maximum([num_types_in_tuple(m.sig) for m in methods(f)])
    return (numparam - 1) # -1 in v0.5 since it adds f as the first parameter
end

function num_types_in_tuple(sig)
    length(sig.parameters)
end

function num_types_in_tuple(sig::UnionAll)
    length(Base.unwrap_unionall(sig).parameters)
end

"""
$(TYPEDEF)

A statistical ensemble that is equivalent to a density matrix ρ.

# Fields

$(FIELDS)
"""
struct EᵨEnsemble
    "The weights for each state vector"
    ω::Vector
    "The states vectors in the ensemble"
    vec::Vector
    function EᵨEnsemble(ω::Vector, vec::Vector)
        if !(eltype(ω) <: Number && all((x) -> x >= 0, ω))
            throw(ArgumentError("Weights vector ω must be 1-d array of positive numbers."))
        end
        if !(eltype(vec) <: Vector)
            throw(ArgumentError("vec must be 1-d array of vectors."))
        end
        new(ω, vec)
    end
end

sample_state_vector(Eᵨ::EᵨEnsemble) = sample(Eᵨ.vec, Weights(Eᵨ.ω))

"""
$(TYPEDEF)

A container for a matrix whose elements are the same function. Getting any indices of this type returns the same function.

$(FIELDS)
"""
struct SingleFunctionMatrix
    "Internal function"
    fun::Any
end
@inline Base.getindex(F::SingleFunctionMatrix, ind...) = F.fun

"""
$(SIGNATURES)

Convert bloch sphere angle `θ` and `ϕ` to the corresponding state vector according to ``cos(θ/2)|0⟩+exp(iϕ)sin(θ/2)|1⟩``.
"""
function bloch_to_state(θ::Real, ϕ::Real)
    if !(0<=θ<=π)
        throw(ArgumentError("θ is out of range 0≤θ≤π."))
    end
    if !(0<=ϕ<=2π)
        throw(ArgumentError("ϕ is out of range 0≤ϕ≤2π."))
    end
    cos(θ / 2) * PauliVec[3][1] + exp(1.0im * ϕ) * sin(θ / 2) * PauliVec[3][2]
end


text:
@testset "GLGM06 algorithm: homogeneous" begin

    # one-dimensional
    prob, _ = exponential_1d()
    sol = solve(prob, T=5.0, GLGM06(δ=0.01))
    @test isa(sol.alg, GLGM06)
    @test setrep(sol) <: Zonotope
    @test setrep(sol) == Zonotope{Float64,Array{Float64,1},Array{Float64,2}}
    @test dim(sol) == 1

    # higher-dimensional homogeneous
    prob, _ = linear5D_homog()
    sol = solve(prob, T=5.0, GLGM06(δ=0.01))
    @test dim(sol) == 5

    # static option
    sol = solve(prob, T=5.0, GLGM06(δ=0.01, static=true))
    ZS = Zonotope{Float64, SArray{Tuple{5},Float64,1,5}, SArray{Tuple{5,5},Float64,2,25}}
    @test setrep(sol) == ZS

    # use approx model for "discrete-time" reachability
    sol = solve(prob, T=5.0, GLGM06(δ=0.01, approx_model=NoBloating()))

end

@testset "GLGM06 algorithm: inhomogeneous" begin
    # five-dim inhomogeneous
    prob, _ = linear5D()
    sol = solve(prob, T=5.0, GLGM06(δ=0.01))
    @test dim(sol) == 5
    @test tspan(shift(sol, 1.0)) == tspan(sol) + 1.0

    # use approx model for "discrete-time" reachability
    sol = solve(prob, T=5.0, GLGM06(δ=0.01, approx_model=NoBloating()))

    # motor model (8 dim)
    prob, _ = motor()

    # dense array case
    alg = GLGM06(δ=1e-2)
    sol = solve(prob, T=20.0, alg=alg)
    RT = ReachSet{Float64, Zonotope{Float64, Vector{Float64}, Matrix{Float64}}}
    @test rsetrep(sol) == RT

    # static case
    alg = GLGM06(δ=1e-2, static=true, dim=8, max_order=1, ngens=8)
    sol = solve(prob, T=20.0, alg=alg)
    RT = ReachSet{Float64, Zonotope{Float64, SVector{8, Float64}, SMatrix{8, 8, Float64, 64}}}
    @test rsetrep(sol) == RT
end


text:
# This file was generated, do not modify it. # hide
Xnew = (sepal_length = [5.1, 6.3],
        sepal_width = [3.0, 2.5],
        petal_length = [1.4, 4.9],
        petal_width = [0.3, 1.5])
yhat = predict(mach, Xnew)

max_stars_repo_name: alan-turing-institute/MLJTutorials

max_issues_repo_name: alan-turing-institute/MLJTutorials

max_forks_repo_name: alan-turing-institute/MLJTutorials