text:
RpcApi.SimpleOrganism[RpcApi.SimpleOrganism(0x00000000000096b3,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepUp(o)
            Creature.stepUp(o)
            Creature.stepUp(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        var_8 = var_8 - var_8
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,207009,0x0000006e,Dict{Int16,Int16}(),[79,105],16),RpcApi.SimpleOrganism(0x0000000000009657,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int16=15929)
            local var_13::Int16 = -14946
            Creature.stepRight(o)
            o.mem[var_13] = var_13
            Creature.stepLeft(o)
            return var_9
        end
        function func_8(var_7::Int8=15)
            local var_14::Int16 = 26461
            Creature.eatDown(c,o,Int(var_7))
            Creature.eatDown(c,o,Int(var_7))
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = func_8(var_1)
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,146863,0x00000059,Dict{Int16,Int16}(),[170,34],17),RpcApi.SimpleOrganism(0x00000000000098e8,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_8 = var_8 - var_8
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,146183,0x0000006c,Dict{Int16,Int16}(),[78,106],12),RpcApi.SimpleOrganism(0x0000000000007666,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_8(var_7::Int8=15)
            Creature.stepLeft(o)
            Creature.stepRight(o)
            Creature.eatLeft(c,o,Int(var_7))
            Creature.eatDown(c,o,Int(var_7))
            for i::Int8 = 1:div(var_7,_LOOP_STEPS_DIVIDER)
            end
            Creature.stepDown(o)
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepRight(o)
        Creature.stepDown(o)
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,126450,0x00000057,Dict{Int16,Int16}(),[148,24],14),RpcApi.SimpleOrganism(0x00000000000094cc,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int16=15929)
            return var_9
        end
        function func_8(var_7::Int8=15)
            Creature.stepLeft(o)
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.stepLeft(o)
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,125593,0x0000005d,Dict{Int16,Int16}(),[103,166],15),RpcApi.SimpleOrganism(0x00000000000090af,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            local var_15::Int64 = 3571689374673078059
            return var_2
        end
        local var_1::Int8 = 71
        function func_18(var_16::String="KzcamwrC",var_17::Bool=false)
            return var_16
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_8 = var_8 - var_8
        Creature.eatDown(c,o,Int(var_1))
        var_8 = var_8 / var_8
        return true
    end),[110,300,98,0,1,1,1],25,1000,1,113402,0x00000069,Dict{Int16,Int16}(),[72,104],14),RpcApi.SimpleOrganism(0x0000000000006c10,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            return var_9
        end
        function func_3(var_2::Int16=-23790)
            var_2 = var_2 * var_2
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.stepDown(o)
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,108175,0x0000003f,Dict{Int16,Int16}(),[247,48],10),RpcApi.SimpleOrganism(0x000000000000992d,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_10::Int8 = 102
        function func_3(var_2::Int16=-23790)
            Creature.stepUp(o)
            Creature.stepLeft(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_10))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_10))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,105019,0x00000018,Dict{Int16,Int16}(),[229,115],11),RpcApi.SimpleOrganism(0x00000000000097a4,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            Creature.stepRight(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,101940,0x00000041,Dict{Int16,Int16}(),[248,59],15),RpcApi.SimpleOrganism(0x0000000000009655,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,100164,0x00000025,Dict{Int16,Int16}(),[179,33],7),RpcApi.SimpleOrganism(0x00000000000096fa,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            Creature.stepLeft(o)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            var_2 = var_2 * var_2
            Creature.stepDown(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,97986,0x00000044,Dict{Int16,Int16}(),[249,50],16),RpcApi.SimpleOrganism(0x00000000000095f7,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,94228,0x00000025,Dict{Int16,Int16}(),[179,32],7),RpcApi.SimpleOrganism(0x0000000000009919,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_14::Int8 = 25
        function func_9(var_7::Bool=true,var_8::Int64=-2995420336708105682)
            Creature.stepUp(o)
            Creature.stepRight(o)
            return var_7
        end
        local var_1::Int8 = 71
        function func_11(var_10::Int64=-3612233205782250359)
            return var_10
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepUp(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,758,1,93044,0x00000059,Dict{Int16,Int16}(),[230,66],12),RpcApi.SimpleOrganism(0x0000000000008e75,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,89896,0x00000000,Dict{Int16,Int16}(),[177,27],7),RpcApi.SimpleOrganism(0x000000000000837b,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,89803,0x00000000,Dict{Int16,Int16}(),[175,33],7),RpcApi.SimpleOrganism(0x000000000000924b,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_8::Int16=-4298,var_9::Int64=2457415148609568167)
            return var_8
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        if var_1 != var_1
            Creature.stepLeft(o)
        end
        Creature.eatRight(c,o,Int(var_1))
        Creature.stepLeft(o)
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,89701,0x00000071,Dict{Int16,Int16}(),[53,175],8),RpcApi.SimpleOrganism(0x00000000000092a4,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            local var_11::String = "TNCf3vh0"
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.stepDown(o)
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,332,1,87298,0x00000043,Dict{Int16,Int16}(),[247,48],10),RpcApi.SimpleOrganism(0x0000000000009878,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,86613,0x00000040,Dict{Int16,Int16}(),[248,68],15),RpcApi.SimpleOrganism(0x000000000000939a,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_10::Int8 = 102
        function func_3(var_2::Int16=-23790)
            Creature.stepUp(o)
            Creature.stepLeft(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_10))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_10))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,86464,0x00000018,Dict{Int16,Int16}(),[228,73],11),RpcApi.SimpleOrganism(0x0000000000009583,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,86449,0x00000025,Dict{Int16,Int16}(),[179,31],7),RpcApi.SimpleOrganism(0x0000000000006b9f,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            local var_14::String = "jSzghpB1"
            o.mem[var_2] = var_2
            Creature.stepDown(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        if var_1 >= var_1
        end
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepLeft(o)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        var_1 = var_1 - var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,84592,0x00000050,Dict{Int16,Int16}(),[247,48],16),RpcApi.SimpleOrganism(0x000000000000995b,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            return var_9
        end
        function func_3(var_2::Int16=-23790)
            var_2 = var_2 * var_2
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.stepDown(o)
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,83934,0x0000003f,Dict{Int16,Int16}(),[248,53],10),RpcApi.SimpleOrganism(0x0000000000009632,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,83075,0x00000041,Dict{Int16,Int16}(),[248,67],14),RpcApi.SimpleOrganism(0x000000000000931d,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            o.mem[var_2] = var_2
            return var_2
        end
        local var_1::Int8 = 71
        if var_1 < var_1
            Creature.stepDown(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
            Creature.stepLeft(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,79728,0x00000041,Dict{Int16,Int16}(),[208,162],11),RpcApi.SimpleOrganism(0x000000000000559e,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_9(var_8::Bool=false)
            return var_8
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepDown(o)
        end
        var_1 = var_1 - var_1
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepUp(o)
        Creature.stepRight(o)
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,79171,0x00000051,Dict{Int16,Int16}(),[73,181],11),RpcApi.SimpleOrganism(0x0000000000009846,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_9::Int16 = 21853
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            Creature.eatDown(c,o,Int(var_4))
            Creature.stepRight(o)
            Creature.stepRight(o)
            Creature.eatRight(c,o,Int(var_4))
            Creature.eatLeft(c,o,Int(var_4))
            Creature.stepDown(o)
            return var_4
        end
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,78745,0x00000070,Dict{Int16,Int16}(),[224,160],15),RpcApi.SimpleOrganism(0x0000000000009877,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_9::Int16 = 21853
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            for i::Int8 = 1:div(var_4,_LOOP_STEPS_DIVIDER)
                Creature.stepLeft(o)
            end
            Creature.stepUp(o)
            Creature.eatLeft(c,o,Int(var_4))
            return var_4
        end
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,78161,0x0000006f,Dict{Int16,Int16}(),[222,160],13),RpcApi.SimpleOrganism(0x00000000000097c4,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            local var_14::Int64 = -4335654835057001748
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,76722,0x00000042,Dict{Int16,Int16}(),[249,45],14),RpcApi.SimpleOrganism(0x0000000000009705,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_16(var_14::Bool=false,var_15::Int8=-35)
            return var_14
        end
        function func_5(var_4::Bool=true)
            local var_17::Int64 = 5901955699461906666
            Creature.stepUp(o)
            return var_4
        end
        local var_1::Int8 = 71
        Creature.stepRight(o)
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,74924,0x00000054,Dict{Int16,Int16}(),[201,28],10),RpcApi.SimpleOrganism(0x0000000000009971,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            var_9 = var_9 / var_9
            var_9 = var_9 * var_9
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            local var_14::Int64 = -4335654835057001748
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,73910,0x00000042,Dict{Int16,Int16}(),[250,47],15),RpcApi.SimpleOrganism(0x00000000000097b1,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,73676,0x00000040,Dict{Int16,Int16}(),[248,65],15),RpcApi.SimpleOrganism(0x000000000000931a,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            var_11 = var_11[1:if length(var_11) > length(var_11)
                            0
                        else
                            length(var_11) - length(var_11)
                        end]
            var_9 = var_9 / var_9
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            var_4 = var_4 * var_4
            var_5 = Bool(abs(var_5 - var_5))
            Creature.stepRight(o)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        var_1 = var_1 * var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,73661,0x0000003f,Dict{Int16,Int16}(),[256,1],18),RpcApi.SimpleOrganism(0x000000000000908c,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,71334,0x00000025,Dict{Int16,Int16}(),[178,33],7),RpcApi.SimpleOrganism(0x0000000000009803,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_8::Int64 = -333518551926540339
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepUp(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepLeft(o)
            Creature.stepDown(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            var_9 = if haskey(o.mem,var_9)
                    o.mem[var_9]
                else
                    var_9
                end
            Creature.stepRight(o)
        end
        if var_8 == var_8
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        var_1 = var_1 / var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,69257,0x0000004d,Dict{Int16,Int16}(),[50,20],17),RpcApi.SimpleOrganism(0x000000000000924d,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_9::Int16 = 21853
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            Creature.eatDown(c,o,Int(var_4))
            Creature.stepRight(o)
            Creature.stepRight(o)
            Creature.eatRight(c,o,Int(var_4))
            Creature.stepDown(o)
            var_4 = var_4 + var_4
            return var_4
        end
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,66107,0x0000006f,Dict{Int16,Int16}(),[223,160],15),RpcApi.SimpleOrganism(0x000000000000996e,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            local var_17::Int16 = -2407
            local var_14::Int8 = 120
            var_4 = var_4[1:if length(var_4) > length(var_4) > 0
                            0
                        else
                            div(length(var_4),length(var_4))
                        end]
            if var_5 <= var_5
            end
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            local var_16::Int16 = -31980
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.stepUp(o)
        Creature.eatLeft(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            local var_15::Bool = true
            Creature.stepUp(o)
        end
        Creature.stepUp(o)
        return true
    end),[110,300,98,0,1,1,1],0,472,10,65583,0x00000074,Dict{Int16,Int16}(),[252,172],20),RpcApi.SimpleOrganism(0x00000000000091c9,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        if var_1 < var_1
            Creature.stepLeft(o)
            Creature.stepRight(o)
            Creature.stepDown(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,840,1,65174,0x00000039,Dict{Int16,Int16}(),[137,166],9),RpcApi.SimpleOrganism(0x00000000000083b2,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,62877,0x00000025,Dict{Int16,Int16}(),[182,30],7),RpcApi.SimpleOrganism(0x0000000000009562,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,62212,0x00000025,Dict{Int16,Int16}(),[178,33],7),RpcApi.SimpleOrganism(0x0000000000007e68,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_14(var_12::Int64=-1172685063416274102,var_13::String="6CAs70G3")
            return var_12
        end
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepRight(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            local var_16::Int8 = -112
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepDown(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,61129,0x00000066,Dict{Int16,Int16}(),[61,102],17),RpcApi.SimpleOrganism(0x0000000000007d9e,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_14(var_12::Int64=-1172685063416274102,var_13::String="6CAs70G3")
            return var_12
        end
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            o.mem[var_2] = var_2
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,60995,0x0000006a,Dict{Int16,Int16}(),[59,102],14),RpcApi.SimpleOrganism(0x0000000000008e9a,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,60993,0x00000000,Dict{Int16,Int16}(),[177,26],7),RpcApi.SimpleOrganism(0x0000000000008b63,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            local var_17::Int16 = -2407
            local var_14::Int8 = 120
            var_4 = var_4[1:if length(var_4) > length(var_4) > 0
                            0
                        else
                            div(length(var_4),length(var_4))
                        end]
            if var_5 <= var_5
            end
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            local var_16::Int16 = -31980
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.stepUp(o)
        Creature.eatLeft(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            local var_15::Bool = true
            Creature.stepUp(o)
        end
        Creature.stepUp(o)
        return true
    end),[110,300,98,0,1,1,1],0,472,10,60897,0x00000074,Dict{Int16,Int16}(),[251,98],20),RpcApi.SimpleOrganism(0x0000000000007078,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,60875,0x00000040,Dict{Int16,Int16}(),[247,48],15),RpcApi.SimpleOrganism(0x00000000000096b0,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,60805,0x00000025,Dict{Int16,Int16}(),[179,34],7),RpcApi.SimpleOrganism(0x0000000000009161,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            Creature.stepLeft(o)
            Creature.stepDown(o)
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            Creature.stepRight(o)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            var_2 = var_2 / var_2
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        var_1 = var_1 * var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,60561,0x00000042,Dict{Int16,Int16}(),[258,72],16),RpcApi.SimpleOrganism(0x00000000000097c2,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_16::Int8 = -46
        local var_8::Int64 = 7733858157021421351
        local var_1::Int8 = 71
        var_1 = var_1 - var_16
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_16,_LOOP_STEPS_DIVIDER)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_16))
        return true
    end),[110,300,98,0,1,1,1],0,194,1,58940,0x00000078,Dict{Int16,Int16}(),[88,105],10),RpcApi.SimpleOrganism(0x0000000000009895,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepLeft(o)
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,58354,0x00000041,Dict{Int16,Int16}(),[249,56],15),RpcApi.SimpleOrganism(0x0000000000008abc,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_9::Int16 = 21853
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            for i::Int8 = 1:div(var_4,_LOOP_STEPS_DIVIDER)
                Creature.stepLeft(o)
            end
            Creature.stepUp(o)
            Creature.eatLeft(c,o,Int(var_4))
            return var_4
        end
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,57904,0x0000006f,Dict{Int16,Int16}(),[221,160],13),RpcApi.SimpleOrganism(0x0000000000009988,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_9::Int64=5834929311053498552)
            local var_12::String = "F9i3oH7h"
            if var_12 != var_12
            end
            return var_9
        end
        function func_6(var_4::String="h4Bwl0JP",var_5::Bool=false)
            return var_4
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepRight(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,57778,0x00000040,Dict{Int16,Int16}(),[246,85],15)]

max_stars_repo_name: tmptrash/jevo

max_issues_repo_name: tmptrash/jevo

max_forks_repo_name: tmptrash/jevo


text:
using NCCL, CUDAdrv, CuArrays, CUDAnative
using Test

@testset "NCCL.jl" begin
    @testset "Communicator" begin
        comms = Communicator(CUDAdrv.devices())
        for (i,dev) in enumerate(CUDAdrv.devices())
            @test rank(comms[i]) == i-1
            @test device(comms[i]) == i-1
            @test size(comms[i]) == length(CUDAdrv.devices())
        end
        id    = UniqueID()
        #=num_devs = length(CUDAdrv.devices())
        comm  = Communicator(num_devs, id, 0)
        @test device(comm) == 0=#
    end
    @testset "Allreduce!" begin
        devs  = CUDAdrv.devices()
        comms = Communicator(devs)
        recvbuf = Vector{CuVector{Float64}}(undef, length(devs))
        sendbuf = Vector{CuVector{Float64}}(undef, length(devs))
        streams = Vector{CuStream}(undef, length(devs))
        for (ii, dev) in enumerate(devs)
            CUDAnative.device!(ii - 1)
            sendbuf[ii] = cu(fill(Float64(ii), 512))
            recvbuf[ii] = CuArrays.zeros(Float64, 512)
            streams[ii] = CuStream()
        end
        groupStart()
        for ii in 1:length(devs)
            Allreduce!(sendbuf[ii], recvbuf[ii], 512, NCCL.ncclSum, comms[ii], stream=streams[ii])
        end
        groupEnd()
        answer = sum(1:length(devs))
        for (ii, dev) in enumerate(devs)
            device!(ii - 1)
            crecv = collect(recvbuf[ii])
            @test all(crecv .== answer)
        end
    end
    @testset "Broadcast!" begin
        devs  = CUDAdrv.devices()
        comms = Communicator(devs)
        recvbuf = Vector{CuVector{Float64}}(undef, length(devs))
        sendbuf = Vector{CuVector{Float64}}(undef, length(devs))
        streams = Vector{CuStream}(undef, length(devs))
        root  = 0
        for (ii, dev) in enumerate(devs)
            CUDAnative.device!(ii - 1)
            sendbuf[ii] = (ii - 1) == root ? cu(fill(Float64(1.0), 512)) : CuArrays.zeros(Float64, 512)
            recvbuf[ii] = CuArrays.zeros(Float64, 512)
            streams[ii] = CuStream()
        end
        groupStart()
        for ii in 1:length(devs)
            Broadcast!(sendbuf[ii], recvbuf[ii], 512, 0, comms[ii], stream=streams[ii])
        end
        groupEnd()
        answer = 1.0
        for (ii, dev) in enumerate(devs)
            device!(ii - 1)
            crecv = collect(recvbuf[ii])
            @test all(crecv .== answer)
        end
    end
    @testset "Reduce!" begin
        devs  = CUDAdrv.devices()
        comms = Communicator(devs)
        recvbuf = Vector{CuVector{Float64}}(undef, length(devs))
        sendbuf = Vector{CuVector{Float64}}(undef, length(devs))
        streams = Vector{CuStream}(undef, length(devs))
        root  = 0
        for (ii, dev) in enumerate(devs)
            CUDAnative.device!(ii - 1)
            sendbuf[ii] = cu(fill(Float64(ii), 512))
            recvbuf[ii] = CuArrays.zeros(Float64, 512)
            streams[ii] = CuStream()
        end
        groupStart()
        for ii in 1:length(devs)
            Reduce!(sendbuf[ii], recvbuf[ii], 512, NCCL.ncclSum, 0, comms[ii], stream=streams[ii])
        end
        groupEnd()
        for (ii, dev) in enumerate(devs)
            answer = (ii - 1) == root ? sum(1:length(devs)) : 0.0
            device!(ii - 1)
            crecv = collect(recvbuf[ii])
            @test all(crecv .== answer)
        end
    end
    @testset "Allgather!" begin
        devs  = CUDAdrv.devices()
        comms = Communicator(devs)
        recvbuf = Vector{CuVector{Float64}}(undef, length(devs))
        sendbuf = Vector{CuVector{Float64}}(undef, length(devs))
        streams = Vector{CuStream}(undef, length(devs))
        for (ii, dev) in enumerate(devs)
            CUDAnative.device!(ii - 1)
            sendbuf[ii] = cu(fill(Float64(ii), 512))
            recvbuf[ii] = CuArrays.zeros(Float64, length(devs)*512)
            streams[ii] = CuStream()
        end
        groupStart()
        for ii in 1:length(devs)
            Allgather!(sendbuf[ii], recvbuf[ii], 512, comms[ii], stream=streams[ii])
        end
        groupEnd()
        answer = vec(repeat(1:length(devs), inner=512))
        for (ii, dev) in enumerate(devs)
            device!(ii - 1)
            crecv = collect(recvbuf[ii])
            @test all(crecv .== answer)
        end
    end
    @testset "ReduceScatter!" begin
        devs  = CUDAdrv.devices()
        comms = Communicator(devs)
        recvbuf = Vector{CuVector{Float64}}(undef, length(devs))
        sendbuf = Vector{CuVector{Float64}}(undef, length(devs))
        streams = Vector{CuStream}(undef, length(devs))
        root  = 0
        for (ii, dev) in enumerate(devs)
            CUDAnative.device!(ii - 1)
            sendbuf[ii] = cu(vec(repeat(collect(1:length(devs)), inner=2)))
            recvbuf[ii] = CuArrays.zeros(Float64, length(devs))
            streams[ii] = CuStream()
        end
        groupStart()
        for ii in 1:length(devs)
            ReduceScatter!(sendbuf[ii], recvbuf[ii], length(devs), NCCL.ncclSum, comms[ii], stream=streams[ii])
        end
        groupEnd()
        for (ii, dev) in enumerate(devs)
            answer = length(devs)*ii
            device!(ii - 1)
            crecv = collect(recvbuf[ii])
            @test all(crecv .== answer)
        end
    end
end

ext: jl


text:
using PointerStructs, Aqua
using Test

@pointer struct Bar
  a::Vector{Float64}
  b::Vector{Float64}
  c::Matrix{Float64}
  d::((a,b,c,c)=>(size=tuple,size=tuple,size=x->(x,x),strides=x->(static(1),x)))::Int
end
@pointer struct Foo
  a::Int
  b::&Float64
  d::(c => d)::Int
  c::Bar
  z::&Float64
end

@testset "PointerStructs.jl" begin
  x = rand(10*(2+10)+2);
  GC.@preserve x begin
    foo = Foo(pointer(x), 5, 10)
    @test foo.a == 5
    @unpack a, b, d, c, z = foo;
    @test a == 5
    @test b == x[1]
    b = 3.14
    @pack! foo = b
    b = 0.0
    @unpack b = foo;
    @test b == 3.14
    foo.b = 13.4
    @test foo.b == 13.4

    @test d == 10
    @unpack a, b, c = c;
    @test collect(a) == view(x, 2:11)
    @test collect(b) == view(x, 12:21)
    @test collect(c) == reshape(view(x, 22:121),(10,10))

    @test z == x[end]
    z = 123.4
    @pack! foo = z;
    @test x[end] == 123.4
  end
  Aqua.test_all(PointerStructs)
end


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

using Markdown
using InteractiveUtils

# ╔═╡ 2d08dd15-3ecb-4e0e-9a00-54359ec84f93
md"""
# Installing and Running Julia

This notebook describes the installation process for various components of the software.

### Competences

The reader will be able to install `Julia` and all its components, to run `Julia` and start `IJulia` and `Pluto` notebook servers.

## Installing Julia

To install Julia download and extract prebuilt binary for your operating system - see [Julia](https://julialang.org).

After instalation, you can start Julia in terminal mode by clicking its icon.

Semi-colon is the shell escape symbol, so, for example `; ls` gives directory listing.

Question mark is the help symbol, so `?` enters help and you can write the command.

Backspace exits from shell and help.

Installation of Julia and packages may take some time, so be patient.

## Installing and running `IJulia`

Do the following:
* start Julia in terminal mode
* at the `julia` prompt type
```
import Pkg
Pkg.add("IJulia")
using IJulia
notebook(detached=true)
```

This opens IJulia window in your default browser, which should be Chrome or Firefox. _The first two commands need to be executed only the first time!_.

## Installing and running `Pluto`

Do the following:
* start Julia in terminal mode
* at the `julia` prompt type
```
import Pkg
Pkg.add("Pluto")
using Pluto
Pluto.run()
```

This opens Pluto window in your default browser. The first two commands need to be executed only the first time!.

## Remarks

In Linux, packges are installed in the directory `$HOME/.julia/packages/`.

In Windows 10, you will have Julia icon which starts Julia command window.
Julia is installed in the directory (`AppData` is a hidden directory):
```
\Users\your_user_name\AppData\Local\Programs\Julia-1.6.2
```
The packages are installed in the directory `\Users\your_user_name\.julia\packages`
In Julia, current path and directory listing are obtained by Julia commands
`pwd()` and `readdir()`, respectively.

Prior to executing `notebook()` command, you can use shell commands in `Julia` prompt to change directory, something like
```
; cd ../../my_julia_directory`
```

"""

# ╔═╡ ab1a0cfc-0a8b-4137-a73c-9dd7bb4296fd

# ╔═╡ Cell order:
# ╟─2d08dd15-3ecb-4e0e-9a00-54359ec84f93
# ╠═ab1a0cfc-0a8b-4137-a73c-9dd7bb4296fd

max_stars_repo_path: src/Module A - Short Julia Course/L00 Installing and Running Julia.jl

max_stars_repo_name: ivanslapnicar/GIAN-Applied-NLA-Course

max_issues_repo_name: ivanslapnicar/GIAN-Applied-NLA-Course

max_forks_repo_name: ivanslapnicar/GIAN-Applied-NLA-Course


text:
module RvSpectMLPlots

using RvSpectMLBase
using Plots
using ColorSchemes

using LinearAlgebra
using StatsBase

include("spectra.jl")
export plot_spectrum_chunks, get_λs, add_time_gap_lines

include("ccf.jl")
export make_plot_ccf_vs_time, make_heatmap_ccf_vs_time
#export make_plot_ccf_vs_order, make_plot_ccf_vs_chunk  # TODO: Write
export make_heatmap_ccf_vs_order

include("scalpels_code.jl")
export make_plots_scalpels

include("dcpca.jl")
export plot_basis_vectors, plot_basis_scores, plot_basis_scores_cor

end


text:
function POMDPs.requirements_info(solver::AbstractPOMCPSolver, problem::POMDP)
    if @implemented initial_state_distribution(::typeof(problem))
        return requirements_info(solver, problem, initial_state_distribution(problem))
    else
        println("""
        Since POMCP is an online solver, most of the computation occurs in `action(planner, state)`. In order to view the requirements for this function, please, supply a state as the third argument to `requirements_info`, e.g.

            @requirements_info $(typeof(solver))() $(typeof(problem))() $(state_type(typeof(problem)))()

            """)
    end
end

function POMDPs.requirements_info(solver::AbstractPOMCPSolver, problem::POMDP, b)
    policy = solve(solver, problem)
    requirements_info(policy, b)
end

function POMDPs.requirements_info(policy::POMCPPlanner, b)
    @show_requirements action(policy, b)

    problem = policy.problem
    rng = MersenneTwister(1)
    if @implemented(rand(::typeof(rng), ::typeof(b))) &&
        @implemented(actions(::typeof(problem))) &&
        @implemented(iterator(::typeof(actions(problem))))
        s = rand(rng, b)
        a = first(iterator(actions(problem)))
        if @implemented generate_sor(::typeof(policy.problem), ::typeof(s), ::typeof(a), ::typeof(rng))
            sp, o, r = generate_sor(policy.problem, s, a, rng)

            if !isequal(deepcopy(o), o)
                warn("""
                     isequal(deepcopy(o), o) returned false. Is isequal() defined correctly?

                     For POMCP to work correctly, you must define isequal(::$(typeof(o)), ::$(typeof(o))) (see https://docs.julialang.org/en/stable/stdlib/collections/#Associative-Collections-1, https://github.com/andrewcooke/AutoHashEquals.jl#background, also consider using StaticArrays). This warning was thrown because isequal($(deepcopy(o)), $o) returned false.

                     Note: isequal() should also be defined correctly for actions, but no warning will be issued.
                     """)
            end
            if hash(deepcopy(o)) != hash(o)
                warn("""
                     hash(deepcopy(o)) was not equal to hash(o). Is hash() defined correctly?

                     For MCTS to work correctly, you must define hash(::$(typeof(o)), ::UInt) (see https://docs.julialang.org/en/stable/stdlib/collections/#Associative-Collections-1, https://github.com/andrewcooke/AutoHashEquals.jl#background, also consider using StaticArrays). This warning was thrown because hash($(deepcopy(o))) != hash($o).

                     Note: hash() should also be defined correctly for actions, but no warning will be issued.
                     """)
            end
        end
    end
end

@POMDP_require action(p::POMCPPlanner, b) begin
    tree = POMCPTree(p.problem, p.solver.tree_queries)
    @subreq search(p, b, tree)
end

@POMDP_require search(p::POMCPPlanner, b, t::POMCPTree) begin
    P = typeof(p.problem)
    @req rand(::typeof(p.rng), ::typeof(b))
    s = rand(p.rng, b)
    @req isterminal(::P, ::state_type(P))
    @subreq simulate(p, s, POMCPObsNode(t, 1), p.solver.max_depth)
end

@POMDP_require simulate(p::POMCPPlanner, s, hnode::POMCPObsNode, steps::Int) begin
    P = typeof(p.problem)
    S = state_type(P)
    A = action_type(P)
    O = obs_type(P)
    @req generate_sor(::P, ::S, ::A, ::typeof(p.rng))
    @req isequal(::O, ::O)
    @req hash(::O)
    # from insert_obs_node!
    @req n_actions(::P)
    @req actions(::P)
    AS = typeof(actions(p.problem))
    @req iterator(::AS)
    @subreq estimate_value(p.solved_estimator, p.problem, s, hnode, steps)
    @req discount(::P)
end

@POMDP_require estimate_value(f::Function, pomdp::POMDPs.POMDP, start_state, h::BeliefNode, steps::Int) begin
    @req f(::typeof(pomdp), ::typeof(start_state), ::typeof(h), ::typeof(steps))
end


text:
using PackageCompiler
using CSV
using DataFrames
using LaTeXStrings
using Latexify
using Plots
using Pluto
using PlutoUI
using Markdown

create_sysimage([
    :CSV,
    :DataFrames,
    :LaTeXStrings,
    :Latexify,
    :Plots,
    :Pluto,
    :PlutoUI,
    :Markdown
    ];
    precompile_statements_file="pluto_precompile.jl",
    precompile_execution_file="pluto_warmup.jl",
    sysimage_path="PlutoSysImage.so")


text:
# make your scripts automatically re-activate your project
cd(@__DIR__)
using Pkg; Pkg.activate("../..")

# load packages
using ml_for_pt
using DelimitedFiles
using LaTeXStrings
using Plots
using Random
ENV["GKSwstype"]="nul"

# set linear system size and corresponding data folder
L = 10
# L=60
data_folder = "../../data/ising/L="*string(L)*"/"

# set path to save folder
save_folder = "./results/L="*string(L)*"/"

# critical parameter value for the Ising model
p_crit = Float32(2/log(1+sqrt(2)))

# define parameter ranges
p_min = 0.05f0
p_max = 10.0f0
dp = 0.05f0
p_range = collect(p_min:dp:p_max)
p_range_LBC = collect(p_min-dp/2:dp:p_max+dp/2)

# import Monte Carlo data

# unique energies at p=p_1
energy = readdlm(data_folder*"E_T="*string(0)*".txt", eltype(dp))

# number of times each energy is drawn at T=T_1
num = readdlm(data_folder*"num_T="*string(0)*".txt", eltype(dp))

# iterate over entire parameter range
energies=[energy]
numbers=[num]
for index in 1:length(p_range)-1
  energyy = readdlm(data_folder*"E_T="*string(index)*".txt", eltype(dp))
  numm = readdlm(data_folder*"num_T="*string(index)*".txt", eltype(dp))
  push!(energies, energyy)
  push!(numbers, numm)
end
unique_energies = unique(vcat(energies...))
n_samples = sum(numbers[1])

# construct probability distribution from Monte Carlo data
# distr(x,p) gives probability to draw the sample x at parameter value p
# samples correspond to enumeration of unique energies with integers
distr,samples = MLP.distr_approx(energies, unique_energies, numbers, p_range)

# supervised learning using analytical expression
# returns optimal predictions, indicator, and loss
pred_opt_SL, indicator_opt_SL, loss_opt_SL = MLP.get_indicators_SL_analytical(samples, distr, p_range, dp, p_min, p_max)

# prediction-based method using analytical expression
# returns optimal predictions, indicator, and loss
pred_opt_PBM, indicator_opt_PBM, loss_opt_PBM = MLP.get_indicators_PBM_analytical(samples, distr, p_range, dp)

# learning by confusion using analytical expression
# returns optimal indicator and loss
indicator_opt_LBC, loss_opt_LBC = MLP.get_indicators_LBC_analytical(samples, distr, p_range, p_range_LBC)

# save output in save_folder
open(save_folder*"p_range_SL.txt", "w") do io
  writedlm(io, p_range)
end

open(save_folder*"p_range_PBM.txt", "w") do io
  writedlm(io, p_range)
end

open(save_folder*"p_range_LBC.txt", "w") do io
  writedlm(io, p_range_LBC)
end

open(save_folder*"pred_opt_SL.txt", "w") do io
  writedlm(io, pred_opt_SL)
end

open(save_folder*"indicator_opt_SL.txt", "w") do io
  writedlm(io, indicator_opt_SL)
end

open(save_folder*"loss_opt_SL.txt", "w") do io
  writedlm(io, [loss_opt_SL])
end

open(save_folder*"pred_opt_PBM.txt", "w") do io
  writedlm(io, pred_opt_PBM)
end

open(save_folder*"indicator_opt_PBM.txt", "w") do io
  writedlm(io, indicator_opt_PBM)
end

open(save_folder*"loss_opt_PBM.txt", "w") do io
  writedlm(io, [loss_opt_PBM])
end

open(save_folder*"indicator_opt_LBC.txt", "w") do io
  writedlm(io, indicator_opt_LBC)
end

open(save_folder*"loss_opt_LBC.txt", "w") do io
  writedlm(io, loss_opt_LBC)
end

# plot and save results in save_folder
plt = plot(p_range, pred_opt_SL, dpi=300, c="black", label=false)
vline!([p_crit], label=L"p_{c}", c="red")
xlabel!(L"$p$")
ylabel!(L"$\hat{y}^{\mathrm{opt}}_{\mathrm{SL}}$")
savefig(save_folder*"pred_opt_SL.png")

plt = plot(p_range[2:end-1], indicator_opt_SL, dpi=300, c="black", label=false)
vline!([p_crit], label=L"p_{c}", c="red")
xlabel!(L"$p$")
ylabel!(L"$I^{\mathrm{opt}}_{\mathrm{SL}}$")
savefig(save_folder*"indicator_opt_SL.png")

plt = plot(p_range, pred_opt_PBM, dpi=300, c="black", label=false)
vline!([p_crit], label=L"p_{c}", c="red")
xlabel!(L"$p$")
ylabel!(L"$\hat{y}^{\mathrm{opt}}_{\mathrm{PBM}}$")
savefig(save_folder*"pred_opt_PBM.png")

plt = plot(p_range[2:end-1], indicator_opt_PBM, dpi=300, c="black", label=false)
vline!([p_crit], label=L"p_{c}", c="red")
xlabel!(L"$p$")
ylabel!(L"$I^{\mathrm{opt}}_{\mathrm{PBM}}$")
savefig(save_folder*"indicator_opt_PBM.png")

plt = plot(p_range_LBC, indicator_opt_LBC, dpi=300, c="black", label=false)
vline!([p_crit], label=L"p_{c}",c="red")
xlabel!(L"$p$")
ylabel!(L"$I^{\mathrm{opt}}_{\mathrm{LBC}}$")
savefig(save_folder*"indicator_opt_LBC.png")

plt = plot(p_range_LBC, loss_opt_LBC, dpi=300, c="black",label=false)
vline!([p_crit], label=L"p_{c}",c="red")
xlabel!(L"$p$")
ylabel!(L"$\mathcal{L}^{\mathrm{opt}}_{\mathrm{LBC}}$")
savefig(save_folder*"loss_opt_LBC.png")


text:
"""
Xijiang's breeding algorithms implemented in Julia and C++.
"""
module ABG
#using SparseArrays, LinearAlgebra, Serialization, Statistics

workdir = pwd()
abg_bin, abg_cpp, abg_dat = begin
    t = splitdir(pathof(ABG))[1]
    l = findlast('/', t) - 1
    d = t[1:l]
    joinpath.(d, ["bin", "cpp", "dat"])
end

global abg_rst = joinpath(pwd(), "sandbox")
set_rst(dir) = (global abg_rst = dir)

beagle = joinpath(abg_bin, "beagle.jar")
plink = joinpath(abg_bin, "plink")

# v0.1
################################################################################
include("styled-messages.jl")   # checked 2020-09-13-11:39
include("final-reports-2-ped.jl")

# v0.2
include("makefile.jl")
include("a-matrix.jl")
include("g-matrix.jl")
include("g-med-stor-m.jl")
include("sort-pedigree.jl")
include("simulation.jl")

# v0.2.1
include("bgcf.jl")              # for Theo's `bgcf` program
include("DMU.jl")               # prepare for the running of DMU

ABG.title("ABG Julia Package")
ABG.message(lpad("Developed by Xijiang Yu @NMBU", 60),
            lpad("MIT license", 60),
            lpad("Copyright © 2020 - " * string(Dates.year(Dates.now())), 60)
            )
ABG.Update()
ABG.message("Current sandbox path is $abg_rst",
            "You can change it by calling 'ABG.set_rst(your_desired_path)'"
            )
end # module


text:
using CodecZlib
using Test
import TranscodingStreams:
    TranscodingStreams,
    TranscodingStream,
    test_roundtrip_read,
    test_roundtrip_write,
    test_roundtrip_lines,
    test_roundtrip_transcode

const testdir = @__DIR__

@testset "Gzip Codec" begin
    codec = GzipCompressor()
    @test codec isa GzipCompressor
    @test occursin(r"^(CodecZlib\.)?GzipCompressor\(level=-1, windowbits=\d+\)$", sprint(show, codec))
    @test CodecZlib.initialize(codec) === nothing
    @test CodecZlib.finalize(codec) === nothing

    codec = GzipDecompressor()
    @test codec isa GzipDecompressor
    @test occursin(r"^(CodecZlib\.)?GzipDecompressor\(windowbits=\d+\)$", sprint(show, codec))
    @test CodecZlib.initialize(codec) === nothing
    @test CodecZlib.finalize(codec) === nothing

    # `gzip.compress(b"foo")` in Python 3.6.2 (zlib 1.2.8).
    gzip_data = b"\x1f\x8b\x08\x00R\xcc\x10Y\x02\xffK\xcb\xcf\x07\x00!es\x8c\x03\x00\x00\x00"

    file = IOBuffer(gzip_data)
    stream = GzipDecompressorStream(file)
    @test !eof(stream)
    @test read(stream) == b"foo"
    @test eof(stream)
    @test close(stream) === nothing
    @test !isopen(stream)
    @test !isopen(file)

    file = IOBuffer(gzip_data)
    stream = GzipDecompressorStream(file, bufsize=1)
    @test length(stream.state.buffer1) == 1
    @test length(stream.state.buffer2) == 1
    @test read(stream) == b"foo"
    close(stream)

    # Corrupted data
    gzip_data_corrupted = copy(gzip_data)
    gzip_data_corrupted[1] = 0x00  # corrupt header
    file = IOBuffer(gzip_data_corrupted)
    stream = GzipDecompressorStream(file)
    @test_throws ErrorException read(stream)
    @test_throws ArgumentError read(stream)
    @test !isopen(stream)
    @test isopen(file)
    @test close(stream) === nothing
    @test !isopen(stream)
    @test !isopen(file)

    stream = TranscodingStream(GzipDecompressor(gziponly=false), IOBuffer(gzip_data))
    @test read(stream) == b"foo"
    close(stream)

    stream = TranscodingStream(GzipDecompressor(gziponly=true), IOBuffer(gzip_data))
    @test read(stream) == b"foo"
    close(stream)

    file = IOBuffer(vcat(gzip_data, gzip_data))
    stream = GzipDecompressorStream(file)
    @test read(stream) == b"foofoo"
    close(stream)

    open(joinpath(testdir, "foo.txt.gz")) do file
        @test read(GzipDecompressorStream(file)) == b"foo"
    end

    file = IOBuffer("foo")
    stream = GzipCompressorStream(file)
    @test !eof(stream)
    @test length(read(stream)) > 0
    @test eof(stream)
    @test close(stream) === nothing
    @test !isopen(stream)
    @test !isopen(file)

    mktemp() do path, file
        stream = GzipDecompressorStream(file)
        @test write(stream, gzip_data) == length(gzip_data)
        @test close(stream) === nothing
        @test !isopen(stream)
        @test !isopen(file)
        @test read(path) == b"foo"
    end

    mktemp() do path, file
        stream = GzipCompressorStream(file)
        @test write(stream, "foo") == 3
        @test close(stream) === nothing
        @test !isopen(stream)
        @test !isopen(file)
        @test length(read(path)) > 0
    end

    @test GzipCompressorStream <: TranscodingStream
    @test GzipDecompressorStream <: TranscodingStream

    test_roundtrip_read(GzipCompressorStream, GzipDecompressorStream)
    test_roundtrip_write(GzipCompressorStream, GzipDecompressorStream)
    test_roundtrip_lines(GzipCompressorStream, GzipDecompressorStream)
    test_roundtrip_transcode(GzipCompressor, GzipDecompressor)

    @test_throws ArgumentError GzipCompressor(level=10)
    @test_throws ArgumentError GzipCompressor(windowbits=16)
    @test_throws ArgumentError GzipDecompressor(windowbits=16)
end

@testset "Zlib Codec" begin
    codec = ZlibCompressor()
    @test codec isa ZlibCompressor
    @test occursin(r"^(CodecZlib\.)?ZlibCompressor\(level=-1, windowbits=\d+\)$", sprint(show, codec))
    @test CodecZlib.initialize(codec) === nothing
    @test CodecZlib.finalize(codec) === nothing

    codec = ZlibDecompressor()
    @test codec isa ZlibDecompressor
    @test occursin(r"^(CodecZlib\.)?ZlibDecompressor\(windowbits=\d+\)$", sprint(show, codec))
    @test CodecZlib.initialize(codec) === nothing
    @test CodecZlib.finalize(codec) === nothing

    # `zlib.compress(b"foo")` in Python 3.6.2 (zlib 1.2.8).
    zlib_data = b"x\x9cK\xcb\xcf\x07\x00\x02\x82\x01E"

    file = IOBuffer(zlib_data)
    stream = ZlibDecompressorStream(file)
    @test !eof(stream)
    @test read(stream) == b"foo"
    @test eof(stream)
    @test close(stream) === nothing
    @test !isopen(stream)
    @test !isopen(file)

    file = IOBuffer(zlib_data)
    stream = ZlibDecompressorStream(file, bufsize=1)
    @test length(stream.state.buffer1) == 1
    @test length(stream.state.buffer2) == 1
    @test read(stream) == b"foo"
    close(stream)

    stream = TranscodingStream(GzipDecompressor(gziponly=false), IOBuffer(zlib_data))
    @test read(stream) == b"foo"
    close(stream)

    stream = TranscodingStream(GzipDecompressor(gziponly=true), IOBuffer(zlib_data))
    @test_throws Exception read(stream)
    close(stream)

    file = IOBuffer(b"foo")
    stream = ZlibCompressorStream(file)
    @test !eof(stream)
    @test read(stream) == zlib_data
    @test eof(stream)
    @test close(stream) === nothing
    @test !isopen(stream)
    @test !isopen(file)

    mktemp() do path, file
        stream = ZlibDecompressorStream(file)
        @test write(stream, zlib_data) == length(zlib_data)
        @test close(stream) === nothing
        @test !isopen(stream)
        @test !isopen(file)
        @test read(path) == b"foo"
    end

    mktemp() do path, file
        stream = ZlibCompressorStream(file)
        @test write(stream, "foo") == 3
        @test close(stream) === nothing
        @test !isopen(stream)
        @test !isopen(file)
        @test read(path) == zlib_data
    end

    @test ZlibCompressorStream <: TranscodingStream
    @test ZlibDecompressorStream <: TranscodingStream

    test_roundtrip_read(ZlibCompressorStream, ZlibDecompressorStream)
    test_roundtrip_write(ZlibCompressorStream, ZlibDecompressorStream)
    test_roundtrip_lines(ZlibCompressorStream, ZlibDecompressorStream)
    test_roundtrip_transcode(ZlibCompressor, ZlibDecompressor)

    @test_throws ArgumentError ZlibCompressor(level=10)
    @test_throws ArgumentError ZlibCompressor(windowbits=16)
    @test_throws ArgumentError ZlibDecompressor(windowbits=16)
end

@testset "Deflate Codec" begin
    codec = DeflateCompressor()
    @test codec isa DeflateCompressor
    @test occursin(r"^(CodecZlib\.)?DeflateCompressor\(level=-1, windowbits=-\d+\)$", sprint(show, codec))
    @test CodecZlib.initialize(codec) === nothing
    # FIXME: This test fails.
    #@test CodecZlib.finalize(codec) === nothing

    codec = DeflateDecompressor()
    @test codec isa DeflateDecompressor
    @test occursin(r"^(CodecZlib\.)?DeflateDecompressor\(windowbits=-\d+\)$", sprint(show, codec))
    @test CodecZlib.initialize(codec) === nothing
    @test CodecZlib.finalize(codec) === nothing

    test_roundtrip_read(DeflateCompressorStream, DeflateDecompressorStream)
    test_roundtrip_write(DeflateCompressorStream, DeflateDecompressorStream)
    test_roundtrip_lines(DeflateCompressorStream, DeflateDecompressorStream)
    test_roundtrip_transcode(DeflateCompressor, DeflateDecompressor)

    @test DeflateCompressorStream <: TranscodingStream
    @test DeflateDecompressorStream <: TranscodingStream

    @test_throws ArgumentError DeflateCompressor(level=10)
    @test_throws ArgumentError DeflateCompressor(windowbits=16)
    @test_throws ArgumentError DeflateDecompressor(windowbits=16)
end

# Test APIs of TranscodingStreams.jl using the gzip compressor/decompressor.
@testset "TranscodingStreams" begin
    TranscodingStreams.test_chunked_read(GzipCompressor, GzipDecompressor)
    TranscodingStreams.test_chunked_write(GzipCompressor, GzipDecompressor)
    TranscodingStreams.test_roundtrip_fileio(GzipCompressor, GzipDecompressor)

    @testset "seek" begin
        data = transcode(GzipCompressor, Vector(b"abracadabra"))
        stream = TranscodingStream(GzipDecompressor(), IOBuffer(data))
        seekstart(stream)
        @test read(stream, 3) == b"abr"
        seekstart(stream)
        @test read(stream, 3) == b"abr"
        seekend(stream)
        #@test eof(stream)
    end

    @testset "panic" begin
        stream = TranscodingStream(GzipDecompressor(), IOBuffer("some invalid data"))
        @test_throws ErrorException read(stream)
        @test_throws ArgumentError eof(stream)
    end

    testfile = joinpath(dirname(@__FILE__), "abra.gz")

    @testset "open" begin
        open(GzipDecompressorStream, testfile) do stream
            @test read(stream) == b"abracadabra"
        end
    end

    @testset "stats" begin
        size = filesize(testfile)
        stream = GzipDecompressorStream(open(testfile))
        stats = TranscodingStreams.stats(stream)
        @test stats.in == 0
        @test stats.out == 0
        @test stats.transcoded_in == 0
        @test stats.transcoded_out == 0
        read(stream, UInt8)
        stats = TranscodingStreams.stats(stream)
        @test stats.in == size
        @test stats.out == 1
        @test stats.transcoded_in == size
        @test stats.transcoded_out == 11
        close(stream)
        @test_throws ArgumentError TranscodingStreams.stats(stream)

        buf = IOBuffer()
        stream = GzipCompressorStream(buf)
        stats = TranscodingStreams.stats(stream)
        @test stats.in == 0
        @test stats.out == 0
        @test stats.transcoded_in == 0
        @test stats.transcoded_out == 0
        write(stream, b"abracadabra")
        stats = TranscodingStreams.stats(stream)
        @test stats.in == 11
        @test stats.out == 0
        @test stats.transcoded_in == 0
        @test stats.transcoded_out == 0
        write(stream, TranscodingStreams.TOKEN_END)
        flush(stream)
        stats = TranscodingStreams.stats(stream)
        @test stats.in == 11
        @test stats.out == position(buf)
        @test stats.transcoded_in == 11
        @test stats.transcoded_out == position(buf)
        close(stream)
        @test_throws ArgumentError TranscodingStreams.stats(stream)
    end
end


text:
# Core types and definitions

if VERSION < v"0.5.0-dev"
    macro pure(ex)
        esc(ex)
    end
else
    using Base: @pure
end

const Symbols = Tuple{Symbol,Vararg{Symbol}}

@doc """
Type-stable axis-specific indexing and identification with a
parametric type.

### Type parameters

```julia
immutable Axis{name,T}
```
* `name` : the name of the axis, a Symbol
* `T` : the type of the axis

### Constructors

```julia
Axis{name}(I)
```

### Arguments

* `name` : the axis name Symbol or integer dimension
* `I` : the indexer, any indexing type that the axis supports

### Examples

Here is an example with a Dimensional axis representing a time
sequence along rows and a Categorical axis of Symbols for column
headers.

```julia
A = AxisArray(reshape(1:60, 12, 5), .1:.1:1.2, [:a, :b, :c, :d, :e])
A[Axis{:col}(2)] # grabs the second column
A[Axis{:col}(:b)] # Same as above, grabs column :b (the second column)
A[Axis{:row}(2)] # grabs the second row
A[Axis{2}(2:5)] # grabs the second through 5th columns
```

""" ->
immutable Axis{name,T}
    val::T
end
# Constructed exclusively through Axis{:symbol}(...) or Axis{1}(...)
(::Type{Axis{name}}){name,T}(I::T=()) = Axis{name,T}(I)
Base.:(==){name}(A::Axis{name}, B::Axis{name}) = A.val == B.val
Base.hash{name}(A::Axis{name}, hx::UInt) = hash(A.val, hash(name, hx))
axistype{name,T}(::Axis{name,T}) = T
axistype{name,T}(::Type{Axis{name,T}}) = T
# Pass indexing and related functions straight through to the wrapped value
# TODO: should Axis be an AbstractArray? AbstractArray{T,0} for scalar T?
Base.getindex(A::Axis, i...) = A.val[i...]
Base.eltype{_,T}(::Type{Axis{_,T}}) = eltype(T)
Base.size(A::Axis) = size(A.val)
Base.endof(A::Axis) = length(A)
Base.indices(A::Axis) = indices(A.val)
Base.indices(A::Axis, d) = indices(A.val, d)
Base.length(A::Axis) = length(A.val)
(A::Axis{name}){name}(i) = Axis{name}(i)
Base.convert{name,T}(::Type{Axis{name,T}}, ax::Axis{name,T}) = ax
Base.convert{name,T}(::Type{Axis{name,T}}, ax::Axis{name}) = Axis{name}(convert(T, ax.val))

@doc """
An AxisArray is an AbstractArray that wraps another AbstractArray and
adds axis names and values to each array dimension. AxisArrays can be indexed
by using the named axes as an alternative to positional indexing by
dimension. Other advanced indexing along axis values are also provided.

### Type parameters

The AxisArray contains several type parameters:

```julia
immutable AxisArray{T,N,D,Ax} <: AbstractArray{T,N}
```
* `T` : the elemental type of the AbstractArray
* `N` : the number of dimensions
* `D` : the type of the wrapped AbstractArray
* `Ax` : the names and types of the axes, as a (specialized) NTuple{N, Axis}

### Constructors

```julia
AxisArray(A::AbstractArray, axes::Axis...)
AxisArray(A::AbstractArray, names::Symbol...)
AxisArray(A::AbstractArray, vectors::AbstractVector...)
AxisArray(A::AbstractArray, (names...,), (steps...,), [(offsets...,)])
```

### Arguments

* `A::AbstractArray` : the wrapped array data
* `axes` or `names` or `vectors` : dimensional information for the wrapped array

The dimensional information may be passed in one of three ways and is
entirely optional. When the axis name or value is missing for a
dimension, a default is substituted. The default axis names for
dimensions `(1, 2, 3, 4, 5, ...)` are `(:row, :col, :page, :dim_4,
:dim_5, ...)`. The default axis values are `indices(A, d)` for each
missing dimension `d`.

### Indexing

Indexing returns a view into the original data. The returned view is a
new AxisArray that wraps a SubArray. Indexing should be type
stable. Use `Axis{axisname}(idx)` to index based on a specific
axis. `axisname` is a Symbol specifying the axis to index/slice, and
`idx` is a normal indexing object (`Int`, `Array{Int,1}`, etc.) or a
custom indexing type for that particular type of axis.

Two main types of axes supported by default include:

* Categorical axis -- These are vectors of labels, normally Symbols or
  strings. Elements or slices can be indexed by elements or vectors
  of elements.

* Dimensional axis -- These are sorted vectors or iterators that can
  be indexed by `ClosedInterval()`. These are commonly used for sequences of
  times or date-times. For regular sample rates, ranges can be used.

User-defined axis types can be added along with custom indexing
behaviors. To add add a custom type as a Categorical or Dimensional
axis, add a trait using `AxisArrays.axistrait`. Here is the example of
adding a custom Dimensional axis:

```julia
AxisArrays.axistrait(v::MyCustomAxis) = AxisArrays.Dimensional
```

For more advanced indexing, you can define custom methods for
`AxisArrays.axisindexes`.

### Examples

Here is an example with a Dimensional axis representing a time
sequence along rows (it's a FloatRange) and a Categorical axis of
Symbols for column headers.

```julia
A = AxisArray(reshape(1:15, 5, 3), Axis{:time}(.1:.1:0.5), Axis{:col}([:a, :b, :c]))
A[Axis{:time}(1:3)]   # equivalent to A[1:3,:]
A[Axis{:time}(ClosedInterval(.2,.4))] # restrict the AxisArray along the time axis
A[ClosedInterval(0.,.3), [:a, :c]]   # select an interval and two columns
```

""" ->
immutable AxisArray{T,N,D,Ax} <: AbstractArray{T,N}
    data::D  # D <:AbstractArray, enforced in constructor to avoid dispatch bugs (https://github.com/JuliaLang/julia/issues/6383)
    axes::Ax # Ax<:NTuple{N, Axis}, but with specialized Axis{...} types
    (::Type{AxisArray{T,N,D,Ax}}){T,N,D,Ax}(data::AbstractArray{T,N}, axs::Tuple{Vararg{Axis,N}}) = new{T,N,D,Ax}(data, axs)
end

# Helper functions: Default axis names (if not provided)
_defaultdimname(i) = i == 1 ? (:row) : i == 2 ? (:col) : i == 3 ? (:page) : Symbol(:dim_, i)
# Why doesn't @pure work here?
@generated function _nextaxistype{M}(axs::NTuple{M,Axis})
    name = _defaultdimname(M+1)
    :(Axis{$(Expr(:quote, name))})
end

"""
    default_axes(A::AbstractArray)
    default_axes(A::AbstractArray, axs)

Return a tuple of Axis objects that appropriately index into the array A.

The optional second argument can take a tuple of vectors or axes, which will be
wrapped with the appropriate axis name, and it will ensure no axis goes beyond
the dimensionality of the array A.
"""
@inline default_axes(A::AbstractArray, args=indices(A)) = _default_axes(A, args, ())
_default_axes{T,N}(A::AbstractArray{T,N}, args::Tuple{}, axs::NTuple{N,Axis}) = axs
_default_axes{T,N}(A::AbstractArray{T,N}, args::Tuple{Any, Vararg{Any}}, axs::NTuple{N,Axis}) = throw(ArgumentError("too many axes provided"))
_default_axes{T,N}(A::AbstractArray{T,N}, args::Tuple{Axis, Vararg{Any}}, axs::NTuple{N,Axis}) = throw(ArgumentError("too many axes provided"))
@inline _default_axes{T,N}(A::AbstractArray{T,N}, args::Tuple{}, axs::Tuple) =
    _default_axes(A, args, (axs..., _nextaxistype(axs)(indices(A, length(axs)+1))))
@inline _default_axes{T,N}(A::AbstractArray{T,N}, args::Tuple{Any, Vararg{Any}}, axs::Tuple) =
    _default_axes(A, Base.tail(args), (axs..., _nextaxistype(axs)(args[1])))
@inline _default_axes{T,N}(A::AbstractArray{T,N}, args::Tuple{Axis, Vararg{Any}}, axs::Tuple) =
    _default_axes(A, Base.tail(args), (axs..., args[1]))

# Axis consistency checks — ensure sizes match and the names are unique
@inline checksizes(axs, sz) =
    (length(axs[1]) == sz[1]) & checksizes(tail(axs), tail(sz))
checksizes(::Tuple{}, sz) = true
@inline function checknames(name::Symbol, names...)
    matches = false
    for n in names
        matches |= name == n
    end
    matches && throw(ArgumentError("axis name :$name is used more than once"))
    checknames(names...)
end
checknames(name, names...) = throw(ArgumentError("the Axis names must be Symbols"))
checknames() = ()

# The primary AxisArray constructors — specify an array to wrap and the axes
AxisArray(A::AbstractArray, vects::Union{AbstractVector, Axis}...) = AxisArray(A, vects)
AxisArray(A::AbstractArray, vects::Tuple{Vararg{Union{AbstractVector, Axis}}}) = AxisArray(A, default_axes(A, vects))
function AxisArray{T,N}(A::AbstractArray{T,N}, axs::NTuple{N,Axis})
    checksizes(axs, _size(A)) || throw(ArgumentError("the length of each axis must match the corresponding size of data"))
    checknames(axisnames(axs...)...)
    AxisArray{T,N,typeof(A),typeof(axs)}(A, axs)
end

# Simple non-type-stable constructors to specify names as symbols
AxisArray(A::AbstractArray) = AxisArray(A, ()) # Disambiguation
AxisArray(A::AbstractArray, names::Symbol...)         = (inds = indices(A); AxisArray(A, ntuple(i->Axis{names[i]}(inds[i]), length(names))))
function AxisArray{T,N}(A::AbstractArray{T,N}, names::NTuple{N,Symbol}, steps::NTuple{N,Number}, offsets::NTuple{N,Number}=map(zero, steps))
    axs = ntuple(i->Axis{names[i]}(range(offsets[i], steps[i], size(A,i))), N)
    AxisArray(A, axs...)
end

# Traits
immutable HasAxes{B} end
HasAxes{A<:AxisArray}(::Type{A}) = HasAxes{true}()
HasAxes{A<:AbstractArray}(::Type{A}) = HasAxes{false}()
HasAxes(A::AbstractArray) = HasAxes(typeof(A))

# Axis definitions
@doc """
    axisdim(::AxisArray, ::Axis) -> Int
    axisdim(::AxisArray, ::Type{Axis}) -> Int

Given an AxisArray and an Axis, return the integer dimension of
the Axis within the array.
""" ->
axisdim(A::AxisArray, ax::Axis) = axisdim(A, typeof(ax))
@generated function axisdim{T<:Axis}(A::AxisArray, ax::Type{T})
    dim = axisdim(A, T)
    :($dim)
end
# The actual computation is done in the type domain, which is a little tricky
# due to type invariance.
axisdim{T,N,D,Ax,name,S}(A::Type{AxisArray{T,N,D,Ax}}, ::Type{Axis{name,S}}) = axisdim(A, Axis{name})
function axisdim{T,N,D,Ax,name}(::Type{AxisArray{T,N,D,Ax}}, ::Type{Axis{name}})
    isa(name, Int) && return name <= N ? name : error("axis $name greater than array dimensionality $N")
    names = axisnames(Ax)
    idx = findfirst(names, name)
    idx == 0 && error("axis $name not found in array axes $names")
    idx
end

# Base definitions that aren't provided by AbstractArray
@inline Base.size(A::AxisArray) = size(A.data)
@inline Base.size(A::AxisArray, Ax::Axis) = size(A.data, axisdim(A, Ax))
@inline Base.size{Ax<:Axis}(A::AxisArray, ::Type{Ax}) = size(A.data, axisdim(A, Ax))
@inline Base.indices(A::AxisArray) = indices(A.data)
@inline Base.indices(A::AxisArray, Ax::Axis) = indices(A.data, axisdim(A, Ax))
@inline Base.indices{Ax<:Axis}(A::AxisArray, ::Type{Ax}) = indices(A.data, axisdim(A, Ax))
Base.convert{T,N}(::Type{Array{T,N}}, A::AxisArray{T,N}) = convert(Array{T,N}, A.data)
Base.parent(A::AxisArray) = A.data
# Similar is tricky. If we're just changing the element type, it can stay as an
# AxisArray. But if we're changing dimensions, there's no way it can know how
# to keep track of the axes, so just punt and return a regular old Array.
# TODO: would it feel more consistent to return an AxisArray without any axes?
Base.similar{S}(A::AxisArray, ::Type{S})       = (d = similar(A.data, S); AxisArray(d, A.axes))
Base.similar{S,N}(A::AxisArray, ::Type{S}, dims::Dims{N}) = similar(A.data, S, dims)
# If, however, we pass Axis objects containing the new axis for that dimension,
# we can return a similar AxisArray with an appropriately modified size
Base.similar{T}(A::AxisArray{T}, ax1::Axis, axs::Axis...) = similar(A, T, (ax1, axs...))
Base.similar{S}(A::AxisArray, ::Type{S}, ax1::Axis, axs::Axis...) = similar(A, S, (ax1, axs...))
@generated function Base.similar{T,S,N}(A::AxisArray{T,N}, ::Type{S}, axs::Tuple{Axis,Vararg{Axis}})
    inds = Expr(:tuple)
    ax = Expr(:tuple)
    for d=1:N
        push!(inds.args, :(indices(A, Axis{$d})))
        push!(ax.args, :(axes(A, Axis{$d})))
    end
    to_delete = Int[]
    for i=1:length(axs.parameters)
        a = axs.parameters[i]
        d = axisdim(A, a)
        axistype(a) <: Tuple{} && push!(to_delete, d)
        inds.args[d] = :(indices(axs[$i].val, 1))
        ax.args[d] = :(axs[$i])
    end
    sort!(to_delete)
    deleteat!(inds.args, to_delete)
    deleteat!(ax.args, to_delete)
    quote
        d = similar(A.data, S, $inds)
        AxisArray(d, $ax)
    end
end

# These methods allow us to preserve the AxisArray under reductions
# Note that we only extend the following two methods, and then have it
# dispatch to package-local `reduced_indices` and `reduced_indices0`
# methods. This avoids a whole slew of ambiguities.
if VERSION == v"0.5.0"
    Base.reduced_dims(A::AxisArray, region)  = reduced_indices(axes(A), region)
    Base.reduced_dims0(A::AxisArray, region) = reduced_indices0(axes(A), region)
else
    Base.reduced_indices(A::AxisArray, region)  = reduced_indices(axes(A), region)
    Base.reduced_indices0(A::AxisArray, region) = reduced_indices0(axes(A), region)
end

reduced_indices{N}(axs::Tuple{Vararg{Axis,N}}, ::Tuple{})  = axs
reduced_indices0{N}(axs::Tuple{Vararg{Axis,N}}, ::Tuple{}) = axs
reduced_indices{N}(axs::Tuple{Vararg{Axis,N}}, region::Integer) =
    reduced_indices(axs, (region,))
reduced_indices0{N}(axs::Tuple{Vararg{Axis,N}}, region::Integer) =
    reduced_indices0(axs, (region,))

reduced_indices{N}(axs::Tuple{Vararg{Axis,N}}, region::Dims) =
    map((ax,d)->d∈region ? reduced_axis(ax) : ax, axs, ntuple(identity, Val{N}))
reduced_indices0{N}(axs::Tuple{Vararg{Axis,N}}, region::Dims) =
    map((ax,d)->d∈region ? reduced_axis0(ax) : ax, axs, ntuple(identity, Val{N}))

@inline reduced_indices{Ax<:Axis}(axs::Tuple{Vararg{Axis}}, region::Type{Ax}) =
    _reduced_indices(reduced_axis, (), region, axs...)
@inline reduced_indices0{Ax<:Axis}(axs::Tuple{Vararg{Axis}}, region::Type{Ax}) =
    _reduced_indices(reduced_axis0, (), region, axs...)
@inline reduced_indices(axs::Tuple{Vararg{Axis}}, region::Axis) =
    _reduced_indices(reduced_axis, (), region, axs...)
@inline reduced_indices0(axs::Tuple{Vararg{Axis}}, region::Axis) =
    _reduced_indices(reduced_axis0, (), region, axs...)

reduced_indices(axs::Tuple{Vararg{Axis}}, region::Tuple) =
    reduced_indices(reduced_indices(axs, region[1]), tail(region))
reduced_indices(axs::Tuple{Vararg{Axis}}, region::Tuple{Vararg{Axis}}) =
    reduced_indices(reduced_indices(axs, region[1]), tail(region))
reduced_indices0(axs::Tuple{Vararg{Axis}}, region::Tuple) =
    reduced_indices0(reduced_indices0(axs, region[1]), tail(region))
reduced_indices0(axs::Tuple{Vararg{Axis}}, region::Tuple{Vararg{Axis}}) =
    reduced_indices0(reduced_indices0(axs, region[1]), tail(region))

@pure samesym{n1,n2}(::Type{Axis{n1}}, ::Type{Axis{n2}}) = Val{n1==n2}()
samesym{n1,n2,T1,T2}(::Type{Axis{n1,T1}}, ::Type{Axis{n2,T2}}) = samesym(Axis{n1},Axis{n2})
samesym{n1,n2}(::Type{Axis{n1}}, ::Axis{n2}) = samesym(Axis{n1}, Axis{n2})
samesym{n1,n2}(::Axis{n1}, ::Type{Axis{n2}}) = samesym(Axis{n1}, Axis{n2})
samesym{n1,n2}(::Axis{n1}, ::Axis{n2}) = samesym(Axis{n1}, Axis{n2})

@inline _reduced_indices{Ax<:Axis}(f, out, chosen::Type{Ax}, ax::Axis, axs...) =
    __reduced_indices(f, out, samesym(chosen, ax), chosen, ax, axs)
@inline _reduced_indices(f, out, chosen::Axis, ax::Axis, axs...) =
    __reduced_indices(f, out, samesym(chosen, ax), chosen, ax, axs)
_reduced_indices(f, out, chosen) = out

@inline __reduced_indices(f, out, ::Val{true}, chosen, ax, axs) =
    _reduced_indices(f, (out..., f(ax)), chosen, axs...)
@inline __reduced_indices(f, out, ::Val{false}, chosen, ax, axs) =
    _reduced_indices(f, (out..., ax), chosen, axs...)

reduced_axis(ax) = ax(oftype(ax.val, Base.OneTo(1)))
reduced_axis0(ax) = ax(oftype(ax.val, length(ax.val) == 0 ? Base.OneTo(0) : Base.OneTo(1)))

function Base.permutedims(A::AxisArray, perm)
    p = permutation(perm, axisnames(A))
    AxisArray(permutedims(A.data, p), axes(A)[[p...]])
end

Base.transpose{T}(A::AxisArray{T,2})  = AxisArray(transpose(A.data), A.axes[2], A.axes[1])
Base.ctranspose{T}(A::AxisArray{T,2}) = AxisArray(ctranspose(A.data), A.axes[2], A.axes[1])
Base.transpose{T}(A::AxisArray{T,1})  = AxisArray(transpose(A.data), Axis{:transpose}(Base.OneTo(1)), A.axes[1])
Base.ctranspose{T}(A::AxisArray{T,1}) = AxisArray(ctranspose(A.data), Axis{:transpose}(Base.OneTo(1)), A.axes[1])

Base.map!{F}(f::F, A::AxisArray) = (map!(f, A.data); A)
Base.map(f, A::AxisArray) = AxisArray(map(f, A.data), A.axes...)

function Base.map!{F,T,N,D,Ax<:Tuple{Vararg{Axis}}}(f::F, dest::AxisArray{T,N,D,Ax},
                                                  As::AxisArray{T,N,D,Ax}...)
    matchingdims((dest, As...)) || error("All axes must be identically-valued")
    data = map(a -> a.data, As)
    map!(f, dest.data, data...)
    return dest
end

function Base.map{T,N,D,Ax<:Tuple{Vararg{Axis}}}(f, As::AxisArray{T,N,D,Ax}...)
    matchingdims(As) || error("All axes must be identically-valued")
    data = map(a -> a.data, As)
    return AxisArray(map(f, data...), As[1].axes...)
end

permutation(to::Union{AbstractVector{Int},Tuple{Int,Vararg{Int}}}, from::Symbols) = to

"""
    permutation(to, from) -> p

Calculate the permutation of labels in `from` to produce the order in
`to`. Any entries in `to` that are missing in `from` will receive an
index of 0. Any entries in `from` that are missing in `to` will have
their indices appended to the end of the permutation. Consequently,
the length of `p` is equal to the longer of `to` and `from`.
"""
function permutation(to::Symbols, from::Symbols)
    n = length(to)
    nf = length(from)
    li = linearindices(from)
    d = Dict(from[i]=>i for i in li)
    covered = similar(dims->falses(length(li)), li)
    ind = Array{Int}(max(n, nf))
    for (i,toi) in enumerate(to)
        j = get(d, toi, 0)
        ind[i] = j
        if j != 0
            covered[j] = true
        end
    end
    k = n
    for i in li
        if !covered[i]
            d[from[i]] != i && throw(ArgumentError("$(from[i]) is a duplicated argument"))
            k += 1
            k > nf && throw(ArgumentError("no incomplete containment allowed in $to and $from"))
            ind[k] = i
        end
    end
    ind
end

function Base.squeeze(A::AxisArray, dims::Dims)
    keepdims = setdiff(1:ndims(A), dims)
    AxisArray(squeeze(A.data, dims), axes(A)[keepdims])
end
# This version is type-stable
function Base.squeeze{Ax<:Axis}(A::AxisArray, ::Type{Ax})
    dim = axisdim(A, Ax)
    AxisArray(squeeze(A.data, dim), dropax(Ax, axes(A)...))
end

@inline dropax(ax, ax1, axs...) = (ax1, dropax(ax, axs...)...)
@inline dropax{name}(ax::Axis{name}, ax1::Axis{name}, axs...) = dropax(ax, axs...)
@inline dropax{name}(ax::Type{Axis{name}}, ax1::Axis{name}, axs...) = dropax(ax, axs...)
@inline dropax{name,T}(ax::Type{Axis{name,T}}, ax1::Axis{name}, axs...) = dropax(ax, axs...)
dropax(ax) = ()

# A simple display method to include axis information. It might be nice to
# eventually display the axis labels alongside the data array, but that is
# much more difficult.
function summaryio(io::IO, A::AxisArray)
    _summary(io, A)
    for (name, val) in zip(axisnames(A), axisvalues(A))
        print(io, "    :$name, ")
        show(IOContext(io, :limit=>true), val)
        println(io)
    end
    print(io, "And data, a ", summary(A.data))
end
_summary{T,N}(io, A::AxisArray{T,N}) = println(io, "$N-dimensional AxisArray{$T,$N,...} with axes:")

function Base.summary(A::AxisArray)
    io = IOBuffer()
    summaryio(io, A)
    String(io)
end

# Custom methods specific to AxisArrays
@doc """
    axisnames(A::AxisArray)           -> (Symbol...)
    axisnames(::Type{AxisArray{...}}) -> (Symbol...)
    axisnames(ax::Axis...)            -> (Symbol...)
    axisnames(::Type{Axis{...}}...)   -> (Symbol...)

Returns the axis names of an AxisArray or list of Axises as a tuple of Symbols.
""" ->
axisnames{T,N,D,Ax}(::AxisArray{T,N,D,Ax})       = _axisnames(Ax)
axisnames{T,N,D,Ax}(::Type{AxisArray{T,N,D,Ax}}) = _axisnames(Ax)
axisnames{Ax<:Tuple{Vararg{Axis}}}(::Type{Ax})   = _axisnames(Ax)
@pure _axisnames(Ax) = axisnames(Ax.parameters...)
axisnames() = ()
@inline axisnames{name  }(::Axis{name},         B::Axis...) = tuple(name, axisnames(B...)...)
@inline axisnames{name  }(::Type{Axis{name}},   B::Type...) = tuple(name, axisnames(B...)...)
@inline axisnames{name,T}(::Type{Axis{name,T}}, B::Type...) = tuple(name, axisnames(B...)...)

axisname{name,T}(::Type{Axis{name,T}}) = name
axisname{name  }(::Type{Axis{name  }}) = name
axisname(ax::Axis) = axisname(typeof(ax))

@doc """
    axisvalues(A::AxisArray)           -> (AbstractVector...)
    axisvalues(ax::Axis...)            -> (AbstractVector...)

Returns the axis values of an AxisArray or list of Axises as a tuple of vectors.
""" ->
axisvalues(A::AxisArray) = axisvalues(A.axes...)
axisvalues() = ()
axisvalues(ax::Axis, axs::Axis...) = tuple(ax.val, axisvalues(axs...)...)

@doc """
    axes(A::AxisArray) -> (Axis...)
    axes(A::AxisArray, ax::Axis) -> Axis
    axes(A::AxisArray, dim::Int) -> Axis

Returns the tuple of axis vectors for an AxisArray. If an specific `Axis` is
specified, then only that axis vector is returned.  Note that when extracting a
single axis vector, `axes(A, Axis{1})`) is type-stable and will perform better
than `axes(A)[1]`.

For an AbstractArray without `Axis` information, `axes` returns the
default axes, i.e., those that would be produced by `AxisArray(A)`.
""" ->
axes(A::AxisArray) = A.axes
axes(A::AxisArray, dim::Int) = A.axes[dim]
axes(A::AxisArray, ax::Axis) = axes(A, typeof(ax))
@generated function axes{T<:Axis}(A::AxisArray, ax::Type{T})
    dim = axisdim(A, T)
    :(A.axes[$dim])
end
axes(A::AbstractArray) = default_axes(A)
axes(A::AbstractArray, dim::Int) = default_axes(A)[dim]

### Axis traits ###
@compat abstract type AxisTrait end
immutable Dimensional <: AxisTrait end
immutable Categorical <: AxisTrait end
immutable Unsupported <: AxisTrait end

axistrait(::Any) = Unsupported
axistrait(ax::Axis) = axistrait(ax.val)
axistrait{T<:Union{Number, Dates.AbstractTime}}(::AbstractVector{T}) = Dimensional
axistrait{T<:Union{Symbol, AbstractString}}(::AbstractVector{T}) = Categorical

checkaxis(ax::Axis) = checkaxis(ax.val)
checkaxis(ax) = checkaxis(axistrait(ax), ax)
checkaxis(::Type{Unsupported}, ax) = nothing # TODO: warn or error?
# Dimensional axes must be monotonically increasing
checkaxis(::Type{Dimensional}, ax) = issorted(ax) || throw(ArgumentError("Dimensional axes must be monotonically increasing"))
# Categorical axes must simply be unique
function checkaxis(::Type{Categorical}, ax)
    seen = Set{eltype(ax)}()
    for elt in ax
        if elt in seen
            throw(ArgumentError("Categorical axes must be unique"))
        end
        push!(seen, elt)
    end
end

_length(A::AbstractArray) = length(linearindices(A))
_length(A) = length(A)
_size(A::AbstractArray) = map(length, indices(A))
_size(A) = size(A)
_size(A::AbstractArray, d) = length(indices(A, d))
_size(A, d) = size(A, d)


text:
mutable struct StructTreeRoot
    k::CosObject                                    # Dict, Array or null
    idTree::Nullable{CosTreeNode{CDTextString}}     # Name tree
    parentTree::Nullable{CosTreeNode{Int}}          # Number tree
    parentTreeNext::Int
    roleMap::CosObject                              # Dict or null
    classMap::CosObject                             # Dict or null
end

mutable struct StructElem
    s::CosName
    p::CosObject                                    # Indirect Dict
    id::Vector{UInt8}
    pg::CosObject                                   # Dict
    k::Union{StructElem, CosObject}
    a::CosObject
    r::Int
    t::CDTextString
    lang::CDTextString
    alt::CDTextString
    e::CDTextString
    actualText::CDTextString
end

function get_structure_tree_root(obj::CosObject)
    @assert cn"StructTreeRoot" = get(obj, cn"Type")
    k = get(obj, cn"K")
    ptreeobj = get(obj, cn"ParentTree")
    idtreeobj = get(obj, cn"IDTree")
    prtNext = get(obj, cn"ParentTreeNextKey")
    parentTreeNext = (prtNext === CosNull) ? -1 : get(prtNext)

    parentTree = ptreeobj === CosNull ? Nullable{CosTreeNode{Int}}() :
                                        Nullable(createTreeNode(Int, ptreeobj))
    idTree    = idtreeobj === CosNull ? Nullable{CosTreeNode{String}}() :
                                        Nullable(createTreeNode(String, idtreeobj))
    roleMap  = get(obj, cn"RoleMap")
    classMap = get(obj, cn"ClassMap")

    return StructTreeRoot(k, idTree, parentTree, parentTreeNext, roleMap, classMap)
end

function get_structure_elem(obj::CosObject)
    @assert cn"StructElem" = get(obj, cn"Type")
    s = get(obj, cn"S")
    p = get(obj, cn"P")
    id = get(obj, cn"ID") |> get
    pg = get(obj, cn"Pg")
    k::Union{StructElem, CosObject}
    a = get(obj, cn"A")
    tobj = get(obj, cn"R")
    r = tobj === CosNull ? 0 : get(tobj)
    tobj = get(obj, cn"T")
    t = tobj === CosNull ? "" : convert(CDTextString, tobj)
    tobj = get(obj, cn"Lang")
    lang = tobj === CosNull ? "" : convert(CDTextString, tobj)
    tobj = get(obj, cn"Alt")
    alt = tobj === CosNull ? "" : convert(CDTextString, tobj)
    tobj = get(obj, cn"E")
    e = tobj === CosNull ? "" : convert(CDTextString, tobj)
    tobj = get(obj, cn"ActualText")
    actualText = tobj === CosNull ? "" : convert(CDTextString, tobj)

    return StructElem(s, p, id, pg, k, a, r, t, lang, alt, e, actualText)
end


text:
function forward_autodiff_derivative(result::DiffResults.DiffResult, f::Function, x::Real)
  ForwardDiff.derivative!(result, f, x)
  return DiffResults.derivative(result)
end

function forward_autodiff_gradient(result::DiffResults.DiffResult, f::Function, x::Vector, cfg::ForwardDiff.GradientConfig)
  result = ForwardDiff.gradient!(result, f, x, cfg)
  return DiffResults.gradient(result)
end

function forward_autodiff_negative_hessian(
  result::DiffResults.DiffResult, f::Function, x::Vector, cfg::ForwardDiff.HessianConfig
)
  ForwardDiff.hessian!(result, f, x, cfg)
  return -DiffResults.hessian(result)
end

function forward_autodiff_upto_derivative(result::DiffResults.DiffResult, f::Function, x::Real)
  ForwardDiff.derivative!(result, f, x)
  return DiffResults.value(result), DiffResults.derivative(result)
end

function forward_autodiff_upto_gradient(
  result::DiffResults.DiffResult, f::Function, x::Vector, cfg::ForwardDiff.GradientConfig
)
  ForwardDiff.gradient!(result, f, x, cfg)
  return DiffResults.value(result), DiffResults.gradient(result)
end

function forward_autodiff_upto_negative_hessian(
  result::DiffResults.DiffResult, f::Function, x::Vector, cfg::ForwardDiff.HessianConfig
)
  ForwardDiff.hessian!(result, f, x, cfg)
  return DiffResults.value(result), DiffResults.gradient(result), -DiffResults.hessian(result)
end