text:
julia> [RpcApi.SimpleOrganism(0x0000000000039c0c,:(function (o::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            if var_284 < var_284
            end
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        function func_264(var_263::Int8=-125)
            var_263 = var_263 + var_263
            Creature.eatUp(o,Int(var_263))
            for i::Int8 = 1:div(var_263,_LOOP_STEPS_DIVIDER)
            end
            Creature.eatDown(o,Int(var_263))
            return var_263
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            local var_402::Bool = false
            return var_230
        end
        function func_189(var_188::Int16=2883)
            o.mem[var_188] = var_188
            o.mem[var_188] = var_188
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            Creature.stepUp(o)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        var_120 = var_120 * var_120
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        Creature.stepLeft(o)
        Creature.stepLeft(o)
        Creature.eatUp(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_117 = var_117 + var_117
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepDown(o)
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,84517,0x00000008,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1920,959],78),RpcApi.SimpleOrganism(0x0000000000039c26,:(fu
nction (o::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        function func_264(var_263::Int8=-125)
            var_263 = var_263 + var_263
            Creature.eatUp(o,Int(var_263))
            for i::Int8 = 1:div(var_263,_LOOP_STEPS_DIVIDER)
            end
            Creature.eatDown(o,Int(var_263))
            return var_263
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            return var_230
        end
        function func_189(var_188::Int16=2883)
            o.mem[var_188] = var_188
            var_188 = if haskey(o.mem,var_188)
                    o.mem[var_188]
                else
                    var_188
                end
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        Creature.stepUp(o)
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        var_124 = var_124 + var_124
        Creature.stepLeft(o)
        Creature.eatUp(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        var_124 = func_142(var_124)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_156)))
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,18,76863,0x00000001,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1913,4],75),RpcApi.SimpleOrganism(0x0000000000039c51,:(func
tion (o::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            if var_284 < var_284
            end
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        function func_264(var_263::Int8=-125)
            var_263 = var_263 + var_263
            Creature.eatUp(o,Int(var_263))
            for i::Int8 = 1:div(var_263,_LOOP_STEPS_DIVIDER)
            end
            Creature.eatDown(o,Int(var_263))
            return var_263
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            var_230 = var_230 | var_230
            return var_230
        end
        function func_189(var_188::Int16=2883)
            var_188 = var_188 * var_188
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            Creature.stepRight(o)
            Creature.stepUp(o)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        Creature.stepUp(o)
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        var_124 = var_124 + var_124
        Creature.stepLeft(o)
        Creature.eatUp(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_156)))
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,59055,0x00000003,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1917,12],76),RpcApi.SimpleOrganism(0x0000000000036952,:(fun
ction (o::Creature.Organism,)
        function func_345(var_343::Int64=8598073464645878164,var_344::Int64=-2115587437940986231)
            Creature.stepUp(o)
            Creature.stepRight(o)
            Creature.stepLeft(o)
            var_344 = var_344 / var_344
            return var_343
        end
        local var_337::ASCIIString = "7A9IyD4t"
        local var_280::Int64 = -2141542542016055773
        function func_273(var_272::Int8=-40)
            for i::Int8 = 1:div(var_272,_LOOP_STEPS_DIVIDER)
            end
            Creature.stepLeft(o)
            Creature.eatLeft(o,Int(var_272))
            Creature.eatDown(o,Int(var_272))
            for i::Int8 = 1:div(var_272,_LOOP_STEPS_DIVIDER)
                Creature.stepRight(o)
            end
            Creature.eatLeft(o,Int(var_272))
            Creature.eatRight(o,Int(var_272))
            Creature.eatRight(o,Int(var_272))
            Creature.stepRight(o)
            return var_272
        end
        local var_243::Bool = false
        function func_142(var_141::Int64=7558744495470982559)
            return var_141
        end
        local var_124::Int64 = -1961703428302216313
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        Creature.eatRight(o,Int(var_117))
        var_280 = func_142(var_124)
        Creature.eatRight(o,Int(var_117))
        Creature.eatDown(o,Int(var_117))
        var_117 = var_117 + var_117
        Creature.eatDown(o,Int(var_117))
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        if var_280 < var_124
        end
        Creature.eatLeft(o,Int(var_117))
        var_243 = var_123 | var_123
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
            Creature.stepDown(o)
        end
        Creature.eatDown(o,Int(var_117))
        Creature.stepUp(o)
        Creature.stepUp(o)
        var_337 = var_337[1:if length(var_337) > length(var_337)
                        0
                    else
                        length(var_337) - length(var_337)
                    end]
        var_280 = var_124 * var_124
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.eatDown(o,Int(var_117))
        var_120 = func_189(var_120)
        Creature.stepUp(o)
        var_120 = if haskey(o.mem,var_120)
                o.mem[var_120]
            else
                var_120
            end
        var_156 = func_286(var_156)
        var_120 = if haskey(o.mem,var_156)
                o.mem[var_156]
            else
                var_120
            end
        Creature.eatUp(o,Int(var_117))
        var_124 = var_124 * var_124
        if var_280 === var_124
            Creature.stepLeft(o)
        end
        var_243 = var_123 * var_243
        var_120 = if haskey(o.mem,var_156)
                o.mem[var_156]
            else
                var_120
            end
        var_120 = if haskey(o.mem,var_156)
                o.mem[var_156]
            else
                var_120
            end
        var_280 = var_124 * var_124
        Creature.eatLeft(o,Int(var_117))
        var_337 = var_337 * var_337
        Creature.stepLeft(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
            local var_369::Int64 = -2529727123571610472
            Creature.stepLeft(o)
        end
        Creature.stepLeft(o)
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
            Creature.stepLeft(o)
        end
        var_123 = var_243 | var_123
        Creature.eatRight(o,Int(var_117))
        var_124 = var_124 * var_280
        return true
    end),[110,300,95,0,1,1,1],56,3006,6,44564,0x000002f4,Dict(0=>0,10070=>10070,-26920=>-26920,-4015=>19308,-29748=>-29748,23323=>23323,19308=>19308,-1631=>-1631,1=>1),[1919,960],73),RpcApi.SimpleOrganism(0x0000000000039c49,:(function (o
::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            Creature.stepLeft(o)
            return var_230
        end
        function func_189(var_188::Int16=2883)
            var_188 = var_188 - var_188
            Creature.stepDown(o)
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        var_120 = var_120 + var_120
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        var_124 = var_124 + var_124
        Creature.stepLeft(o)
        var_280 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.eatLeft(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_156)))
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        Creature.stepDown(o)
        var_243 = var_123 | var_123
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,42815,0x0000000a,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1335,958],68),RpcApi.SimpleOrganism(0x0000000000039c53,:(fu
nction (o::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            return var_230
        end
        function func_189(var_188::Int16=2883)
            o.mem[var_188] = var_188
            Creature.stepLeft(o)
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            Creature.stepUp(o)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        Creature.stepLeft(o)
        Creature.stepUp(o)
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        var_124 = var_124 + var_124
        Creature.stepLeft(o)
        o.mem[var_120] = var_120
        var_124 = var_124 * var_124
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_156)))
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        Creature.stepDown(o)
        var_243 = var_123 | var_123
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,39774,0x00000005,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1915,807],72),RpcApi.SimpleOrganism(0x0000000000039ab8,:(fu
nction (o::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            var_284 = if haskey(o.mem,var_284)
                    o.mem[var_284]
                else
                    var_284
                end
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        function func_264(var_263::Int8=-125)
            var_263 = var_263 + var_263
            Creature.eatUp(o,Int(var_263))
            for i::Int8 = 1:div(var_263,_LOOP_STEPS_DIVIDER)
            end
            Creature.eatDown(o,Int(var_263))
            return var_263
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            return var_230
        end
        function func_189(var_188::Int16=2883)
            o.mem[var_188] = var_188
            var_188 = if haskey(o.mem,var_188)
                    o.mem[var_188]
                else
                    var_188
                end
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            local var_401::Bool = false
            Creature.stepUp(o)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        Creature.stepUp(o)
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        var_124 = var_124 + var_124
        Creature.stepLeft(o)
        Creature.eatUp(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatLeft(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_156)))
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,38473,0x00000003,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1915,6],75),RpcApi.SimpleOrganism(0x0000000000039c3e,:(func
tion (o::Creature.Organism,)
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            if var_284 < var_284
            end
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        function func_264(var_263::Int8=-125)
            var_263 = var_263 + var_263
            Creature.eatUp(o,Int(var_263))
            for i::Int8 = 1:div(var_263,_LOOP_STEPS_DIVIDER)
            end
            Creature.eatDown(o,Int(var_263))
            return var_263
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            local var_402::Bool = false
            return var_230
        end
        function func_189(var_188::Int16=2883)
            var_188 = var_188 / var_188
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            Creature.stepUp(o)
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        var_120 = var_120 * var_120
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.stepLeft(o)
        Creature.stepLeft(o)
        Creature.eatUp(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_117 = var_117 + var_117
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        Creature.eatLeft(o,Int(var_117))
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepDown(o)
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,38291,0x00000008,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1919,959],75),RpcApi.SimpleOrganism(0x0000000000039c5a,:(fu
nction (o::Creature.Organism,)
        local var_280::Int64 = -2141542542016055773
        function func_264(var_263::Int8=-125)
            var_263 = var_263 + var_263
            Creature.eatUp(o,Int(var_263))
            Creature.stepRight(o)
            for i::Int8 = 1:div(var_263,_LOOP_STEPS_DIVIDER)
            end
            Creature.eatDown(o,Int(var_263))
            return var_263
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            return var_230
        end
        function func_189(var_188::Int16=2883)
            Creature.stepDown(o)
            o.mem[var_188] = var_188
            return var_188
        end
        function func_142(var_141::Int64=7558744495470982559)
            local var_403::Bool = false
            return var_141
        end
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_243 = func_232(var_123)
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        Creature.stepUp(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        var_120 = var_120 - var_120
        Creature.stepUp(o)
        var_120 = var_120 * var_120
        var_243 = func_232(var_243)
        Creature.eatRight(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        var_117 = var_117 + var_117
        Creature.stepLeft(o)
        Creature.stepLeft(o)
        Creature.eatUp(o,Int(var_117))
        o.mem[var_120] = var_120
        Creature.stepUp(o)
        Creature.stepRight(o)
        Creature.eatUp(o,Int(var_117))
        Creature.eatUp(o,Int(var_117))
        Creature.eatLeft(o,Int(var_117))
        var_120 = func_286(var_120,var_280)
        Creature.stepRight(o)
        Creature.stepRight(o)
        Creature.stepDown(o)
        Creature.stepDown(o)
        o.mem[var_120] = var_120
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        o.mem[var_120] = var_120
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepRight(o)
        var_124 = Int(Creature.getEnergy(o,Int(var_156),Int(var_120)))
        var_120 = var_120 - var_120
        Creature.eatUp(o,Int(var_117))
        o.mem[var_156] = var_120
        Creature.eatRight(o,Int(var_117))
        var_124 = var_280 - var_124
        Creature.stepDown(o)
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepLeft(o)
        Creature.stepDown(o)
        Creature.eatDown(o,Int(var_117))
        Creature.stepLeft(o)
        var_117 = var_117 + var_117
        Creature.eatDown(o,Int(var_117))
        var_123 = var_243 * var_123
        Creature.eatUp(o,Int(var_117))
        var_120 = var_120 * var_120
        Creature.stepLeft(o)
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
        end
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepDown(o)
        Creature.stepUp(o)
        Creature.stepUp(o)
        Creature.eatLeft(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],4,8554,37,36415,0x0000000e,Dict(0=>0,-8030=>-8030,10070=>10070,-26920=>-26920,-4015=>-4015,-29748=>-29748,23323=>23323,19308=>0,-1631=>-1631,1=>1),[1610,326],76),RpcApi.SimpleOrganism(0x0000000000039aa1,:(fu
nction (o::Creature.Organism,)
        function func_399(var_397::Int16=-13358,var_398::Bool=false)
            var_397 = var_397 - var_397
            return var_397
        end
        local var_360::Int16 = 18308
        local var_355::ASCIIString = "dyiLP4Yk"
        local var_349::Int8 = -22
        function func_345(var_343::Int64=8598073464645878164,var_344::Int64=-2115587437940986231)
            return var_343
        end
        local var_337::ASCIIString = "7A9IyD4t"
        local var_323::Int16 = -30014
        function func_286(var_284::Int16=2081,var_285::Int64=9145930075523767031)
            return var_284
        end
        local var_280::Int64 = -2141542542016055773
        function func_273(var_272::Int8=-40)
            Creature.eatLeft(o,Int(var_272))
            Creature.eatLeft(o,Int(var_272))
            Creature.eatDown(o,Int(var_272))
            Creature.eatDown(o,Int(var_272))
            for i::Int8 = 1:div(var_272,_LOOP_STEPS_DIVIDER)
            end
            return var_272
        end
        local var_243::Bool = false
        function func_232(var_230::Bool=false,var_231::Int16=-29748)
            var_230 = var_230 * var_230
            return var_230
        end
        function func_142(var_141::Int64=7558744495470982559)
            return var_141
        end
        local var_124::Int64 = -1961703428302216313
        local var_123::Bool = true
        local var_120::Int16 = -4015
        local var_117::Int8 = 61
        local var_156::Int16 = 19308
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_120)))
        var_124 = var_280 * var_124
        Creature.eatRight(o,Int(var_117))
        var_280 = func_142(var_124)
        Creature.eatRight(o,Int(var_117))
        Creature.eatDown(o,Int(var_117))
        var_117 = var_117 + var_117
        var_120 = if haskey(o.mem,var_156)
                o.mem[var_156]
            else
                var_120
            end
        Creature.eatUp(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        var_355 = var_355[if length(var_337) > length(var_355)
                        1
                    else
                        length(var_337)
                    end:if length(var_337) > length(var_355) > 0
                        0
                    else
                        end
                    end]
        o.mem[var_360] = var_120
        var_124 = Int(Creature.getEnergy(o,Int(var_120),Int(var_156)))
        Creature.eatLeft(o,Int(var_117))
        Creature.eatDown(o,Int(var_117))
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
            Creature.stepLeft(o)
        end
        if var_123 == var_243
            local var_392::ASCIIString = "218rWAYM"
            Creature.stepDown(o)
            Creature.stepDown(o)
            Creature.stepRight(o)
        end
        var_337 = var_337[1:if length(var_355) > length(var_337) > 0
                        0
                    else
                        div(length(var_337),length(var_355))
                    end]
        var_337 = var_337[1:if length(var_337) > length(var_337) > 0
                        0
                    else
                        div(length(var_337),length(var_337))
                    end]
        var_120 = var_120 / var_120
        Creature.eatLeft(o,Int(var_349))
        var_117 = var_349 / var_349
        Creature.eatUp(o,Int(var_117))
        var_349 = var_117 / var_349
        Creature.eatUp(o,Int(var_349))
        if var_355 > var_355
            Creature.stepUp(o)
            Creature.stepLeft(o)
        end
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        Creature.eatDown(o,Int(var_117))
        var_120 = if haskey(o.mem,var_120)
                o.mem[var_120]
            else
                var_120
            end
        var_280 = var_280 / var_124
        Creature.eatDown(o,Int(var_117))
        Creature.eatRight(o,Int(var_117))
        Creature.stepDown(o)
        Creature.stepRight(o)
        var_120 = var_156 + var_120
        for i::Int8 = 1:div(var_117,_LOOP_STEPS_DIVIDER)
            local var_390::Int64 = -7544227345049730690
            Creature.stepRight(o)
            Creature.stepDown(o)
            Creature.stepUp(o)
        end
        var_120 = var_120 / var_323
        Creature.stepLeft(o)
        o.mem[var_120] = var_120
        Creature.stepLeft(o)
        var_349 = var_117 / var_349
        Creature.stepLeft(o)
        var_120 = if haskey(o.mem,var_156)
                o.mem[var_156]
            else
                var_120
            end
        Creature.stepLeft(o)
        var_123 = var_243 | var_123
        Creature.eatLeft(o,Int(var_349))
        Creature.eatDown(o,Int(var_117))
        return true
    end),[110,300,95,0,1,1,1],51,4113,67,33703,0x00000016,Dict(0=>0,10070=>10070,-26920=>-26920,-4015=>19308,-29748=>-29748,18308=>19308,23323=>23323,19308=>19308,-1631=>-1631,1=>1),[1919,568],84)]

max_stars_repo_name: tmptrash/jevo

max_issues_repo_name: tmptrash/jevo

max_forks_repo_name: tmptrash/jevo


text:
using QuasiArrays, DomainSets, Test

@testset "Kron" begin
    @testset "InclusionKron" begin
        a = Inclusion(0:0.5:2)
        b = Inclusion([1,3,4])
        c = quasikron(a,b)
        @test eltype(c) == Tuple{Float64,Int}
        @test c[(0.5,3)] == (0.5,3)
        @test_throws BoundsError c[(0.6,3)]
        @test_throws BoundsError c[(0.5,2)]
    end

    @testset "QuasiKron" begin
        a = QuasiVector(randn(5), 0:0.5:2)
        b = QuasiVector([5,6,8], [1,3,4])
        K = quasikron(a, b)
        @test axes(K) == (quasikron(axes(a,1),axes(b,1)),)
        @test K[(0.5,3)] == a[0.5]b[3]
        @test_throws BoundsError K[(0.6,3)]
        @test_throws BoundsError K[(0.5,2)]
    end
end

ext: jl


text:
function convert_to_complex(::Type{ComplexUtils}, arg0::Vector{jdouble})
    return jcall(ComplexUtils, "convertToComplex", Vector{JComplex}, (Vector{jdouble},), arg0)
end

function polar2_complex(::Type{ComplexUtils}, arg0::jdouble, arg1::jdouble)
    return jcall(ComplexUtils, "polar2Complex", JComplex, (jdouble, jdouble), arg0, arg1)
end


text:
using Knet, ArgParse

function copytenten(args=ARGS)
    info("Learning to copy sequences to test the S2S model.")
    s = ArgParseSettings()
    @add_arg_table s begin
        ("--dictfile"; required=true)
        ("--hidden"; arg_type=Int; default=1024)
        ("--batchsize"; arg_type=Int; default=128)
        ("--epochsize"; arg_type=Int; default=typemax(Int))
        ("--lossreport"; arg_type=Int; default=100000)
        ("--maxlen"; arg_type=Int; default=40)
        ("--gclip"; arg_type=Float64; default=5.0)
        ("--lr"; arg_type=Float64; default=2.0)
        ("--ftype"; default="Float32")
        ("--winit"; default="Gaussian(0,0.01)")
        ("--dense"; action=:store_true)
        ("--fast"; help="skip norm and loss calculations."; action=:store_true)
        ("--seed"; arg_type=Int; default=42)
    end
    isa(args, AbstractString) && (args=split(args))
    opts = parse_args(args, s)
    println(opts)
    for (k,v) in opts; @eval ($(symbol(k))=$v); end
    seed > 0 && setseed(seed)
    global data = S2SData(`tenten.pl -l $maxlen`; batchsize=batchsize, epochsize=epochsize, ftype=eval(parse(ftype)), dense=dense, dict=dictfile)
    vocab = maxtoken(data,2)
    global model = S2S(lstm; hidden=hidden, vocab=vocab, winit=eval(parse(winit)))
    setopt!(model; lr=lr)
    (maxnorm,losscnt) = fast ? (nothing,zeros(2)) : (zeros(2),zeros(2))
    train(model, data, softloss; gclip=gclip, maxnorm=maxnorm, losscnt=losscnt, lossreport=lossreport)
    Knet.s2s_lossreport(losscnt, batchsize, 0)
end

!isinteractive() && !isdefined(:load_only) && copytenten(ARGS)


text:
using DataDeps

register(DataDep(
  "zoo",
  "http://archive.ics.uci.edu/ml/datasets/Zoo",
  "http://archive.ics.uci.edu/ml/machine-learning-databases/zoo/zoo.data",
  "cddc71c26ab9bc82795b8f4ff114cade41885d92720c6af29ffb69bcf73f0315",
  post_fetch_method=(path -> begin
    UCIData.process_dataset(path,
        target_index=18,
        feature_indices=2:17,
        id_indices=1,
        categoric_indices=[2:13; 15:17],
    )
  end),
))

max_stars_repo_name: JackDunnNZ/uci-data

max_issues_repo_name: JackDunnNZ/uci-data

max_forks_repo_name: JackDunnNZ/uci-data


text:
module DualTest

using Base.Test
using ForwardDiff
using ForwardDiff: Partials, Dual, value, partials

import NaNMath
import Calculus
import SpecialFunctions
import RealInterface

samerng() = MersenneTwister(1)

# By lower-bounding the Int range at 2, we avoid cases where differentiating an
# exponentiation of an Int value would cause a DomainError due to reducing the
# exponent by one
intrand(V) = V == Int ? rand(2:10) : rand(V)

dual_isapprox(a, b) = isapprox(a, b)
dual_isapprox(a::Dual, b::Dual) = isapprox(value(a), value(b)) && isapprox(partials(a), partials(b))

for N in (0,3), M in (0,4), V in (Int, Float32)
    println("  ...testing Dual{Void,$V,$N} and Dual{Void,Dual{Void,$V,$M},$N}")

    PARTIALS = Partials{N,V}(ntuple(n -> intrand(V), Val{N}))
    PRIMAL = intrand(V)
    FDNUM = Dual(PRIMAL, PARTIALS)

    PARTIALS2 = Partials{N,V}(ntuple(n -> intrand(V), Val{N}))
    PRIMAL2 = intrand(V)
    FDNUM2 = Dual(PRIMAL2, PARTIALS2)

    PARTIALS3 = Partials{N,V}(ntuple(n -> intrand(V), Val{N}))
    PRIMAL3 = intrand(V)
    FDNUM3 = Dual(PRIMAL3, PARTIALS3)

    M_PARTIALS = Partials{M,V}(ntuple(m -> intrand(V), Val{M}))
    NESTED_PARTIALS = convert(Partials{N,Dual{Void,V,M}}, PARTIALS)
    NESTED_FDNUM = Dual(Dual(PRIMAL, M_PARTIALS), NESTED_PARTIALS)

    M_PARTIALS2 = Partials{M,V}(ntuple(m -> intrand(V), Val{M}))
    NESTED_PARTIALS2 = convert(Partials{N,Dual{Void,V,M}}, PARTIALS2)
    NESTED_FDNUM2 = Dual(Dual(PRIMAL2, M_PARTIALS2), NESTED_PARTIALS2)

    ################
    # Constructors #
    ################

    @test Dual(PRIMAL, PARTIALS...) === FDNUM
    @test typeof(Dual(widen(V)(PRIMAL), PARTIALS)) === Dual{Void,widen(V),N}
    @test typeof(Dual(widen(V)(PRIMAL), PARTIALS.values)) === Dual{Void,widen(V),N}
    @test typeof(Dual(widen(V)(PRIMAL), PARTIALS...)) === Dual{Void,widen(V),N}
    @test typeof(NESTED_FDNUM) == Dual{Void,Dual{Void,V,M},N}

    #############
    # Accessors #
    #############

    @test value(PRIMAL) == PRIMAL
    @test value(FDNUM) == PRIMAL
    @test value(NESTED_FDNUM) === Dual(PRIMAL, M_PARTIALS)

    @test partials(PRIMAL) == Partials{0,V}(tuple())
    @test partials(FDNUM) == PARTIALS
    @test partials(NESTED_FDNUM) === NESTED_PARTIALS

    for i in 1:N
        @test partials(FDNUM, i) == PARTIALS[i]
        for j in 1:M
            @test partials(NESTED_FDNUM, i, j) == partials(NESTED_PARTIALS[i], j)
        end
    end

    @test ForwardDiff.npartials(FDNUM) == N
    @test ForwardDiff.npartials(typeof(FDNUM)) == N
    @test ForwardDiff.npartials(NESTED_FDNUM) == N
    @test ForwardDiff.npartials(typeof(NESTED_FDNUM)) == N

    @test ForwardDiff.valtype(FDNUM) == V
    @test ForwardDiff.valtype(typeof(FDNUM)) == V
    @test ForwardDiff.valtype(NESTED_FDNUM) == Dual{Void,V,M}
    @test ForwardDiff.valtype(typeof(NESTED_FDNUM)) == Dual{Void,V,M}

    #####################
    # Generic Functions #
    #####################

    @test FDNUM === copy(FDNUM)
    @test NESTED_FDNUM === copy(NESTED_FDNUM)

    if V != Int
        @test eps(FDNUM) === eps(PRIMAL)
        @test eps(typeof(FDNUM)) === eps(V)
        @test eps(NESTED_FDNUM) === eps(PRIMAL)
        @test eps(typeof(NESTED_FDNUM)) === eps(V)

        @test floor(Int, FDNUM) === floor(Int, PRIMAL)
        @test floor(Int, FDNUM2) === floor(Int, PRIMAL2)
        @test floor(Int, NESTED_FDNUM) === floor(Int, PRIMAL)

        @test floor(FDNUM) === floor(PRIMAL)
        @test floor(FDNUM2) === floor(PRIMAL2)
        @test floor(NESTED_FDNUM) === floor(PRIMAL)

        @test ceil(Int, FDNUM) === ceil(Int, PRIMAL)
        @test ceil(Int, FDNUM2) === ceil(Int, PRIMAL2)
        @test ceil(Int, NESTED_FDNUM) === ceil(Int, PRIMAL)

        @test ceil(FDNUM) === ceil(PRIMAL)
        @test ceil(FDNUM2) === ceil(PRIMAL2)
        @test ceil(NESTED_FDNUM) === ceil(PRIMAL)

        @test trunc(Int, FDNUM) === trunc(Int, PRIMAL)
        @test trunc(Int, FDNUM2) === trunc(Int, PRIMAL2)
        @test trunc(Int, NESTED_FDNUM) === trunc(Int, PRIMAL)

        @test trunc(FDNUM) === trunc(PRIMAL)
        @test trunc(FDNUM2) === trunc(PRIMAL2)
        @test trunc(NESTED_FDNUM) === trunc(PRIMAL)

        @test round(Int, FDNUM) === round(Int, PRIMAL)
        @test round(Int, FDNUM2) === round(Int, PRIMAL2)
        @test round(Int, NESTED_FDNUM) === round(Int, PRIMAL)

        @test round(FDNUM) === round(PRIMAL)
        @test round(FDNUM2) === round(PRIMAL2)
        @test round(NESTED_FDNUM) === round(PRIMAL)

        @test Base.rtoldefault(typeof(FDNUM)) ≡ Base.rtoldefault(typeof(PRIMAL))
        @test Dual(PRIMAL-eps(V), PARTIALS) ≈ FDNUM
        @test Base.rtoldefault(typeof(NESTED_FDNUM)) ≡ Base.rtoldefault(typeof(PRIMAL))
    end

    @test hash(FDNUM) === hash(PRIMAL)
    @test hash(FDNUM, hash(PRIMAL)) === hash(PRIMAL, hash(PRIMAL))
    @test hash(NESTED_FDNUM) === hash(PRIMAL)
    @test hash(NESTED_FDNUM, hash(PRIMAL)) === hash(PRIMAL, hash(PRIMAL))

    const TMPIO = IOBuffer()
    write(TMPIO, FDNUM)
    seekstart(TMPIO)
    @test read(TMPIO, typeof(FDNUM)) === FDNUM
    seekstart(TMPIO)
    write(TMPIO, FDNUM2)
    seekstart(TMPIO)
    @test read(TMPIO, typeof(FDNUM2)) === FDNUM2
    seekstart(TMPIO)
    write(TMPIO, NESTED_FDNUM)
    seekstart(TMPIO)
    @test read(TMPIO, typeof(NESTED_FDNUM)) === NESTED_FDNUM
    close(TMPIO)

    @test zero(FDNUM) === Dual(zero(PRIMAL), zero(PARTIALS))
    @test zero(typeof(FDNUM)) === Dual(zero(V), zero(Partials{N,V}))
    @test zero(NESTED_FDNUM) === Dual(Dual(zero(PRIMAL), zero(M_PARTIALS)), zero(NESTED_PARTIALS))
    @test zero(typeof(NESTED_FDNUM)) === Dual(Dual(zero(V), zero(Partials{M,V})), zero(Partials{N,Dual{Void,V,M}}))

    @test one(FDNUM) === Dual(one(PRIMAL), zero(PARTIALS))
    @test one(typeof(FDNUM)) === Dual(one(V), zero(Partials{N,V}))
    @test one(NESTED_FDNUM) === Dual(Dual(one(PRIMAL), zero(M_PARTIALS)), zero(NESTED_PARTIALS))
    @test one(typeof(NESTED_FDNUM)) === Dual(Dual(one(V), zero(Partials{M,V})), zero(Partials{N,Dual{Void,V,M}}))

    @test rand(samerng(), FDNUM) === Dual(rand(samerng(), V), zero(PARTIALS))
    @test rand(samerng(), typeof(FDNUM)) === Dual(rand(samerng(), V), zero(Partials{N,V}))
    @test rand(samerng(), NESTED_FDNUM) === Dual(Dual(rand(samerng(), V), zero(M_PARTIALS)), zero(NESTED_PARTIALS))
    @test rand(samerng(), typeof(NESTED_FDNUM)) === Dual(Dual(rand(samerng(), V), zero(Partials{M,V})), zero(Partials{N,Dual{Void,V,M}}))

    # Predicates #
    #------------#

    @test ForwardDiff.isconstant(zero(FDNUM))
    @test ForwardDiff.isconstant(rand(FDNUM))
    @test ForwardDiff.isconstant(one(FDNUM))
    @test ForwardDiff.isconstant(FDNUM) == (N == 0)

    @test ForwardDiff.isconstant(zero(NESTED_FDNUM))
    @test ForwardDiff.isconstant(rand(NESTED_FDNUM))
    @test ForwardDiff.isconstant(one(NESTED_FDNUM))
    @test ForwardDiff.isconstant(NESTED_FDNUM) == (N == 0)

    @test isequal(FDNUM, Dual(PRIMAL, PARTIALS2))
    @test isequal(PRIMAL, PRIMAL2) == isequal(FDNUM, FDNUM2)

    @test isequal(NESTED_FDNUM, Dual(Dual(PRIMAL, M_PARTIALS2), NESTED_PARTIALS2))
    @test isequal(PRIMAL, PRIMAL2) == isequal(NESTED_FDNUM, NESTED_FDNUM2)

    @test FDNUM == Dual(PRIMAL, PARTIALS2)
    @test (PRIMAL == PRIMAL2) == (FDNUM == FDNUM2)
    @test (PRIMAL == PRIMAL2) == (NESTED_FDNUM == NESTED_FDNUM2)

    @test isless(Dual(1, PARTIALS), Dual(2, PARTIALS2))
    @test !(isless(Dual(1, PARTIALS), Dual(1, PARTIALS2)))
    @test !(isless(Dual(2, PARTIALS), Dual(1, PARTIALS2)))

    @test isless(Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS), Dual(Dual(2, M_PARTIALS2), NESTED_PARTIALS2))
    @test !(isless(Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS), Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2)))
    @test !(isless(Dual(Dual(2, M_PARTIALS), NESTED_PARTIALS), Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2)))

    @test Dual(1, PARTIALS) < Dual(2, PARTIALS2)
    @test !(Dual(1, PARTIALS) < Dual(1, PARTIALS2))
    @test !(Dual(2, PARTIALS) < Dual(1, PARTIALS2))

    @test Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) < Dual(Dual(2, M_PARTIALS2), NESTED_PARTIALS2)
    @test !(Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) < Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2))
    @test !(Dual(Dual(2, M_PARTIALS), NESTED_PARTIALS) < Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2))

    @test Dual(1, PARTIALS) <= Dual(2, PARTIALS2)
    @test Dual(1, PARTIALS) <= Dual(1, PARTIALS2)
    @test !(Dual(2, PARTIALS) <= Dual(1, PARTIALS2))

    @test Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) <= Dual(Dual(2, M_PARTIALS2), NESTED_PARTIALS2)
    @test Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) <= Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2)
    @test !(Dual(Dual(2, M_PARTIALS), NESTED_PARTIALS) <= Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2))

    @test Dual(2, PARTIALS) > Dual(1, PARTIALS2)
    @test !(Dual(1, PARTIALS) > Dual(1, PARTIALS2))
    @test !(Dual(1, PARTIALS) > Dual(2, PARTIALS2))

    @test Dual(Dual(2, M_PARTIALS), NESTED_PARTIALS) > Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2)
    @test !(Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) > Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2))
    @test !(Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) > Dual(Dual(2, M_PARTIALS2), NESTED_PARTIALS2))

    @test Dual(2, PARTIALS) >= Dual(1, PARTIALS2)
    @test Dual(1, PARTIALS) >= Dual(1, PARTIALS2)
    @test !(Dual(1, PARTIALS) >= Dual(2, PARTIALS2))

    @test Dual(Dual(2, M_PARTIALS), NESTED_PARTIALS) >= Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2)
    @test Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) >= Dual(Dual(1, M_PARTIALS2), NESTED_PARTIALS2)
    @test !(Dual(Dual(1, M_PARTIALS), NESTED_PARTIALS) >= Dual(Dual(2, M_PARTIALS2), NESTED_PARTIALS2))

    @test isnan(Dual(NaN, PARTIALS))
    @test !(isnan(FDNUM))

    @test isnan(Dual(Dual(NaN, M_PARTIALS), NESTED_PARTIALS))
    @test !(isnan(NESTED_FDNUM))

    @test isfinite(FDNUM)
    @test !(isfinite(Dual(Inf, PARTIALS)))

    @test isfinite(NESTED_FDNUM)
    @test !(isfinite(Dual(Dual(NaN, M_PARTIALS), NESTED_PARTIALS)))

    @test isinf(Dual(Inf, PARTIALS))
    @test !(isinf(FDNUM))

    @test isinf(Dual(Dual(Inf, M_PARTIALS), NESTED_PARTIALS))
    @test !(isinf(NESTED_FDNUM))

    @test isreal(FDNUM)
    @test isreal(NESTED_FDNUM)

    @test isinteger(Dual(1.0, PARTIALS))
    @test isinteger(FDNUM) == (V == Int)

    @test isinteger(Dual(Dual(1.0, M_PARTIALS), NESTED_PARTIALS))
    @test isinteger(NESTED_FDNUM) == (V == Int)

    @test iseven(Dual(2))
    @test !(iseven(Dual(1)))

    @test iseven(Dual(Dual(2)))
    @test !(iseven(Dual(Dual(1))))

    @test isodd(Dual(1))
    @test !(isodd(Dual(2)))

    @test isodd(Dual(Dual(1)))
    @test !(isodd(Dual(Dual(2))))

    ########################
    # Promotion/Conversion #
    ########################

    WIDE_T = widen(V)

    @test promote_type(Dual{Void,V,N}, V) == Dual{Void,V,N}
    @test promote_type(Dual{Void,V,N}, WIDE_T) == Dual{Void,WIDE_T,N}
    @test promote_type(Dual{Void,WIDE_T,N}, V) == Dual{Void,WIDE_T,N}
    @test promote_type(Dual{Void,V,N}, Dual{Void,V,N}) == Dual{Void,V,N}
    @test promote_type(Dual{Void,V,N}, Dual{Void,WIDE_T,N}) == Dual{Void,WIDE_T,N}
    @test promote_type(Dual{Void,WIDE_T,N}, Dual{Void,Dual{Void,V,M},N}) == Dual{Void,Dual{Void,WIDE_T,M},N}

    WIDE_FDNUM = convert(Dual{Void,WIDE_T,N}, FDNUM)
    WIDE_NESTED_FDNUM = convert(Dual{Void,Dual{Void,WIDE_T,M},N}, NESTED_FDNUM)

    @test typeof(WIDE_FDNUM) === Dual{Void,WIDE_T,N}
    @test typeof(WIDE_NESTED_FDNUM) === Dual{Void,Dual{Void,WIDE_T,M},N}

    @test value(WIDE_FDNUM) == PRIMAL
    @test value(WIDE_NESTED_FDNUM) == PRIMAL

    @test convert(Dual, FDNUM) === FDNUM
    @test convert(Dual, NESTED_FDNUM) === NESTED_FDNUM
    @test convert(Dual{Void,V,N}, FDNUM) === FDNUM
    @test convert(Dual{Void,Dual{Void,V,M},N}, NESTED_FDNUM) === NESTED_FDNUM
    @test convert(Dual{Void,WIDE_T,N}, PRIMAL) === Dual(WIDE_T(PRIMAL), zero(Partials{N,WIDE_T}))
    @test convert(Dual{Void,Dual{Void,WIDE_T,M},N}, PRIMAL) === Dual(Dual(WIDE_T(PRIMAL), zero(Partials{M,WIDE_T})), zero(Partials{N,Dual{Void,V,M}}))
    @test convert(Dual{Void,Dual{Void,V,M},N}, FDNUM) === Dual(Dual{Void,V,M}(PRIMAL), convert(Partials{N,Dual{Void,V,M}}, PARTIALS))
    @test convert(Dual{Void,Dual{Void,WIDE_T,M},N}, FDNUM) === Dual(Dual{Void,WIDE_T,M}(PRIMAL), convert(Partials{N,Dual{Void,WIDE_T,M}}, PARTIALS))

    if V != Int
        @test Base.promote_array_type(+, Dual{Void,V,N}, V, Base.promote_op(+, Dual{Void,V,N}, V)) == Dual{Void,V,N}
        @test Base.promote_array_type(+, Dual{Void,Int,N}, V, Base.promote_op(+, Dual{Void,Int,N}, V)) == Dual{Void,V,N}
        @test Base.promote_array_type(+, V, Dual{Void,V,N}, Base.promote_op(+, V, Dual{Void,V,N})) == Dual{Void,V,N}
        @test Base.promote_array_type(+, V, Dual{Void,Int,N}, Base.promote_op(+, V, Dual{Void,Int,N})) == Dual{Void,V,N}
        @test Base.promote_array_type(+, Dual{Void,V,N}, V) == Dual{Void,V,N}
        @test Base.promote_array_type(+, Dual{Void,Int,N}, V) == Dual{Void,V,N}
        @test Base.promote_array_type(+, V, Dual{Void,V,N}) == Dual{Void,V,N}
        @test Base.promote_array_type(+, V, Dual{Void,Int,N}) == Dual{Void,V,N}
    end

    ##############
    # Arithmetic #
    ##############

    # Addition/Subtraction #
    #----------------------#

    @test FDNUM + FDNUM2 === Dual(value(FDNUM) + value(FDNUM2), partials(FDNUM) + partials(FDNUM2))
    @test FDNUM + PRIMAL === Dual(value(FDNUM) + PRIMAL, partials(FDNUM))
    @test PRIMAL + FDNUM === Dual(value(FDNUM) + PRIMAL, partials(FDNUM))

    @test NESTED_FDNUM + NESTED_FDNUM2 === Dual(value(NESTED_FDNUM) + value(NESTED_FDNUM2), partials(NESTED_FDNUM) + partials(NESTED_FDNUM2))
    @test NESTED_FDNUM + PRIMAL === Dual(value(NESTED_FDNUM) + PRIMAL, partials(NESTED_FDNUM))
    @test PRIMAL + NESTED_FDNUM === Dual(value(NESTED_FDNUM) + PRIMAL, partials(NESTED_FDNUM))

    @test FDNUM - FDNUM2 === Dual(value(FDNUM) - value(FDNUM2), partials(FDNUM) - partials(FDNUM2))
    @test FDNUM - PRIMAL === Dual(value(FDNUM) - PRIMAL, partials(FDNUM))
    @test PRIMAL - FDNUM === Dual(PRIMAL - value(FDNUM), -(partials(FDNUM)))
    @test -(FDNUM) === Dual(-(value(FDNUM)), -(partials(FDNUM)))

    @test NESTED_FDNUM - NESTED_FDNUM2 === Dual(value(NESTED_FDNUM) - value(NESTED_FDNUM2), partials(NESTED_FDNUM) - partials(NESTED_FDNUM2))
    @test NESTED_FDNUM - PRIMAL === Dual(value(NESTED_FDNUM) - PRIMAL, partials(NESTED_FDNUM))
    @test PRIMAL - NESTED_FDNUM === Dual(PRIMAL - value(NESTED_FDNUM), -(partials(NESTED_FDNUM)))
    @test -(NESTED_FDNUM) === Dual(-(value(NESTED_FDNUM)), -(partials(NESTED_FDNUM)))

    # Multiplication #
    #----------------#

    @test FDNUM * FDNUM2 === Dual(value(FDNUM) * value(FDNUM2), ForwardDiff._mul_partials(partials(FDNUM), partials(FDNUM2), value(FDNUM2), value(FDNUM)))
    @test FDNUM * PRIMAL === Dual(value(FDNUM) * PRIMAL, partials(FDNUM) * PRIMAL)
    @test PRIMAL * FDNUM === Dual(value(FDNUM) * PRIMAL, partials(FDNUM) * PRIMAL)

    @test NESTED_FDNUM * NESTED_FDNUM2 === Dual(value(NESTED_FDNUM) * value(NESTED_FDNUM2), ForwardDiff._mul_partials(partials(NESTED_FDNUM), partials(NESTED_FDNUM2), value(NESTED_FDNUM2), value(NESTED_FDNUM)))
    @test NESTED_FDNUM * PRIMAL === Dual(value(NESTED_FDNUM) * PRIMAL, partials(NESTED_FDNUM) * PRIMAL)
    @test PRIMAL * NESTED_FDNUM === Dual(value(NESTED_FDNUM) * PRIMAL, partials(NESTED_FDNUM) * PRIMAL)

    # Division #
    #----------#

    if M > 0 && N > 0
        @test Dual{1}(FDNUM) / Dual{1}(PRIMAL) === Dual{1}(FDNUM / PRIMAL)
        @test Dual{1}(PRIMAL) / Dual{1}(FDNUM) === Dual{1}(PRIMAL / FDNUM)
        @test Dual{1}(FDNUM) / FDNUM2 === Dual{1}(FDNUM / FDNUM2)
        @test FDNUM / Dual{1}(FDNUM2) === Dual{1}(FDNUM / FDNUM2)
        @test Dual{1}(FDNUM / PRIMAL, FDNUM2 / PRIMAL) === Dual{1}(FDNUM, FDNUM2) / PRIMAL
    end

    @test dual_isapprox(FDNUM / FDNUM2, Dual(value(FDNUM) / value(FDNUM2), ForwardDiff._div_partials(partials(FDNUM), partials(FDNUM2), value(FDNUM), value(FDNUM2))))
    @test dual_isapprox(FDNUM / PRIMAL, Dual(value(FDNUM) / PRIMAL, partials(FDNUM) / PRIMAL))
    @test dual_isapprox(PRIMAL / FDNUM, Dual(PRIMAL / value(FDNUM), (-(PRIMAL) / value(FDNUM)^2) * partials(FDNUM)))

    @test dual_isapprox(NESTED_FDNUM / NESTED_FDNUM2, Dual(value(NESTED_FDNUM) / value(NESTED_FDNUM2), ForwardDiff._div_partials(partials(NESTED_FDNUM), partials(NESTED_FDNUM2), value(NESTED_FDNUM), value(NESTED_FDNUM2))))
    @test dual_isapprox(NESTED_FDNUM / PRIMAL, Dual(value(NESTED_FDNUM) / PRIMAL, partials(NESTED_FDNUM) / PRIMAL))
    @test dual_isapprox(PRIMAL / NESTED_FDNUM, Dual(PRIMAL / value(NESTED_FDNUM), (-(PRIMAL) / value(NESTED_FDNUM)^2) * partials(NESTED_FDNUM)))

    # Exponentiation #
    #----------------#

    @test dual_isapprox(FDNUM^FDNUM2, exp(FDNUM2 * log(FDNUM)))
    @test dual_isapprox(FDNUM^PRIMAL, exp(PRIMAL * log(FDNUM)))
    @test dual_isapprox(PRIMAL^FDNUM, exp(FDNUM * log(PRIMAL)))

    @test dual_isapprox(NESTED_FDNUM^NESTED_FDNUM2, exp(NESTED_FDNUM2 * log(NESTED_FDNUM)))
    @test dual_isapprox(NESTED_FDNUM^PRIMAL, exp(PRIMAL * log(NESTED_FDNUM)))
    @test dual_isapprox(PRIMAL^NESTED_FDNUM, exp(NESTED_FDNUM * log(PRIMAL)))

    @test partials(NaNMath.pow(Dual(-2.0, 1.0), Dual(2.0, 0.0)), 1) == -4.0

    ###################################
    # General Mathematical Operations #
    ###################################

    @test conj(FDNUM) === FDNUM
    @test conj(NESTED_FDNUM) === NESTED_FDNUM

    @test transpose(FDNUM) === FDNUM
    @test transpose(NESTED_FDNUM) === NESTED_FDNUM

    @test ctranspose(FDNUM) === FDNUM
    @test ctranspose(NESTED_FDNUM) === NESTED_FDNUM

    @test abs(-FDNUM) === FDNUM
    @test abs(FDNUM) === FDNUM
    @test abs(-NESTED_FDNUM) === NESTED_FDNUM
    @test abs(NESTED_FDNUM) === NESTED_FDNUM

    if V != Int
        for f in vcat(RealInterface.UNARY_MATH, RealInterface.UNARY_SPECIAL_MATH)
            if DiffBase.hasdiffrule(f, 1)
                deriv = DiffBase.diffrule(f, :x)
                modifier = in(f, (:asec, :acsc, :asecd, :acscd, :acosh, :acoth)) ? one(V) : zero(V)
                @eval begin
                    x = rand() + $modifier
                    dx = $f(Dual(x, one(x)))
                    @test value(dx) == $f(x)
                    @test partials(dx, 1) == $deriv
                end
            end
        end
        for f in RealInterface.BINARY_SPECIAL_MATH
            in(f, (:hankelh1, :hankelh1x, :hankelh2, :hankelh2x)) && continue
            if DiffBase.hasdiffrule(f, 2)
                derivs = DiffBase.diffrule(f, :x, :y)
                @eval begin
                    x, y = rand(1:10), rand()
                    dx = $f(Dual(x, one(x)), y)
                    dy = $f(x, Dual(y, one(y)))
                    actualdx = $(derivs[1])
                    actualdy = $(derivs[2])
                    @test value(dx) == $f(x, y)
                    @test value(dy) == value(dx)
                    if isnan(actualdx)
                        @test isnan(partials(dx, 1))
                    else
                        @test partials(dx, 1) == actualdx
                    end
                    if isnan(actualdy)
                        @test isnan(partials(dy, 1))
                    else
                        @test partials(dy, 1) == actualdy
                    end
                end
            end
        end
    end

    # Special Cases #
    #---------------#

    @test dual_isapprox(hypot(FDNUM, FDNUM2), sqrt(FDNUM^2 + FDNUM2^2))
    @test dual_isapprox(hypot(FDNUM, FDNUM2, FDNUM), sqrt(2*(FDNUM^2) + FDNUM2^2))

    @test all(map(dual_isapprox, ForwardDiff.sincos(FDNUM), (sin(FDNUM), cos(FDNUM))))

    if V === Float32
        @test typeof(sqrt(FDNUM)) === typeof(FDNUM)
        @test typeof(sqrt(NESTED_FDNUM)) === typeof(NESTED_FDNUM)
    end

    @test dual_isapprox(atan2(abs(FDNUM), abs(FDNUM2)), atan(abs(FDNUM) / abs(FDNUM2)))

    @test dual_isapprox(fma(FDNUM, FDNUM2, FDNUM3),   Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2 + PRIMAL2*PARTIALS + PARTIALS3))
    @test dual_isapprox(fma(FDNUM, FDNUM2, PRIMAL3),  Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2 + PRIMAL2*PARTIALS))
    @test dual_isapprox(fma(PRIMAL, FDNUM2, FDNUM3),  Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2 + PARTIALS3))
    @test dual_isapprox(fma(PRIMAL, FDNUM2, PRIMAL3), Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL*PARTIALS2))
    @test dual_isapprox(fma(FDNUM, PRIMAL2, FDNUM3),  Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL2*PARTIALS + PARTIALS3))
    @test dual_isapprox(fma(FDNUM, PRIMAL2, PRIMAL3), Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PRIMAL2*PARTIALS))
    @test dual_isapprox(fma(PRIMAL, PRIMAL2, FDNUM3), Dual(fma(PRIMAL, PRIMAL2, PRIMAL3), PARTIALS3))
end

end # module


text:
using OrdinaryDiffEq
using Trixi

# initial_condition_convergence_test transformed to the parallelogram
function initial_condition_parallelogram(x, t, equation::LinearScalarAdvectionEquation2D)
  # Transform back to unit square
  x_transformed = SVector(x[1] + x[2], x[2])
  a = equation.advectionvelocity
  a_transformed = SVector(a[1] + a[2], a[2])

  # Store translated coordinate for easy use of exact solution
  x_translated = x_transformed - a_transformed * t

  c = 1.0
  A = 0.5
  L = 2
  f = 1/L
  omega = 2 * pi * f
  scalar = c + A * sin(omega * sum(x_translated))
  return SVector(scalar)
end

###############################################################################
# semidiscretization of the linear advection equation

advectionvelocity = (2.0, 1.0)
equations = LinearScalarAdvectionEquation2D(advectionvelocity)

# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux
solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs)

# Define faces for a parallelogram that looks like this
#
#             (0,1) __________ (2, 1)
#                ⟋         ⟋
#             ⟋         ⟋
#          ⟋         ⟋
# (-2,-1) ‾‾‾‾‾‾‾‾‾‾ (0,-1)
mapping(xi, eta) = SVector(xi + eta, eta)

cells_per_dimension = (16, 16)

# Create curved mesh with 16 x 16 elements, periodic in both dimensions
mesh = StructuredMesh(cells_per_dimension, mapping; periodicity=(true, true))

# A semidiscretization collects data structures and functions for the spatial discretization
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_parallelogram, solver)

###############################################################################
# ODE solvers, callbacks etc.

# Create ODE problem with time span from 0.0 to 1.0
ode = semidiscretize(semi, (0.0, 1.0));

# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup
# and resets the timers
summary_callback = SummaryCallback()

# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results
analysis_callback = AnalysisCallback(semi, interval=100)

# The SaveSolutionCallback allows to save the solution to a file in regular intervals
save_solution = SaveSolutionCallback(interval=100,
                                     solution_variables=cons2prim)

# The StepsizeCallback handles the re-calculcation of the maximum Δt after each time step
stepsize_callback = StepsizeCallback(cfl=1.6)

# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver
callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback)

###############################################################################
# run the simulation

# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks
sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false),
            dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
            save_everystep=false, callback=callbacks);

# Print the timer summary
summary_callback()


text:
using SafeTestsets

@safetestset "Test Lagrange Polynomial Construction" begin
    include("test_lagrange_polynomials.jl")
end

@safetestset "Test Hermite Polynomial Construction" begin
    include("test_hermite_polynomials.jl")
end

@safetestset "Test Lagrange Basis" begin
    include("test_lagrange_basis.jl")
end

@safetestset "Test Hermite Basis" begin
    include("test_hermite_basis.jl")
end

@safetestset "Test Tensor Product Basis" begin
    include("test_lagrange_tensor_product_basis.jl")
end

@safetestset "Test Hermite Tensor Product Basis" begin
    include("test_hermite_tensor_product_basis.jl")
end

@safetestset "Test Lagrange Interpolating Polynomial" begin
    include("test_lagrange_interpolation.jl")
end

@safetestset "Test Hermite Interpolating Polynomial" begin
    include("test_hermite_interpolation.jl")
end


text:
"""
    println_verbose(x, isVerbose)

Version of println that only prints when isVerbose flag is true

# Arguments

- x = something that can be printed
- isVerbose = boolean flag indicating whether or not to print messages.
  Defaults to `true`.

# Value

None; prints to console

"""
function println_verbose(x, isVerbose::Bool=true)

    if isVerbose == true
        println(x)
    end
end

"""
    criterion(B, resid, lambdaL1, lambdaL2, crit_denom)

Calculate the criterion for the Elastic-net penalty

# Arguments

- B = 2d array of floats consisting of regularized coefficient estimates
- resid = 2d array of floats consisting of the residuals
- lambdaL1 = l1 penalty, a floating scalar
- lambdaL2 = l2 penalty, a floating scalar
- crit_denom = 1d array of 2 integers, the denominators of the criterion

# Value

A floating scalar

"""
function criterion(B::AbstractArray{Float64,2},
                   resid::AbstractArray{Float64,2},
                   lambdaL1::Float64, lambdaL2::Float64, crit_denom::AbstractArray{Int64,1})

    return 0.5 * sum(abs2, resid)/crit_denom[1] +
             lambdaL1 * sum(abs, B)/crit_denom[2] +
             0.5 * lambdaL2 * sum(abs2, B)/crit_denom[2]
end

"""
    prox(b, gradient, b2sign, lambda, norm, stepsize)

Proximal (soft-thresholding) operator when not incorporating the norms
(norms=1)

# Arguments

- b = coefficient to update, a float
- gradient = gradient of b, a float
- b2sign = sign of b + stepsize*gradient, a float
- lambda = lambda penalty , a float
- norm = Nothing
- stepsize = step size to multiply updates, a float

# Value

A floating scalar

"""
function prox(b::Float64, gradient::Float64, b2sign::Float64,
              lambda::Float64, norm::Nothing, stepsize::Float64)

    return max(0.0, b2sign*b - stepsize * (b2sign*gradient + lambda)) * b2sign
end

# New
function prox_mat(b::AbstractArray{Float64,2}, b2sign::AbstractArray{Float64,2}, lambda::Float64,
                  norm::Nothing, stepsize::Float64)

    return max.(0.0, abs.(b) .- stepsize*lambda) .* b2sign
end

"""
    prox(b, gradient, b2sign, lambda, norm)

Proximal (soft-thresholding) operator when not incorporating the norms
(norms=1) and step size is 1

# Arguments

- b = coefficient to update, a float
- gradient = gradient of b, a float
- b2sign = sign of b + stepsize*gradient, a float
- lambda = lambda penalty , a float
- norm = Nothing

# Value

A floating scalar

"""
function prox(b::Float64, gradient::Float64, b2sign::Float64,
              lambda::Float64, norm::Nothing)

    return max(0.0, b2sign*b - (b2sign*gradient + lambda)) * b2sign
end

# New
function prox_mat(b::AbstractArray{Float64,2}, b2sign::AbstractArray{Float64,2}, lambda::Float64,
    norm::Nothing)

return max.(0.0, abs.(b) .- lambda) .* b2sign
end

"""
    prox(b, gradient, b2sign, lambda, norm, stepsize)

Proximal (soft-thresholding) operator

# Arguments

- b = coefficient to update, a float
- gradient = gradient of b, a float
- b2sign = sign of b + stepsize*gradient, a float
- lambda = lambda penalty , a float
- norm = norm corresponding to b, a float
- stepsize = step size to multiply updates, a float

# Value

A floating scalar

"""
function prox(b::Float64, gradient::Float64, b2sign::Float64,
              lambda::Float64, norm::Float64, stepsize::Float64)

    return max(0.0, b2sign*b - stepsize * (b2sign*gradient + lambda)/norm) *
             b2sign
end

# New
function prox_mat(b::AbstractArray{Float64,2}, b2sign::AbstractArray{Float64,2},
                  lambda::Float64, norm::AbstractArray{Float64,2}, stepsize::Float64)

return max.(0.0, abs.(b) .- stepsize*lambda./norm) .* b2sign
end

"""
    prox(b, gradient, b2sign, lambda, norm)

Proximal (soft-thresholding) operator when step size is 1

# Arguments

- b = coefficient to update, a float
- gradient = gradient of b, a float
- b2sign = sign of b + stepsize*gradient, a float
- lambda = lambda penalty , a float
- norm = norm corresponding to b, a float

# Value

A floating scalar

"""
function prox(b::Float64, gradient::Float64, b2sign::Float64,
              lambda::Float64, norm::Float64)

    return max(0.0, b2sign*b - (b2sign*gradient + lambda)/norm) * b2sign
end

# New
function prox_mat(b::AbstractArray{Float64,2}, b2sign::AbstractArray{Float64,2}, lambda::Float64,
    norm::AbstractArray{Float64,2})

return max.(0.0, abs.(b) .- lambda./norm) .* b2sign
end

"""
    calc_grad!(grad, X, Z, resid)

Calculate gradient in place

# Arguments

- gradient = 2d array of floats consisting of the gradient, to be updated in
  place
- X = 2d array of floats consisting of the row covariates, standardized as
  necessary
- Z = 2d array of floats consisting of the column covariates, standardized
  as necessary
- resid = 2d array of floats consisting of the residuals

# Value

None; updates gradient in place.

"""
function calc_grad!(grad::AbstractArray{Float64,2},
                    X::AbstractArray{Float64,2},
                    Z::AbstractArray{Float64,2},
                    resid::AbstractArray{Float64,2})

    LinearAlgebra.mul!(grad, -transpose(X), resid*Z)
end

"""
    calc_grad!(Xi, Zj, resid)

Calculate gradient at a single coefficient

# Arguments

- Xi = 1d array of floats consisting of the row covariates for the
  coefficient, standardized as necessary
- Zj = 1d array of floats consisting of the column covariates for the
  coefficient, standardized as necessary
- resid = 2d array of floats consisting of the residuals

# Value

A floating scalar

"""
function calc_grad(Xi::AbstractArray{Float64,1}, Zj::AbstractArray{Float64,1},
                   resid::AbstractArray{Float64,2})

    return -sum(transpose(Xi)*resid*Zj)
end

"""
    get_func(method)

Return actual module function name according to method name according to a dictionnary.

# Arguments

- method = String describing selected method. The method can be "ista",
 "fista", "fista_bt" or "admm".

# Value

A function

"""
function get_func(method::String )

    dictMethod = Dict("ista"=>ista!,
                        "fista"=>fista!,
                        "fista_bt"=>fista_bt!,
                        "admm"=>admm!,
                        "cd"=>cd!,
                        "cd_active"=>cd_active!);

    return dictMethod[method]
end


text:
include("keystate.jl")

mutable struct HostNode <: Ranger.AbstractNode
    base::Nodes.NodeData
    transform::Nodes.TransformProperties{Float64}

    # Collection for AnchorNode
    children::Array{Ranger.AbstractNode,1}

    # Colors
    color::Rendering.Palette

    # An icon so we can see the host
    polygon::Geometry.Polygon

    # Total AABB
    aabb::Geometry.AABB{Float64}

    # Hit detection for both projectiles and dragging
    detection::Nodes.Detection
    inside::Bool

    keystate::KeyState
    drag::DragState
    node_point::Geometry.Point{Float64}

    particle_system::Particles.ParticleSystem

    function HostNode(world::Ranger.World, name::String, parent::Ranger.AbstractNode)
        o = new()

        o.base = Nodes.NodeData(name, parent, world)
        o.transform = Nodes.TransformProperties{Float64}()
        o.children = Array{Ranger.AbstractNode,1}[]
        o.color = Rendering.White()

        o.aabb = Geometry.AABB{Float64}()

        o.polygon = Geometry.Polygon{Float64}()
        o.detection = Nodes.Detection(Rendering.Yellow(), Rendering.Red())
        o.inside = false
        o.keystate = KeyState(false, false, Int8(0))
        o.drag = DragState()
        o.node_point = Geometry.Point{Float64}()

        # Setup particle activator
        activator = Particles.Activator360()
        activator.max_life = 3.0

        # Create and activate particle system.
        o.particle_system = Particles.ParticleSystem(activator)
        o.particle_system.active = true
        o.particle_system.auto_trigger = true

        # Add a few particles to the system.
        for i in 1:Particles.MAX_PARTICLES
            p = Particles.Particle{Float64}()
            Particles.add_particle!(o.particle_system, p)

            # Add a particle node to the parent (i.e. a visual).
            pnode = BasicParticleNode(world, "ParticleNode:" * string(i), parent)
            p.visual = pnode
            pnode.color = Rendering.Red()
            pnode.base.id = i # assign an id for lookups.
            Nodes.set_scale!(pnode, Particles.MAX_PARTICE_SIZE) # an initial size

            # Important! We are adding the node to the parent and NOT this host node.
            # We want the particle to be independent of the emitter.
            push!(Nodes.get_children(parent), pnode)
        end

        build(o, world)
        o
    end
end

function build(node::HostNode, world::Ranger.World)
    Geometry.add_vertex!(node.polygon, 0.05, -0.05)
    Geometry.add_vertex!(node.polygon, 0.05, -0.15)
    Geometry.add_vertex!(node.polygon, 0.0, -0.25)
    Geometry.add_vertex!(node.polygon, -0.05, -0.25)
    Geometry.add_vertex!(node.polygon, -0.05, -0.15)
    Geometry.add_vertex!(node.polygon, -0.05, -0.05)

    Geometry.add_vertex!(node.polygon, -0.15, -0.05)
    Geometry.add_vertex!(node.polygon, -0.25, 0.0)
    Geometry.add_vertex!(node.polygon, -0.25, 0.05)
    Geometry.add_vertex!(node.polygon, -0.15, 0.05)
    Geometry.add_vertex!(node.polygon, -0.05, 0.05)

    Geometry.add_vertex!(node.polygon, -0.05, 0.15)
    Geometry.add_vertex!(node.polygon, 0.0, 0.25)
    Geometry.add_vertex!(node.polygon, 0.05, 0.25)
    Geometry.add_vertex!(node.polygon, 0.05, 0.15)
    Geometry.add_vertex!(node.polygon, 0.05, 0.05)

    Geometry.add_vertex!(node.polygon, 0.15, 0.05)
    Geometry.add_vertex!(node.polygon, 0.25, 0.0)
    Geometry.add_vertex!(node.polygon, 0.25, -0.05)
    Geometry.add_vertex!(node.polygon, 0.15, -0.05)
    Geometry.add_vertex!(node.polygon, 0.05, -0.05)

    Geometry.build!(node.polygon)

    Nodes.set_dirty!(node, true);
end

# --------------------------------------------------------
# Timing
# --------------------------------------------------------
function Nodes.update(node::HostNode, dt::Float64)
    Nodes.update!(node.detection, node)
    Particles.update!(node.particle_system, dt)

    pos = node.transform.position
    Particles.set_position!(node.particle_system, pos.x, pos.y)
end

# Called during visit/rendering which is AFTER update()
function Nodes.interpolate(node::HostNode, interpolation::Float64)
end

# --------------------------------------------------------
# Rendering
# --------------------------------------------------------
function Nodes.draw(node::HostNode, context::Rendering.RenderContext)
    if Nodes.is_dirty(node)
        Rendering.transform!(context, node.polygon)

        Nodes.set_dirty!(node, false)
    end

    Rendering.set_draw_color(context, node.color)
    Rendering.render_outlined_polygon(context, node.polygon, Rendering.CLOSED);

    aabb_color = Nodes.highlight_color(node.detection, node.inside)
    Rendering.set_draw_color(context, aabb_color)

    Geometry.set!(node.aabb, Nodes.get_bucket(node))
    Rendering.render_aabb_rectangle(context, node.aabb)

end

# --------------------------------------------------------
# Life cycle events
# --------------------------------------------------------
function Nodes.enter_node(node::HostNode, man::Nodes.NodeManager)
    println("enter ", node);
    Nodes.register_event_target(man, node);

    node.inside = Nodes.check!(node.detection, node, node.base.world)
end

function Nodes.exit_node(node::HostNode, man::Nodes.NodeManager)
    println("exit ", node);
    Nodes.unregister_event_target(man, node);
end

# --------------------------------------------------------
# Events
# --------------------------------------------------------
# Here we elect to receive keyboard events.
function Nodes.io_event(node::HostNode, event::Events.KeyboardEvent)
    # Events.print(event)
    if (event.keycode == Events.KEY_F && event.state == Events.KEY_PRESSED)
        pos = node.transform.position
        Particles.set_position!(node.particle_system, pos.x, pos.y)
        Particles.trigger_oneshot!(node.particle_system)
    end

    if (event.keycode == Events.KEY_E && event.state == Events.KEY_PRESSED)
        pos = node.transform.position
        Particles.set_position!(node.particle_system, pos.x, pos.y)
        Particles.explode!(node.particle_system)
    end

    if (event.keycode == Events.KEY_W && event.state == Events.KEY_PRESSED)
        node.particle_system.auto_trigger = !node.particle_system.auto_trigger
        if node.particle_system.auto_trigger
            println("Autotrigger ON")
        else
            println("Autotrigger OFF")
        end
    end

    set_state!(node.keystate, event)
end

function Nodes.io_event(node::HostNode, event::Events.MouseMotionEvent)
    set_motion_state!(node.drag, event.x, event.y, node)

    dragging = is_dragging(node.drag)
    # println(dragging, ", ", node.inside)
    if dragging && node.inside
        pos = node.transform.position
        Nodes.set_position!(node, pos.x + node.drag.delta.x, pos.y + node.drag.delta.y)
    end

    Nodes.set_device_point!(node.detection, Float64(event.x), Float64(event.y))
    node.inside = Nodes.check!(node.detection, node, node.base.world)
end

function Nodes.io_event(node::HostNode, event::Events.MouseButtonEvent)
    set_button_state!(node.drag, event.x, event.y, event.button, event.state, node)
end

# --------------------------------------------------------
# Grouping
# --------------------------------------------------------
function Nodes.get_children(node::HostNode)
    node.children
end

# --------------------------------------------------------
# Host specific functionality
# --------------------------------------------------------

max_stars_repo_name: wdevore/Ranger-Julia-SDL

max_issues_repo_name: wdevore/Ranger-Julia-SDL

max_forks_repo_name: wdevore/Ranger-Julia-SDL


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule rmapi_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("rmapi")
JLLWrappers.@generate_main_file("rmapi", UUID("3ae0f9c0-76b4-5b6c-94ea-a996d928aed7"))
end  # module rmapi_jll


text:
using Plots
using Unzip
using Random: shuffle!
using LaTeXStrings

## util
function datapoint(f, target_size, target_density=nothing)
    time = @elapsed g = if target_density === nothing
        f(round(Integer, target_size))
    else
        f(round(Integer, target_size), target_density)
    end
    size = hypergraphsize(g)
    density = log_density(g)
    size, time, density
end

exp_range(start, stop, points) = exp.(LinRange(log(start), log(stop), points))

function middles(y, x...)
    buckets = Dict()
    for (i, (yi, xi)) in enumerate(zip(y, zip(x...)))
        xi ∈ keys(buckets) || (buckets[xi] = [])
        push!(buckets[xi], (yi, i))
    end
    sort!([sort!(v)[Int((length(v)+1)/2)][2] for v in values(buckets)])
end

# Plotting functions
const DATA = [[] for _ in 1:6]
const COMPUTE = Ref(true)
scale=2
first_row_x = (
    xaxis = :log,
    #xlims = (10^.9, 10^8.6),
    xticks = (10.0 .^ (1:10), [L"\large\bf 10^{%$i}" for i in 1:10]),
)
first_row = (
    yaxis = :log10,
    xlabel = L"\textrm{\large\bf hypergraph size}",
    #ylabel = L"\textrm{\large\bf runtime (s)}",
    bottom_margin = 10Plots.px,
    guidefontsize = 14,
    #ylims = (10^-6.1, 10^-.9),
    fontfamily = "times",
    tickfontsize = 15,
    legendfontsize = 12,
    legend =:topleft,
    #grid = false,
    #markerstrokewidth = 0,
    markersize = 7,
    first_row_x...
    )

function make_figure_1()
    #500s at scale = 2
    fs, target = unzip(shuffle!(vcat(
        [(new_dchsbm, t) for t in 10 .^ (1:.5:7.5+scale)],
        [(old_dchsbm, t) for t in 10 .^ (1:.5:4.5+scale)],
        repeat(vcat(
        [(new_dchsbm, t) for t in 10 .^ (1:.5:6.5+scale)],
        [(old_dchsbm, t) for t in 10 .^ (1:.5:3.5+scale)]), 10),
        repeat(
        [(new_dchsbm, t) for t in 10 .^ (1:.5:4+scale/2)], 1000))))

    if COMPUTE[]
        @time sizes, times, densities = unzip(datapoint.(fs, target))
        push!(DATA[1], (fs, target, sizes, times, densities))
    else
        fs, target, sizes, times, densities = last(DATA[1])
    end

    #display(scatter(sizes, densities, group=string.(fs) .* " density"; first_row_x...))

    I = middles(times, target, fs)
    scatter(sizes[I], times[I], group=string.(fs[I]); first_row...,
        labels = [L"\textrm{\large\bf FBD}" L"\textrm{\large\bf CVB}"],
        yticks = (10.0 .^ ((-5.0):5.0), [L"\large\bf 10^{%$i}" for i in -5:5]),)
end
function make_figure_2()
    fs, target = unzip(shuffle!(vcat(
        [(new_kronecker, t) for t in 10 .^ (1:.5:7.5+scale)],
        [(old_kronecker, t) for t in 10 .^ (1:.5:6+scale)],
        repeat(vcat(
        [(new_kronecker, t) for t in 10 .^ (1:.5:6.5+scale)],
        [(old_kronecker, t) for t in 10 .^ (1:.5:5+scale)]), 10),
        repeat(vcat(
        [(new_kronecker, t) for t in 10 .^ (1:.5:3.5+scale/2)],
        [(old_kronecker, t) for t in 10 .^ (1:.5:2+scale/2)]), 1000))))

    if COMPUTE[]
        @time sizes, times, densities = unzip(datapoint.(fs, target))
        push!(DATA[2], (fs, target, sizes, times, densities))
    else
        fs, target, sizes, times, densities = last(DATA[2])
    end

    #display(scatter(sizes, densities, group=string.(fs) .* " density"; first_row_x...))

    I = middles(times, target, fs)
    scatter(sizes[I], times[I], group=string.(fs[I]); first_row...,
        labels = [L"\textrm{\large\bf FBD}" L"\textrm{\large\bf ERG}"],
        yticks = (10.0 .^ ((-6.0):5.0), [L"\large\bf 10^{%$i}" for i in -6:5]),)
end

function make_figure_3()
    fs, target = unzip(shuffle!(vcat(
        (scale >= 2 ? [(new_hyperpa, 8.25)] : []),
        [(new_hyperpa, t) for t in 10 .^ (2:.5:6.5+scale)],
        (scale >= 2 ? [(old_hyperpa, t) for t in 45000*10 .^ (0:.25:1)] : []),
        repeat(vcat(
        (scale >= 2 ? [(old_hyperpa, t) for t in 45000*10 .^ (0:.25:.5)] : []),
        [(new_hyperpa, t) for t in 10 .^ (2:.5:5.5+scale)]), 10),
        repeat(
        [(new_hyperpa, t) for t in 10 .^ (2:.5:3+scale/2)], 1000))))

    if COMPUTE[]
        @time sizes, times, densities = unzip(datapoint.(fs, target))
        push!(DATA[3], (fs, target, sizes, times, densities))
    else
        fs, target, sizes, times, densities = last(DATA[3])
    end

    #display(scatter(sizes, densities, group=string.(fs) .* " density"; first_row_x...))

    I = middles(times, target, fs)

    scatter(sizes[I], times[I], group=string.(fs[I]); first_row...,
        ylabel = L"\textrm{\large\bf runtime (s)}",
        labels = [L"\textrm{\large\bf FBD}" L"\textrm{\large\bf TYHS}"],
        xticks = (10.0 .^ (2:8), [L"\large\bf 10^{%$i}" for i in 2:8]),
        yticks = (10.0 .^ ((-4.0):5.0), [L"\large\bf 10^{%$i}" for i in -4:5]),)
end

function make_figure_4()
    #12 seconds at trials=1
    fs, target = unzip(shuffle!(repeat(vcat(
        [((x,y) -> new_dchsbm(x,y,kmax=10), t) for t in vcat([3e-21, 1.5e-19], 10 .^ ((-17:1:1).+4 .- LinRange(-√4,√4,19).^2))],
        [((x,y) -> old_dchsbm(x,y,kmax=10), t) for t in 9:.5:15]), 15)))

    if COMPUTE[]
        @time sizes, times, densities = unzip(datapoint.(fs, 10^7, target))
        push!(DATA[4], (fs, target, sizes, times, densities))
    else
        fs, target, sizes, times, densities = last(DATA[4])
    end

    #display(scatter(densities, sizes, group=string.(fs) .* " density"; yaxis = :log))

    I = middles(times, target, fs)
    scatter(densities[I], times[I]./sizes[I], group=string.(fs[I]);
        yaxis = :log,
        yticks = (10.0 .^ (-8:-4), [L"\large\bf 10^{%$i}" for i in -8:-4]),
        xticks = (2:6, [L"\large\bf %$x" for x in 2:6]),
        bottom_margin = 10Plots.px,
        fontfamily = "times",
        guidefontsize = 14,
        tickfontsize = 15,
        legendfontsize = 12,
        legend=:topleft,
        ylabel = L"\textrm{\large\bf runtime (s) / hypergraph size      ..}",
        xlabel = L"\textrm{\large\bf log(hypergraph size) / log(nodes)}",
        xlims = (2,6),
        labels = [L"\textrm{\large\bf FBD}" L"\textrm{\large\bf CVB}"],
        #grid = false,
        #markerstrokewidth = 0,
        markersize = 7)
end
function make_figure_5()
    # 1 hour? at trials=11
    fs, target = unzip(shuffle!(repeat(vcat(
        [(new_dchsbm, t) for t in vcat([1e-11], 10 .^ ((-10:.5:1).+2 .- LinRange(-√2,√2,23).^2))],
        [(old_dchsbm, t) for t in 10 .^ (-1.4:.2:1)]), 11)))

    if COMPUTE[]
        @time sizes, times, densities = unzip(datapoint.(fs, 10^7, target))
        push!(DATA[5], (fs, target, sizes, times, densities))
    else
        fs, target, sizes, times, densities = last(DATA[5])
    end

    #display(scatter(densities, sizes, group=string.(fs) .* " density"; yaxis = :log))

    I = middles(times, target, fs)
    scatter(densities[I], times[I]./sizes[I], group=string.(fs[I]);
        yaxis = :log,
        yticks = (10.0 .^ (-7:-5), [L"\large\bf 10^{%$i}" for i in -7:-5]),
        xticks = (1:.5:3, [L"\large\bf %$x" for x in 1:.5:3]),
        xlims = (1,3),
        bottom_margin=10Plots.px,
        right_margin=10Plots.px,
        fontfamily = "times",
        guidefontsize = 14,
        tickfontsize = 15,
        legendfontsize = 12,
        legend=:topleft,
        #ylabel = L"\textrm{\large\bf runtime (s) / hypergraph size      ..}",
        xlabel = L"\textrm{\large\bf log(hypergraph size) / log(nodes)}",
        labels = [L"\textrm{\large\bf FBD}" L"\textrm{\large\bf CVB}"],
        #grid = false,
        #markerstrokewidth = 0,
        markersize = 7)
end

function make_figure_6()
    # 16m at trials = 15
    fs, target = unzip(shuffle!(repeat(vcat(
        [(new_kronecker, t) for t in [1e-49, 1e-45, 1e-40, 1e-37, 1e-30, 1e-24, 1e-20, 1e-14, 1e-13, 1e-9, 1e-7, 3e-4, 3e-2, 3e3] * 1e-4],
        [(old_kronecker, t) for t in [1e-13, 1e-11, 1e-9, 5e-8, 2e-6, 4e-5, 1e-3, 1e-2, 1e-1, .5, 1, 10, 100]]), 15)))

    if COMPUTE[]
        @time sizes, times, densities = unzip(datapoint.(fs, 10^7, target))
        push!(DATA[6], (fs, target, sizes, times, densities))
    else
        fs, target, sizes, times, densities = last(DATA[6])
    end

    #display(scatter(densities, sizes, group=string.(fs) .* " density"; yaxis = :log))

    I = middles(times, target, fs)
    scatter(densities[I], times[I]./sizes[I], group=string.(fs[I]);
        yaxis = :log,
        yticks = (10.0 .^ (-7:-2), [L"\large\bf 10^{%$i}" for i in -7:-2]),
        xticks = (1:.5:3, [L"\large\bf %$x" for x in 1:.5:3]),
        xlims = (1,3),
        bottom_margin=10Plots.px,
        right_margin=10Plots.px,
        guidefontsize = 14,
        tickfontsize = 15,
        legendfontsize = 12,
        legend=:topright,
        fontfamily = "times",
        #ylabel = L"\textrm{\large\bf runtime (s) / hypergraph size      ..}",
        xlabel = L"\textrm{\large\bf log(hypergraph size) / log(nodes)}",
        labels = [L"\textrm{\large\bf FBD}" L"\textrm{\large\bf ERG}"],
        #grid = false,
        #markerstrokewidth = 0,
        markersize = 7)
end

## Post processing
function save_figures()

    path = joinpath(dirname(@__DIR__), "figures", "")
    mkpath(path)

    #COMPUTE[] && display("Saved: $(save_data())")
    #savefig(make_figure_1(), path*"dchsbm_size.pdf")
    #COMPUTE[] && display("Saved: $(save_data())")
    #savefig(make_figure_2(), path*"kronecker_size.pdf")
    #COMPUTE[] && display("Saved: $(save_data())")
    #savefig(make_figure_3(), path*"hyperpa_size.pdf")
    COMPUTE[] && display("Saved: $(save_data())")
    savefig(make_figure_4(), path*"dchsbm_density_k10.pdf")
    #COMPUTE[] && display("Saved: $(save_data())")
    #savefig(make_figure_5(), path*"dchsbm_density_k3.pdf")
    #COMPUTE[] && display("Saved: $(save_data())")
    #savefig(make_figure_6(), path*"kronecker_density_k3.pdf")
    COMPUTE[] && display("Saved: $(save_data())")
end

function save_data(n=round(Integer, time())%(60*60*24*365))
    open("data_$n.txt", "w") do io
        write(io, string(DATA))
    end
    n
end
function load_data(n)
    v = read("data_$n.txt")
    s = String(v)
    s2 = replace(s,
        "FBDCompare.var" => "",
        "\"()" => "\"",
        "Function[" => "Union{String, Function}[")
    e = Meta.parse(s2)
    d = eval(e)
    DATA .= d
    COMPUTE[] || nothing
end

## The figure at the beginning of the paper
function fbd_with_duplicate_removal(s::FBD.ER_sampler{N, K}, m) where {N, K}
    g = Set{NTuple{K, Int}}()
    sizehint!(g, m)
    while length(g) < m
        push!(g, rand(s))
    end
    g
end

function make_figure_0()
    # 40s at trials = 101
    n = 35
    k = 3
    pts = 50
    trials = 301
    fs, target = unzip(shuffle!(repeat(vec(collect(Iterators.product(1:4,
        round.(Integer, LinRange(0,n^k-1,pts+1)[2:end]#=10 .^ LinRange(1, log10(n^k-1), pts)=#)))), trials)))
    function F(f, m)
        f > 3 && m / n^k > .95 && return NaN
        if f == 1
            @elapsed ER.coin_flip(n, k, m)
        elseif f == 2
            @elapsed ER.grass_hop(n, k, m)
        elseif f == 3
            @elapsed rand(ER_sampler(n, k), m)
        elseif f == 4
            @elapsed fbd_with_duplicate_removal(ER_sampler(n, k), m)
        end
    end

    @time times = F.(fs, target)

    I = middles(times, target, fs)
    sort!(I, by=i->target[i])
    p = plot(target[I]./n^k, times[I]./target[I]./k, group=string.(fs[I]);
        ylims = (0,5e-8),
        yformatter = t -> L"\large\bf%$(round(Integer,t*1e9))",
        xticks = (0:.2:1, [L"\large\bf %$t" for t in 0:.2:1]),
        bottom_margin=10Plots.px,
        right_margin=10Plots.px,
        legend=(.2,.93),
        fontfamily = "times",
        tickfontsize = 12,
        legendfontsize = 10,
        ylabel = L"\textrm{\large\bf runtime (ns) / hypergraph size}",
        xlabel = L"\textrm{\large\bf hyperedges / possible hyperedges}",
        labels = [L"\textrm{\bf Coin Flipping}" L"\textrm{\bf Grass Hopping}" L"\textrm{\bf FBD}" L"\textrm{\bf FBD with duplicate removal}"],
        )
    savefig(joinpath(dirname(@__DIR__), "figures", "er.pdf"))
    p
end


text:
export solveMG,solveGMRES_MG,solveBiCGSTAB_MG,solveCG_MG,getAfun

function solveMG(param::MGparam,b::ArrayTypes,x::ArrayTypes,verbose::Bool)
param = adjustMemoryForNumRHS(param,eltype(b),size(b,2));
tol = param.relativeTol;
numCores = param.numCores;
const oneType = one(eltype(b));
const zeroType = zero(eltype(b));
maxIter = param.maxOuterIter;
A = param.As[1];
r = param.memCycle[1].r;
oneType = one(eltype(b));
r[:] = b;

if vecnorm(x)==0
    res = vecnorm(b);
    res_init = res;
else
	SpMatMul(-oneType,A,x,oneType,r,numCores)#  r -= A'*x;
    res = vecnorm(r);
    res_init = res;
end

for count = 1:maxIter
	x = recursiveCycle(param,b,x,1);
	SpMatMul(-oneType,A,x,zeroType,r,numCores); #  r = -A'*x;
	addVectors(oneType,b,r); # r = r + b;
	res_prev = res;
	res = vecnorm(r);
	if verbose
		println(string("Cycle ",count," done with relres: ",res/res_init,". Convergence factor: ",res/res_prev));
	end
	if res/res_init < tol
		break;
	end
end
return x,param;
end
####################################################################################################################
# this function checks if the memory allocated in param fits the nrhs and generates a function for applying the cycle.
# Also - it checks if the hierarchy needs to be transposed or not.
function getMultigridPreconditioner(param::MGparam,B::ArrayTypes,verbose::Bool=false)
	TYPE = eltype(B);
	n = size(B,1)
	nrhs = size(B,2);
	if hierarchyExists(param)==false
		println("You have to do a setup first.")
	end
	param = adjustMemoryForNumRHS(param,TYPE,nrhs);
	z = param.memCycle[1].x;
	MMG(b) = (z[:] = 0.0; recursiveCycle(param,b,z,1));
	return MMG;
end

function getAfun(AT::SparseMatrixCSC,Az::Array,numCores::Int64)
	function Afun(z::ArrayTypes)
		SpMatMul(AT,z,Az,numCores);
		return Az;
	end
	return Afun;
end

function solveBiCGSTAB_MG(AT::SparseCSCTypes,param::MGparam,b::ArrayTypes,x0::ArrayTypes,verbose::Bool = false)
	return solveBiCGSTAB_MG(getAfun(AT,param.memCycle[1].b,param.numCores),param,b,x0,verbose);
end

function solveBiCGSTAB_MG(Afun::Function,param::MGparam,b::ArrayTypes,x0::ArrayTypes,verbose::Bool = false)
MMG = getMultigridPreconditioner(param,b,verbose);
out= -2;
if verbose
	out = 1;
end
if size(b,2)==1
	b = vec(b);
	x, flag,rnorm,iter = KrylovMethods.bicgstb(Afun,b,tol = param.relativeTol,maxIter = param.maxOuterIter,M1 = MMG,M2 = identity, x = x0,out=out);
else
	x, flag,rnorm,iter = KrylovMethods.blockBiCGSTB(Afun,b,tol = param.relativeTol,maxIter = param.maxOuterIter,M1 = MMG,M2 = identity, x = x0,out=out);
end
nprec = 2*iter*size(b,2) + (flag==-3)*size(b,2);
return x,param,iter,nprec
end

function solveCG_MG(AT::SparseCSCTypes,param::MGparam,b::ArrayTypes,x0::ArrayTypes,verbose::Bool = false)
	return solveCG_MG(getAfun(AT,param.memCycle[1].b,param.numCores),param,b,x0,verbose);
end

function solveCG_MG(Afun::Function,param::MGparam,b::ArrayTypes,x0::ArrayTypes,verbose::Bool = false)
MMG = getMultigridPreconditioner(param,b,verbose);
out = -2;
if verbose
	out = 1;
end
if size(b,2)==1
	b = vec(b);
	x, flag,rnorm,iter = KrylovMethods.cg(Afun,b,tol = param.relativeTol,maxIter = param.maxOuterIter,M = MMG, x = vec(x0),out=out);
else
	x, flag,rnorm,iter = KrylovMethods.blockCG(Afun,b,tol = param.relativeTol,maxIter = param.maxOuterIter,M = MMG, X = x0,out=out);
end
return x,param,iter;
end

####################################################################################################################
function solveGMRES_MG(AT::SparseCSCTypes,param::MGparam,b::ArrayTypes,x0::ArrayTypes,verbose::Bool = false,inner=3)
return solveGMRES_MG(getAfun(AT,param.memCycle[1].b,param.numCores),param,b,x0,verbose,inner);
end

function solveGMRES_MG(Afun::Function,param::MGparam,b::ArrayTypes,x0::ArrayTypes,verbose::Bool = false,inner=3)
param = adjustMemoryForNumRHS(param,eltype(b),size(b,2));
outerIter = param.maxOuterIter;
nrhs = size(b,2);
N 	 = size(b,1);
rhsType = eltype(b);

flexible = true; # there are tons of reasons here why this mey be true (to save the last Vcycle). So, assuming this is true.
# TODO: fix to have an expression for flexible.
if nrhs == 1
	GMRES_MEM = getFGMRESmem(N,flexible,rhsType,inner);
else
	GMRES_MEM = getFGMRESmem(N,flexible,rhsType,inner,nrhs);
	# GMRES_MEM = getBlockFGMRESmem(N,nrhs,flexible,rhsType,inner);
end

numCores = param.numCores;

oneType = one(eltype(b));

MMG = getMultigridPreconditioner(param,b,verbose);

if length(x0)==0
	x = zeros(eltype(b),size(b));
	r = copy(b);
	res = vecnorm(b);
	res_init = res;
else
	x = x0;
	if vecnorm(x)==0
		res = vecnorm(b);
		r = copy(b);
		res_init = res;
	else
		r = b - Afun(x);
		res = vecnorm(r);
		res_init = res;
	end
end
tol = copy(param.relativeTol);
tol *= res_init;
num_iter = 0;
num_prec = 0;
rnorms = 0;
for k=1:outerIter
	# if verbose
		# println("Outer iter ",k-1,":");
	# end
	if nrhs==1
		(x,rnorms) = FGMRES(Afun,r,x,inner,MMG,tol,verbose,true,numCores,GMRES_MEM);
	else
		(x,rnorms) = BlockFGMRES(Afun,r,x,inner,MMG,tol,verbose,true,numCores,GMRES_MEM);
	end
	num_iter = num_iter+1;
	num_prec = num_prec + length(rnorms)*nrhs;
	if verbose
		println(k,": relres: ", rnorms[end]/res_init)
	end
	if rnorms[end] < tol
		break;
	end
	r[:] = b;
	r -= Afun(x);
	# if verbose
		# println(vecnorm(r)/res_init)
		# println("--------------------------------")
	# end
end
if verbose println("(Block)FGMRES finished in ",(num_iter-1)*inner + length(rnorms)," inner iterations, norm: ",rnorms[end]/res_init ); end
# if verbose println("(Block)FGMRES finished in ",num_prec," inner iterations, norm: ",rnorms[end]/res_init ); end
# if verbose println("GMRES finished in ",num_iter*inner," inner iterations, norm: ",vecnorm(b-Afun(x))/res_init ); end
return x,param,num_iter,num_prec;
end


text:
const accept_regex = "([^\\r\\n]*)(\\n|\\r)*.*"

function parse_comment(fncall)
    argind = findfirst(isequal('('), fncall)
    name = fncall[1:(argind - 1)]
    parsed_args = Meta.parse(replace(fncall[argind:end], ";" => ","))
    args, kwargs = Vector{String}(), Dict{Symbol,String}()
    if isa(parsed_args, Expr) && parsed_args.head == :tuple
        started_kwargs = false
        for x in parsed_args.args
            if isa(x, Expr) && (x.head == :kw || x.head == :(=)) && isa(x.args[1], Symbol)
                @assert !haskey(kwargs, x.args[1]) "kwargs must all be unique"
                kwargs[x.args[1]] = string(x.args[2])
                started_kwargs = true
            else
                @assert !started_kwargs "kwargs must come after other args"
                push!(args, string(x))
            end
        end
    elseif isa(parsed_args, Expr) && parsed_args.head == :(=) && isa(parsed_args.args[1], Symbol)
        kwargs[parsed_args.args[1]] = string(parsed_args.args[2])
    else
        push!(args, string(parsed_args))
    end
    return name, args, kwargs
end