text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

# fallback text/plain representation of any type:
show(io::IO, ::MIME"text/plain", x) = show(io, x)

# multiline show functions for types defined before multimedia.jl:
function show(io::IO, ::MIME"text/plain", iter::Union{KeyIterator,ValueIterator})
    print(io, summary(iter))
    isempty(iter) && return
    print(io, ". ", isa(iter,KeyIterator) ? "Keys" : "Values", ":")
    limit::Bool = get(io, :limit, false)
    if limit
        sz = displaysize(io)
        rows, cols = sz[1] - 3, sz[2]
        rows < 2 && (print(io, " …"); return)
        cols < 4 && (cols = 4)
        cols -= 2 # For prefix "  "
        rows -= 1 # For summary
    else
        rows = cols = typemax(Int)
    end

    for (i, v) in enumerate(iter)
        print(io, "\n  ")
        i == rows < length(iter) && (print(io, "⋮"); break)

        if limit
            str = sprint(0, show, v, env=io)
            str = _truncate_at_width_or_chars(str, cols, "\r\n")
            print(io, str)
        else
            show(io, v)
        end
    end
end

function show(io::IO, ::MIME"text/plain", t::Associative{K,V}) where {K,V}
    # show more descriptively, with one line per key/value pair
    recur_io = IOContext(io, :SHOWN_SET => t)
    limit::Bool = get(io, :limit, false)
    if !haskey(io, :compact)
        recur_io = IOContext(recur_io, :compact => true)
    end

    print(io, summary(t))
    isempty(t) && return
    print(io, ":")
    show_circular(io, t) && return
    if limit
        sz = displaysize(io)
        rows, cols = sz[1] - 3, sz[2]
        rows < 2   && (print(io, " …"); return)
        cols < 12  && (cols = 12) # Minimum widths of 2 for key, 4 for value
        cols -= 6 # Subtract the widths of prefix "  " separator " => "
        rows -= 1 # Subtract the summary

        # determine max key width to align the output, caching the strings
        ks = Vector{AbstractString}(uninitialized, min(rows, length(t)))
        vs = Vector{AbstractString}(uninitialized, min(rows, length(t)))
        keylen = 0
        vallen = 0
        for (i, (k, v)) in enumerate(t)
            i > rows && break
            ks[i] = sprint(0, show, k, env=recur_io)
            vs[i] = sprint(0, show, v, env=recur_io)
            keylen = clamp(length(ks[i]), keylen, cols)
            vallen = clamp(length(vs[i]), vallen, cols)
        end
        if keylen > max(div(cols, 2), cols - vallen)
            keylen = max(cld(cols, 3), cols - vallen)
        end
    else
        rows = cols = typemax(Int)
    end

    for (i, (k, v)) in enumerate(t)
        print(io, "\n  ")
        i == rows < length(t) && (print(io, rpad("⋮", keylen), " => ⋮"); break)

        if limit
            key = rpad(_truncate_at_width_or_chars(ks[i], keylen, "\r\n"), keylen)
        else
            key = sprint(0, show, k, env=recur_io)
        end
        print(recur_io, key)
        print(io, " => ")

        if limit
            val = _truncate_at_width_or_chars(vs[i], cols - keylen, "\r\n")
            print(io, val)
        else
            show(recur_io, v)
        end
    end
end

function show(io::IO, ::MIME"text/plain", f::Function)
    ft = typeof(f)
    mt = ft.name.mt
    if isa(f, Core.IntrinsicFunction)
        show(io, f)
        id = Core.Intrinsics.bitcast(Int32, f)
        print(io, " (intrinsic function #$id)")
    elseif isa(f, Core.Builtin)
        print(io, mt.name, " (built-in function)")
    else
        name = mt.name
        isself = isdefined(ft.name.module, name) &&
                 ft == typeof(getfield(ft.name.module, name))
        n = length(methods(f))
        m = n==1 ? "method" : "methods"
        sname = string(name)
        ns = (isself || '#' in sname) ? sname : string("(::", ft, ")")
        what = startswith(ns, '@') ? "macro" : "generic function"
        print(io, ns, " (", what, " with $n $m)")
    end
end

function show(io::IO, ::MIME"text/plain", r::LinSpace)
    # show for linspace, e.g.
    # linspace(1,3,7)
    # 7-element LinSpace{Float64}:
    #   1.0,1.33333,1.66667,2.0,2.33333,2.66667,3.0
    print(io, summary(r))
    if !isempty(r)
        println(io, ":")
        print_range(io, r)
    end
end

function show(io::IO, ::MIME"text/plain", t::Task)
    show(io, t)
    if t.state == :failed
        println(io)
        showerror(io, CapturedException(t.result, t.backtrace))
    end
end

show(io::IO, ::MIME"text/plain", X::AbstractArray) = showarray(io, X, false)
show(io::IO, ::MIME"text/plain", r::AbstractRange) = show(io, r) # always use the compact form for printing ranges

# display something useful even for strings containing arbitrary
# (non-UTF8) binary data:
function show(io::IO, ::MIME"text/plain", s::String)
    if isvalid(s)
        show(io, s)
    else
        println(io, sizeof(s), "-byte String of invalid UTF-8 data:")
        showarray(io, Vector{UInt8}(s), false; header=false)
    end
end

function show(io::IO, ::MIME"text/plain", opt::JLOptions)
    println(io, "JLOptions(")
    fields = fieldnames(JLOptions)
    nfields = length(fields)
    for (i, f) in enumerate(fields)
        v = getfield(opt, i)
        if isa(v, Ptr{UInt8})
            v = (v != C_NULL) ? unsafe_string(v) : ""
        elseif isa(v, Ptr{Ptr{UInt8}})
            v = unsafe_load_commands(v)
        end
        println(io, "  ", f, " = ", repr(v), i < nfields ? "," : "")
    end
    print(io, ")")
end

# showing exception objects as descriptive error messages

"""
    showerror(io, e)

Show a descriptive representation of an exception object.
"""
showerror(io::IO, ex) = show(io, ex)

function showerror(io::IO, ex::BoundsError)
    print(io, "BoundsError")
    if isdefined(ex, :a)
        print(io, ": attempt to access ")
        if isa(ex.a, AbstractArray)
            print(io, summary(ex.a))
        else
            show(io, MIME"text/plain"(), ex.a)
        end
        if isdefined(ex, :i)
            !isa(ex.a, AbstractArray) && print(io, "\n ")
            print(io, " at index [")
            if isa(ex.i, AbstractRange)
                print(io, ex.i)
            else
                join(io, ex.i, ", ")
            end
            print(io, ']')
        end
    end
end

function showerror(io::IO, ex::TypeError)
    print(io, "TypeError: ")
    if ex.expected === Bool
        print(io, "non-boolean ($(typeof(ex.got))) used in boolean context")
    else
        if isa(ex.got, Type)
            tstr = "Type{$(ex.got)}"
        else
            tstr = string(typeof(ex.got))
        end
        if isempty(ex.context)
            ctx = "in $(ex.func)"
        else
            ctx = "in $(ex.func), in $(ex.context)"
        end
        print(io, ctx, ", expected $(ex.expected), got ", tstr)
    end
end

function showerror(io::IO, ex, bt; backtrace=true)
    try
        with_output_color(have_color ? error_color() : :nothing, io) do io
            showerror(io, ex)
        end
    finally
        backtrace && show_backtrace(io, bt)
    end
end

function showerror(io::IO, ex::LoadError, bt; backtrace=true)
    print(io, "LoadError: ")
    showerror(io, ex.error, bt, backtrace=backtrace)
    print(io, "\nin expression starting at $(ex.file):$(ex.line)")
end
showerror(io::IO, ex::LoadError) = showerror(io, ex, [])

function showerror(io::IO, ex::InitError, bt; backtrace=true)
    print(io, "InitError: ")
    showerror(io, ex.error, bt, backtrace=backtrace)
    print(io, "\nduring initialization of module $(ex.mod)")
end
showerror(io::IO, ex::InitError) = showerror(io, ex, [])

function showerror(io::IO, ex::DomainError, bt; backtrace=true)
    if isa(ex.val, AbstractArray)
        compact = get(io, :compact, true)
        limit = get(io, :limit, true)
        print(IOContext(io, :compact => compact, :limit => limit),
              "DomainError with ", ex.val)
    else
        print(io, "DomainError with ", ex.val)
    end
    if isdefined(ex, :msg)
        print(io, ":\n", ex.msg)
    end
    backtrace && show_backtrace(io, bt)
    nothing
end

function showerror(io::IO, ex::SystemError)
    if ex.extrainfo === nothing
        print(io, "SystemError: $(ex.prefix): $(Libc.strerror(ex.errnum))")
    else
        print(io, "SystemError (with $(ex.extrainfo)): $(ex.prefix): $(Libc.strerror(ex.errnum))")
    end
end
showerror(io::IO, ::DivideError) = print(io, "DivideError: integer division error")
showerror(io::IO, ::StackOverflowError) = print(io, "StackOverflowError:")
showerror(io::IO, ::UndefRefError) = print(io, "UndefRefError: access to undefined reference")
showerror(io::IO, ::EOFError) = print(io, "EOFError: read end of file")
function showerror(io::IO, ex::ErrorException)
    print(io, ex.msg)
    if ex.msg == "type String has no field data"
        println(io)
        print(io, "Use `Vector{UInt8}(str)` instead.")
    end
end
showerror(io::IO, ex::KeyError) = print(io, "KeyError: key $(repr(ex.key)) not found")
showerror(io::IO, ex::InterruptException) = print(io, "InterruptException:")
showerror(io::IO, ex::ArgumentError) = print(io, "ArgumentError: $(ex.msg)")
showerror(io::IO, ex::AssertionError) = print(io, "AssertionError: $(ex.msg)")
showerror(io::IO, ex::OverflowError) = print(io, "OverflowError: $(ex.msg)")

function showerror(io::IO, ex::UndefVarError)
    if ex.var in [:UTF16String, :UTF32String, :WString, :utf16, :utf32, :wstring, :RepString]
        return showerror(io, ErrorException("""
        `$(ex.var)` has been moved to the package LegacyStrings.jl:
        Run Pkg.add("LegacyStrings") to install LegacyStrings on Julia v0.5-;
        Then do `using LegacyStrings` to get `$(ex.var)`.
        """))
    end
    print(io, "UndefVarError: $(ex.var) not defined")
end

function showerror(io::IO, ex::InexactError)
    print(io, "InexactError: ", ex.func, '(', ex.T, ", ", ex.val, ')')
end

function showerror(io::IO, ex::MethodError)
    # ex.args is a tuple type if it was thrown from `invoke` and is
    # a tuple of the arguments otherwise.
    is_arg_types = isa(ex.args, DataType)
    arg_types = is_arg_types ? ex.args : typesof(ex.args...)
    f = ex.f
    meth = methods_including_ambiguous(f, arg_types)
    if length(meth) > 1
        return showerror_ambiguous(io, meth, f, arg_types)
    end
    arg_types_param::SimpleVector = arg_types.parameters
    print(io, "MethodError: ")
    ft = typeof(f)
    name = ft.name.mt.name
    f_is_function = false
    kwargs = Any[]
    if startswith(string(ft.name.name), "#kw#")
        f = ex.args[2]
        ft = typeof(f)
        name = ft.name.mt.name
        arg_types_param = arg_types_param[3:end]
        temp = ex.args[1]
        kwargs = Any[(temp[i*2-1], temp[i*2]) for i in 1:(length(temp) ÷ 2)]
        ex = MethodError(f, ex.args[3:end])
    end
    if f == Base.convert && length(arg_types_param) == 2 && !is_arg_types
        f_is_function = true
        # See #13033
        T = striptype(ex.args[1])
        if T === nothing
            print(io, "First argument to `convert` must be a Type, got ", ex.args[1])
        else
            print(io, "Cannot `convert` an object of type ", arg_types_param[2], " to an object of type ", T)
        end
    elseif isempty(methods(f)) && !isa(f, Function)
        print(io, "objects of type $ft are not callable")
    else
        if ft <: Function && isempty(ft.parameters) &&
                isdefined(ft.name.module, name) &&
                ft == typeof(getfield(ft.name.module, name))
            f_is_function = true
            print(io, "no method matching ", name)
        elseif isa(f, Type)
            if isa(f, DataType) && f.abstract
                # Print a more appropriate message if the only method
                # on the type is the default one from sysimg.jl.
                ms = methods(f)
                if length(ms) == 1
                    m = first(ms)
                    if Base.is_default_method(m)
                        print(io, "no constructors have been defined for $f")
                        return
                    end
                end
            end
            print(io, "no method matching ", f)
        else
            print(io, "no method matching (::", ft, ")")
        end
        print(io, "(")
        for (i, typ) in enumerate(arg_types_param)
            print(io, "::$typ")
            i == length(arg_types_param) || print(io, ", ")
        end
        if !isempty(kwargs)
            print(io, "; ")
            for (i, (k, v)) in enumerate(kwargs)
                print(io, k, "=")
                show(IOContext(io, :limit => true), v)
                i == length(kwargs) || print(io, ", ")
            end
        end
        print(io, ")")
    end
    if ft <: AbstractArray
        print(io, "\nUse square brackets [] for indexing an Array.")
    end
    # Check for local functions that shadow methods in Base
    if f_is_function && isdefined(Base, name)
        basef = getfield(Base, name)
        if basef !== ex.f && method_exists(basef, arg_types)
            println(io)
            print(io, "You may have intended to import Base.", name)
        end
    end
    if (ex.world != typemax(UInt) && method_exists(ex.f, arg_types) &&
        !method_exists(ex.f, arg_types, ex.world))
        curworld = ccall(:jl_get_world_counter, UInt, ())
        println(io)
        print(io, "The applicable method may be too new: running in world age $(ex.world), while current world is $(curworld).")
    end
    if !is_arg_types
        # Check for row vectors used where a column vector is intended.
        vec_args = []
        hasrows = false
        for arg in ex.args
            isrow = isa(arg,Array) && ndims(arg)==2 && size(arg,1)==1
            hasrows |= isrow
            push!(vec_args, isrow ? vec(arg) : arg)
        end
        if hasrows && applicable(f, vec_args...)
            print(io, "\n\nYou might have used a 2d row vector where a 1d column vector was required.",
                      "\nNote the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].",
                      "\nYou can convert to a column vector with the vec() function.")
        end
    end
    # Give a helpful error message if the user likely called a type constructor
    # and sees a no method error for convert
    if (f === Base.convert && !isempty(arg_types_param) && !is_arg_types &&
        isa(arg_types_param[1], DataType) &&
        arg_types_param[1].name === Type.body.name)
        construct_type = arg_types_param[1].parameters[1]
        println(io)
        print(io, "This may have arisen from a call to the constructor $construct_type(...),",
                  "\nsince type constructors fall back to convert methods.")
    end
    try
        show_method_candidates(io, ex, kwargs)
    catch
        warn(io, "Error showing method candidates, aborted")
    end
end

striptype(::Type{T}) where {T} = T
striptype(::Any) = nothing

function showerror_ambiguous(io::IO, meth, f, args)
    print(io, "MethodError: ", f, "(")
    p = args.parameters
    for (i,a) in enumerate(p)
        print(io, "::", a)
        i < length(p) && print(io, ", ")
    end
    print(io, ") is ambiguous. Candidates:")
    sigfix = Any
    for m in meth
        print(io, "\n  ", m)
        sigfix = typeintersect(m.sig, sigfix)
    end
    if isa(unwrap_unionall(sigfix), DataType) && sigfix <: Tuple
        print(io, "\nPossible fix, define\n  ")
        Base.show_tuple_as_call(io, :function,  sigfix)
    end
    nothing
end

#Show an error by directly calling jl_printf.
#Useful in Base submodule __init__ functions where STDERR isn't defined yet.
function showerror_nostdio(err, msg::AbstractString)
    stderr_stream = ccall(:jl_stderr_stream, Ptr{Void}, ())
    ccall(:jl_printf, Cint, (Ptr{Void},Cstring), stderr_stream, msg)
    ccall(:jl_printf, Cint, (Ptr{Void},Cstring), stderr_stream, ":\n")
    ccall(:jl_static_show, Csize_t, (Ptr{Void},Any), stderr_stream, err)
    ccall(:jl_printf, Cint, (Ptr{Void},Cstring), stderr_stream, "\n")
end

function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[])
    is_arg_types = isa(ex.args, DataType)
    arg_types = is_arg_types ? ex.args : typesof(ex.args...)
    arg_types_param = Any[arg_types.parameters...]
    # Displays the closest candidates of the given function by looping over the
    # functions methods and counting the number of matching arguments.
    f = ex.f
    ft = typeof(f)
    lines = []
    # These functions are special cased to only show if first argument is matched.
    special = f in [convert, getindex, setindex!]
    funcs = Any[(f, arg_types_param)]

    # An incorrect call method produces a MethodError for convert.
    # It also happens that users type convert when they mean call. So
    # pool MethodErrors for these two functions.
    if f === convert && !isempty(arg_types_param)
        at1 = arg_types_param[1]
        if isa(at1,DataType) && (at1::DataType).name === Type.body.name && !Core.Inference.has_free_typevars(at1)
            push!(funcs, (at1.parameters[1], arg_types_param[2:end]))
        end
    end

    for (func,arg_types_param) in funcs
        for method in methods(func)
            buf = IOBuffer()
            tv = Any[]
            sig0 = method.sig
            if Base.is_default_method(method)
                continue
            end
            while isa(sig0, UnionAll)
                push!(tv, sig0.var)
                sig0 = sig0.body
            end
            s1 = sig0.parameters[1]
            sig = sig0.parameters[2:end]
            print(buf, "  ")
            if !isa(func, s1)
                # function itself doesn't match
                return
            else
                # TODO: use the methodshow logic here
                use_constructor_syntax = isa(func, Type)
                print(buf, use_constructor_syntax ? func : typeof(func).name.mt.name)
            end
            print(buf, "(")
            t_i = copy(arg_types_param)
            right_matches = 0
            for i = 1 : min(length(t_i), length(sig))
                i > 1 && print(buf, ", ")
                # If isvarargtype then it checks whether the rest of the input arguments matches
                # the varargtype
                if Base.isvarargtype(sig[i])
                    sigstr = string(unwrap_unionall(sig[i]).parameters[1], "...")
                    j = length(t_i)
                else
                    sigstr = string(sig[i])
                    j = i
                end
                # Checks if the type of arg 1:i of the input intersects with the current method
                t_in = typeintersect(rewrap_unionall(Tuple{sig[1:i]...}, method.sig),
                                     rewrap_unionall(Tuple{t_i[1:j]...}, method.sig))
                # If the function is one of the special cased then it should break the loop if
                # the type of the first argument is not matched.
                t_in === Union{} && special && i == 1 && break
                if t_in === Union{}
                    if Base.have_color
                        Base.with_output_color(Base.error_color(), buf) do buf
                            print(buf, "::$sigstr")
                        end
                    else
                        print(buf, "!Matched::$sigstr")
                    end
                    # If there is no typeintersect then the type signature from the method is
                    # inserted in t_i this ensures if the type at the next i matches the type
                    # signature then there will be a type intersect
                    t_i[i] = sig[i]
                else
                    right_matches += j==i ? 1 : 0
                    print(buf, "::$sigstr")
                end
            end
            special && right_matches==0 && return # continue the do-block

            if length(t_i) > length(sig) && !isempty(sig) && Base.isvarargtype(sig[end])
                # It ensures that methods like f(a::AbstractString...) gets the correct
                # number of right_matches
                for t in arg_types_param[length(sig):end]
                    if t <: rewrap_unionall(unwrap_unionall(sig[end]).parameters[1], method.sig)
                        right_matches += 1
                    end
                end
            end

            if right_matches > 0 || length(ex.args) < 2
                if length(t_i) < length(sig)
                    # If the methods args is longer than input then the method
                    # arguments is printed as not a match
                    for (k, sigtype) in enumerate(sig[length(t_i)+1:end])
                        sigtype = isvarargtype(sigtype) ? unwrap_unionall(sigtype) : sigtype
                        if Base.isvarargtype(sigtype)
                            sigstr = string(sigtype.parameters[1], "...")
                        else
                            sigstr = string(sigtype)
                        end
                        if !((min(length(t_i), length(sig)) == 0) && k==1)
                            print(buf, ", ")
                        end
                        if Base.have_color
                            Base.with_output_color(Base.error_color(), buf) do buf
                                print(buf, "::$sigstr")
                            end
                        else
                            print(buf, "!Matched::$sigstr")
                        end
                    end
                end
                kwords = Symbol[]
                if isdefined(ft.name.mt, :kwsorter)
                    kwsorter_t = typeof(ft.name.mt.kwsorter)
                    kwords = kwarg_decl(method, kwsorter_t)
                    length(kwords) > 0 && print(buf, "; ", join(kwords, ", "))
                end
                print(buf, ")")
                show_method_params(buf, tv)
                print(buf, " at ", method.file, ":", method.line)
                if !isempty(kwargs)
                    unexpected = Symbol[]
                    if isempty(kwords) || !(any(endswith(string(kword), "...") for kword in kwords))
                        for (k, v) in kwargs
                            if !(k in kwords)
                                push!(unexpected, k)
                            end
                        end
                    end
                    if !isempty(unexpected)
                        Base.with_output_color(Base.error_color(), buf) do buf
                            plur = length(unexpected) > 1 ? "s" : ""
                            print(buf, " got unsupported keyword argument$plur \"", join(unexpected, "\", \""), "\"")
                        end
                    end
                end
                if ex.world < min_world(method)
                    print(buf, " (method too new to be called from this world context.)")
                end
                # TODO: indicate if it's in the wrong world
                push!(lines, (buf, right_matches))
            end
        end
    end

    if !isempty(lines) # Display up to three closest candidates
        Base.with_output_color(:normal, io) do io
            println(io)
            print(io, "Closest candidates are:")
            sort!(lines, by = x -> -x[2])
            i = 0
            for line in lines
                println(io)
                if i >= 3
                    print(io, "  ...")
                    break
                end
                i += 1
                print(io, String(take!(line[1])))
            end
        end
    end
end

function show_trace_entry(io, frame, n; prefix = "")
    print(io, "\n", prefix)
    show(io, frame, full_path=true)
    n > 1 && print(io, " (repeats ", n, " times)")
end

# Contains file name and file number. Gets set when a backtrace
# or methodlist is shown. Used by the REPL to make it possible to open
# the location of a stackframe/method in the editor.
global LAST_SHOWN_LINE_INFOS = Tuple{String, Int}[]

function show_backtrace(io::IO, t::Vector)
    resize!(LAST_SHOWN_LINE_INFOS, 0)
    filtered = Any[]
    process_backtrace((fr, count) -> push!(filtered, (fr, count)), t)
    isempty(filtered) && return

    if length(filtered) == 1 && StackTraces.is_top_level_frame(filtered[1][1])
        f = filtered[1][1]
        if f.line == 0 && f.file == Symbol("")
            # don't show a single top-level frame with no location info
            return
        end
    end

    print(io, "\nStacktrace:")
    frame_counter = 0
    for (last_frame, n) in filtered
        frame_counter += 1
        show_trace_entry(IOContext(io, :backtrace => true), last_frame, n, prefix = string(" [", frame_counter, "] "))
        push!(LAST_SHOWN_LINE_INFOS, (string(last_frame.file), last_frame.line))
    end
end

function show_backtrace(io::IO, t::Vector{Any})
    for entry in t
        show_trace_entry(io, entry...)
    end
end

# call process_func on each frame in a backtrace
function process_backtrace(process_func::Function, t::Vector, limit::Int=typemax(Int); skipC = true)
    n = 0
    last_frame = StackTraces.UNKNOWN
    count = 0
    for i = eachindex(t)
        lkups = StackTraces.lookup(t[i])
        for lkup in lkups
            if lkup === StackTraces.UNKNOWN
                continue
            end

            if lkup.from_c && skipC; continue; end
            if i == 1 && lkup.func == :error; continue; end
            count += 1
            if count > limit; break; end

            if lkup.file != last_frame.file || lkup.line != last_frame.line || lkup.func != last_frame.func || lkup.linfo !== lkup.linfo
                if n > 0
                    process_func(last_frame, n)
                end
                n = 1
                last_frame = lkup
            else
                n += 1
            end
        end
    end
    if n > 0
        process_func(last_frame, n)
    end
end

"""
Determines whether a method is the default method which is provided to all types from sysimg.jl.
Such a method is usually undesirable to be displayed to the user in the REPL.
"""
function is_default_method(m::Method)
    return m.module == Base && m.file == Symbol("sysimg.jl") && m.sig == Tuple{Type{T},Any} where T
end

max_stars_repo_name: ihnorton/julia

max_issues_repo_name: ihnorton/julia

max_forks_repo_name: ihnorton/julia


text:
using Test;

direction_to_xy = Dict(
    0 => [0, 1], # north
    90 => [1, 0], # east
    180 => [0, -1], # south
    270 => [-1, 0], # west
)

function turn(start_direction, degrees)
    return mod(start_direction + degrees, 360)
end

function move(start_pos, direction, distance)
    m = direction_to_xy[direction] .* distance
    return start_pos + m
end

function run(fname)
    f = open(fname, "r")
    lines = readlines(f)

    pos = [0, 0]
    direction = 90 # East
    println(pos)
    for l in lines
        command = l[1]
        number = parse(Int, l[2:length(l)])
        println("cmd=", command, " num=", number)

        # Action N means to move north by the given value.
        mov_dir = direction
        if command == 'N'
            pos = move(pos, 0, number)
        elseif command == 'S'
            pos = move(pos, 180, number)
        elseif command == 'E'
            pos = move(pos, 90, number)
        elseif command == 'W'
            pos = move(pos, 270, number)
        elseif command == 'L'
            direction = turn(direction, -1 * number)
        elseif command == 'R'
            direction = turn(direction, number)
        elseif command == 'F'
            pos = move(pos, direction, number)
        end

        println("pos: ", pos, " facing: ", direction_to_xy[direction])
    end

    result = abs(pos[1]) + abs(pos[2])
    println("[part 1] File = ", fname, " ... Result = ", result)

    return result
end

function reflect(start_pos, degrees)
    deg = mod(degrees, 360)

    if deg == 0
        return start_pos
    elseif deg == 90
        # [1,2] .. R90  (L270) .. [2,-1]  # swap and -1 the second element
        return [start_pos[2], -1 * start_pos[1]]
    elseif deg == 180
        # [1,2] .. R180 (L180) .. [-1,-2] # -1 both elements
        return start_pos .* -1
    elseif deg == 270
        # [1,2] .. R270 (L90)  .. [-2,1]  # swap and -1 the first element
        return [-1 * start_pos[2], start_pos[1]]
    else
        throw("invalid input: degrees = " * degrees)
    end
end

function run2(fname)
    f = open(fname, "r")
    lines = readlines(f)

    pos = [10, 1] # waypoint pos
    ship_pos = [0, 0] # ship position
    println(pos)
    for l in lines
        command = l[1]
        number = parse(Int, l[2:length(l)])
        println("cmd=", command, " num=", number)

        if command == 'N'
            pos = move(pos, 0, number)
        elseif command == 'S'
            pos = move(pos, 180, number)
        elseif command == 'E'
            pos = move(pos, 90, number)
        elseif command == 'W'
            pos = move(pos, 270, number)
        elseif command == 'L'
            pos = reflect(pos, -1 * number)
        elseif command == 'R'
            pos = reflect(pos, number)
        elseif command == 'F'
            # Move the ship
            for i in 1:number
                ship_pos += pos
            end
        end

        println("ship_pos: ", ship_pos, " waypoint_pos: ", pos)
    end

    result = abs(ship_pos[1]) + abs(ship_pos[2])
    println("[part 2] File = ", fname, " ... Result = ", result)

    return result
end

@test run("12ex.txt") == 25
run("12.txt")

@test run2("12ex.txt") == 286
run2("12.txt")

ext: jl


text:
# License for this file: MIT (expat)
# Copyright 2017-2021, DLR Institute of System Dynamics and Control

# Provide functions to handle time and state events

"""
    @enum EventRestart NoRestart Restart FullRestart Terminate

Define how to continue or restart integration after an event. Usually, `Restart`
should be used. Only in special cases, the other flags are useful.

- `NoRestart`, continue integration without restarting the integrator
- `Restart`, restart integrator
- `FullRestart`, restart integrator and simulation state (so dimensions may change)
- `Terminate`, terminate integration
"""
@enum EventRestart NoRestart Restart FullRestart Terminate

using  ForwardDiff
getValue(v) = v
getValue(v::ForwardDiff.Dual) = v.value
getValue(v::Measurements.Measurement) = Measurements.value(v)

const nClock = 100
const nSample = 100
const nAfterDefault = 100

mutable struct EventHandler{FloatType,TimeType}
    stopTime::TimeType              # stopTime of simulation

    # Logging
    logEvents::Bool                 # = true, if events shall be logged
    nZeroCrossings::Int             # Number of zero crossing calls
    nRestartEvents::Int             # Number of Restart events
    nStateEvents::Int               # Number of state events
    nTimeEvents::Int                # Number of time events

    # Input values for the event functions
    time::TimeType                  # Current simulation time
    initial::Bool                   # = true, if model is called at initialization
                                    #         (if initial, event=true)
    terminal::Bool                  # = true, if model is called for termination (close files, streams, visualization, ...)
    event::Bool                     # = true, if model is called at an event
    afterSimulationStart::Bool      # = true, if model is called after simulation start
    crossing::Bool                  # = true, if model is called to compute crossing function
    firstEventIterationDirectlyAfterInitial::Bool # = true, at the first event iteration directly after initial at model.options.startTime.
    triggerEventDirectlyAfterInitial::Bool        # = true, if time event shall be triggered directly after initial at model.options.startTime

    # Values especially for simulations with several segments
    firstInitialOfAllSegments::Bool # = true, if model is called at initialization of the first simulation segment.
    terminalOfAllSegments::Bool     # = true, if model is called for termination at the last simulation segment.

    # Computed by the event functions
    # For time events:
    maxTime::TimeType         # Integrate at most up to maxTime
                              # (if integrateToEvent == true, maxTime = nextEventTime,
                              #  otherwise maxTime > nextEventTime)
    nextEventTime::TimeType   # Next time event instant (= realmax(Time) if no event)
    integrateToEvent::Bool    # = true, if integrator shall integrate to nextEventTime
                              # = false, if integrator can integrate beyond nextEventTime
    restart::EventRestart     # Type of integrator restart at current event
    newEventIteration::Bool   # = true, if another event iteration; = false, if no event iteration anymore
    firstEventIteration::Bool # = true, if first iteration at an event.

    # For state events:
    nz::Int                 # Number of event indicators
    z::Vector{FloatType}    # Vector of event indicators (zero crossings). If one of z[i] passes
                            # zero, that is beforeEvent(z[i])*z[i] < 0, an event is triggered
                            # (allocated during instanciation according to nz).
    zPositive::Vector{Bool} # = true if z > 0 at the last event instant, otherwise false

    # For after time events:
    nafter::Int             # Number of after time events
    after::Vector{Bool}     # after[i] = time >= after(<variable i>)

    # For clocks (time events):
    clock::Vector{TimeType}
    sample::Vector{Any}

    function EventHandler{FloatType,TimeType}(; nz::Int=0, nAfter::Int=0, logEvents::Bool=false) where {FloatType,TimeType}
        @assert(nz >= 0)
        @assert(nAfter >= 0)
        nAfter = nAfter > 0 ? nAfter : nAfterDefault
        new(floatmax(TimeType), logEvents, 0, 0, 0, 0, convert(TimeType,0),
            false, false, false, false, false, false, false, false, false, floatmax(TimeType), floatmax(TimeType),
            true, NoRestart, false, false, nz, ones(FloatType,nz), fill(false, nz), nAfter, fill(false,nAfter),
            fill(convert(TimeType,0),nClock), Vector{Any}(undef, nSample))
    end
end

# Default constructors
#EventHandler(           ; kwargs...)                   = EventHandler{Float64  ,Float64}(; kwargs...)
#EventHandler{FloatType}(; kwargs...) where {FloatType} = EventHandler{FloatType,Float64}(; kwargs...)

function reinitEventHandler(eh::EventHandler{FloatType,TimeType}, stopTime::TimeType, logEvents::Bool)::Nothing where {FloatType,TimeType}
    eh.logEvents      = logEvents
    eh.nZeroCrossings = 0
    eh.nRestartEvents = 0
    eh.nStateEvents   = 0
    eh.nTimeEvents    = 0

    eh.time     = convert(TimeType, 0)
    eh.initial  = false
    eh.terminal = false
    eh.event    = false
    eh.crossing = false
    eh.firstEventIterationDirectlyAfterInitial = false
    eh.triggerEventDirectlyAfterInitial = false

    eh.afterSimulationStart = false
    eh.firstInitialOfAllSegments = false
    eh.terminalOfAllSegments     = false
    eh.stopTime      = stopTime
    eh.maxTime       = floatmax(TimeType)
    eh.nextEventTime = floatmax(TimeType)
    eh.integrateToEvent = false
    eh.restart          = Restart
    eh.newEventIteration   = false
    eh.firstEventIteration = true
    eh.z .= convert(FloatType, 0)
    eh.after .= false

    return nothing
end

positiveCrossingAsString(positive::Bool) = positive ? " became > 0" : " became <= 0"
negativeCrossingAsString(negative::Bool) = negative ? " became < 0" : " became >= 0"

function initEventIteration!(h::EventHandler{FloatType,TimeType}, t::TimeType)::Nothing where {FloatType,TimeType}
    h.time          = t
    h.restart       = NoRestart
    h.maxTime       = floatmax(TimeType)
    h.nextEventTime = floatmax(TimeType)
    h.newEventIteration   = false
    h.firstEventIteration = true
    return nothing
end

const zEps = 1.e-10

function setNextEvent!(h::EventHandler{FloatType,TimeType}, nextEventTime::TimeType;
                       triggerEventDirectlyAfterInitial=false,
                       integrateToEvent::Bool=true,
                       restart::EventRestart=Restart)::Nothing where {FloatType,TimeType}
    #println("... setNextEvent!: time = ", h.time, ", nextEventTime = ", nextEventTime, ", restart = ", restart)
    if (h.event && nextEventTime > h.time) || (h.initial && nextEventTime >= h.time)
        if h.initial && triggerEventDirectlyAfterInitial && nextEventTime == h.time
            h.triggerEventDirectlyAfterInitial = true

            if nextEventTime < h.nextEventTime
                h.nextEventTime = nextEventTime
                if h.logEvents
                    println("        nextEventTime = ", round(nextEventTime, sigdigits=6), " s")
                end
            end
        else
            if integrateToEvent
                h.maxTime = min(h.maxTime, nextEventTime)
            end
            if nextEventTime < h.nextEventTime
                h.nextEventTime    = nextEventTime
                h.integrateToEvent = integrateToEvent
                if h.logEvents
                    println("        nextEventTime = ", round(nextEventTime, sigdigits=6),
                            " s, integrateToEvent = ", integrateToEvent ? "true" : "false")
                end
            end
        end
        h.restart = max(h.restart, restart)
    end
    return nothing
end

function after!(h::EventHandler{FloatType,TimeType}, nr::Int, t::Number, tAsString::String,
                leq::Union{Nothing,ModiaBase.LinearEquations{FloatType}};
                restart::EventRestart=Restart)::Bool where {FloatType,TimeType}
    # time >= t  (it is required that t is a discrete-time expression, but this cannot be checked)
    t2 = convert(TimeType,t)
    if h.initial
        h.after[nr] = h.time >= t2
        if h.logEvents
            println("        after(", tAsString, " (= ", t2, ")) became ", h.after[nr] ? "true" : "false")
        end
        if t2 > h.time
            setNextEvent!(h, t2, restart = restart)
        end

    elseif h.event
        if abs(h.time - t2) < 1E-10
            if h.logEvents && !h.after[nr]
                println("        after(", tAsString, " (= ", t2, ")) became true")
            end
            h.after[nr] = true
        elseif t2 > h.time
            setNextEvent!(h, t2, restart = restart)
            h.after[nr] = false
        else
            if h.logEvents && !h.after[nr]
                println("        after(", tAsString, " (= ", t2, ")) became true")
            end
            h.after[nr] = true
        end
    end
    return h.after[nr]
end

#positive!(h, nr, crossing, crossingAsString, leq_mode; restart=Restart) = positive!(h, nr, getValue(crossing), crossingAsString, leq_mode; restart=restart)

function positive!(h::EventHandler{FloatType,TimeType}, nr::Int, crossing, crossingAsString::String,
                   leq::Union{Nothing,ModiaBase.LinearEquations{FloatType}};
                   restart::EventRestart=Restart)::Bool where {FloatType,TimeType}
    crossing = getValue(crossing)

    if h.initial
        if !isnothing(leq) && leq.mode >= 0
            # crossing has no meaningful value (called in algebraic loop with zero or unit vectors of unknowns).
            h.zPositive[nr] = false  # set to an arbitrary value
            h.z[nr]         = -zEps  # set to an arbitrary value that is consistent to zPositive
            return h.zPositive[nr]
        end

        h.zPositive[nr] = crossing > convert(FloatType,0)
        if h.logEvents
            println("        ", crossingAsString, " (= ", crossing, ")", positiveCrossingAsString(h.zPositive[nr]))
        end

    elseif h.event
        if !isnothing(leq) && leq.mode >= 0
            # crossing has no meaningful value (called in algebraic loop with zero or unit vectors of unknowns).
            return h.zPositive[nr]
        end
        new_zPositive = crossing > convert(FloatType,0)
        change = (h.zPositive[nr] && !new_zPositive) || (!h.zPositive[nr] && new_zPositive)
        h.zPositive[nr] = new_zPositive

        if change
            h.restart = max(h.restart, restart)
            if h.logEvents
                println("        ", crossingAsString, " (= ", crossing, ")", positiveCrossingAsString(h.zPositive[nr]))
            end
            if !isnothing(leq) && leq.mode == -1
                # Solution of mixed linear equation system is not consistent to positve(..)
                leq.success = false
                if leq.niter > leq.niter_max
                    push!(leq.inconsistentPositive, crossingAsString)
                end
            end
        end
    end
    h.z[nr] = crossing + (h.zPositive[nr] ? zEps : -zEps)

    return h.zPositive[nr]
end

function negative!(h::EventHandler{FloatType,TimeType}, nr::Int, crossing, crossingAsString::String,
                   leq::Union{Nothing,ModiaBase.LinearEquations{FloatType}};
                   restart::EventRestart=Restart)::Bool where {FloatType,TimeType}
    crossing = getValue(crossing)

    if h.initial
        if !isnothing(leq) && leq.mode >= 0
            # crossing has no meaningful value (called in algebraic loop with zero or unit vectors of unknowns).
            h.zPositive[nr] = true  # set to an arbitrary value
            h.z[nr]         = zEps  # set to an arbitrary value that is consistent to zPositive
            return !h.zPositive[nr]
        end

        h.zPositive[nr] = !(crossing < convert(FloatType,0))
        if h.logEvents
            println("        ", crossingAsStringg, " (= ", crossing, ")", negativeCrossingAsString(!h.zPositive[nr]))
        end

    elseif h.event
        if !isnothing(leq) && leq.mode >= 0
            # crossing has no meaningful value (called in algebraic loop with zero or unit vectors of unknowns).
            return !h.zPositive[nr]
        end
        new_zPositive = !(crossing < convert(FloatType,0))
        change = (h.zPositive[nr] && !new_zPositive) || (!h.zPositive[nr] && new_zPositive)
        h.zPositive[nr] = new_zPositive

        if change
            h.restart = max(h.restart, restart)
            if h.logEvents
                println("        ", crossingAsStringg, " (= ", crossing, ")", negativeCrossingAsString(!h.zPositive[nr]))
            end
            if !isnothing(leq) && leq.mode == -1
                # Solution of mixed linear equation system is not consistent to negative(..)
                leq.success = false
                if leq.niter > leq.niter_max
                    push!(leq.inconsistentNegative, crossingAsString)
                end
            end
        end
    end
    h.z[nr] = crossing + (h.zPositive[nr] ? zEps : -zEps)

    return !h.zPositive[nr]
end

#=
function change!(h::EventHandler{FloatType,TimeType}, nr::Int, crossing::FloatType, crossingAsString::String,
                 leq::Union{Nothing,ModiaBase.LinearEquations{FloatType}};
                 restart::EventRestart=Restart)::Bool where {FloatType,TimeType}
    if leq_mode >= 0
        return crossing > convert(FloatType,0)
    end

    h.z[nr] = crossing
    if h.initial
        h.zPositive[nr] = crossing > convert(FloatType,0)
        if h.logEvents
            println("        ", crossingAsString, " (= ", crossing, ")", positiveCrossingAsString(h.zPositive[nr]))
        end
        return false

    elseif h.event
        new_zPositive = crossing > convert(FloatType,0)
        change = (h.zPositive[nr] && !new_zPositive) || (!h.zPositive[nr] && new_zPositive)
        h.zPositive[nr] = new_zPositive

        if change
            h.restart = max(h.restart, restart)
            if h.logEvents
                println("        ", crossingAsString, " (= ", crossing, ")",  positiveCrossingAsString(h.zPositive[nr]))
            end
            h.newEventIteration = true
            return true
        end
    end

    return false
end
=#

function edge!(h::EventHandler{FloatType,TimeType}, nr::Int, crossing, crossingAsString::String,
               leq::Union{Nothing,ModiaBase.LinearEquations{FloatType}};
               restart::EventRestart=Restart)::Bool where {FloatType,TimeType}

    if !isnothing(leq)
        @error "edge(" * crossingAsString * ") is called in a linear system of equations with\n" *
               "iteration variables $(leq.vTear_names). This is not supported."
    end

    crossing = getValue(crossing)

    if h.initial
        h.zPositive[nr] = crossing > convert(FloatType,0)

        if h.logEvents
            println("        ", crossingAsString, " (= ", crossing, ")", positiveCrossingAsString(h.zPositive[nr]))
        end

    elseif h.event
        new_zPositive = crossing > convert(FloatType,0)
        edge     = !h.zPositive[nr] && new_zPositive
        downEdge = h.zPositive[nr] && !new_zPositive
        h.zPositive[nr] = new_zPositive

        if edge
            h.restart = max(h.restart, restart)
            if h.logEvents
                println("        ", crossingAsString, " (= ", crossing, ") became > 0")
            end
            h.newEventIteration = true
            h.z[nr] = crossing + (h.zPositive[nr] ? zEps : -zEps)
            return true
        elseif downEdge
            h.restart = max(h.restart, NoRestart)
            if h.logEvents
                println("        ", crossingAsString, " (= ", crossing, ") became <= 0")
            end
        end
    end

    h.z[nr] = crossing + (h.zPositive[nr] ? zEps : -zEps)
    return false
end


text:
# These are parameters that affect the performance of the algorithms. They may need to be changed for different data sets.

initialize(m,n) = [(0.5m,0.5n,0.37m),
					(0.5m,0.5n,0.5m),
					(0.35m,0.5n,0.5m),
					(0.65m,0.5n,0.5m),
					(0.5m,0.5n,0.7m),
					(0.5m,0.65n,0.5m),
					(0.5m,0.35n,0.5m),
				]

get_defaults() = Options(-1/3,
blue,
1/8000,
[ π*[-3/4,-1/4], π*[1/4,3/4] ],
80,
[0.05,0.95],[0.05,0.95],[0.25,0.8],
initialize,
( NewtonTrustRegion(), NelderMead(), ),
)

mutable struct Options
	# Where to expect the purkinje reflection within the cornea. The value is normalized by the radius of the cornea, zero is at the corneal center, and the value should be in the interval [-1,1]. This only affects one initialization of the detection optimization, and if it is wrong, no harm is done.
	purkinje_location
	# Which color channel is best for detection of the purkinje image? Use red, green, blue, or Gray.
	purkinje_channel
	# Minimum allowable area to designate the Purkinje. Expressed as a fraction of the total image's area. If zero, any size is allowed.
	purkinje_minarea
	# These are the angles that are included in the cornea detection optimization. They are relative to the corneal center, with zero angle at six o'clock. Make a vector of intervals to include. The angles are selected from those spaced by 1 degree around the full circle.
	angle_ranges
	# The image is blurred with a gaussian having standard deviation equal to m/BLUR_WIDTH, where m is the row size.
	blur_width
	# These determine bounds on the allowable center location and cornea radius.
	bounds_row   # fraction of the row size
	bounds_column  # fraction of column size
	bounds_radius  # fraction of the row size
	# Initial values to try for the optimizer. Returns a vector of (i,j,r) tuples.
	initializer
	# Methods to try in the minimization.
	optimizers
end

function Options(;kwargs...)
	opt = get_defaults()
	for (name,val) in kwargs
		setfield!(opt,Symbol(name),val)
	end
	return opt
end

function show(io::IO,opt::Options)
	map(fieldnames(Options)) do fn
		println(io,fn,":  ",getfield(opt,fn))
	end
end

function saveopt(options::Options,file="options.txt")
	open(file,"w") do io
		show(io,options)
	end
	return file
end

max_stars_repo_name: tobydriscoll/cornea-detection

max_issues_repo_name: tobydriscoll/cornea-detection

max_forks_repo_name: tobydriscoll/cornea-detection


text:
# IF THIS SMALL FUNCTION IS PLACED IN THE STARTUP.JL
# FILE, IT WILL BE LOADED ON STARTUP. THE REST OF
# THIS EXAMPLE IS IN ALL UPPERCASE.
function RUNUPPERCASECODE(CO)
    COD = replace(lowercase(CO), "date" => "Date")
    for E in Meta.parse(COD, 1) eval(E) end
end

CODE = """BEGIN

USING DATES;
CENTEROBJECT(X, N) = BEGIN S = UPPERCASE(STRING(X)); RPAD(LPAD(S, DIV(N + LENGTH(S), 2)), N) END;
FUNCTION FORMATMONTH(YR, MO)
    DT = DATE(\"\$YR-\$MO-01\");
    DAYOFWEEKFIRST = DAYOFWEEK(DT);
    NUMWEEKLINES = 1;
    STR = UPPERCASE(CENTEROBJECT(MONTHNAME(DT), 20) * \"\\NMO TU WE TH FR SA SU\\N\");
    STR *= \" \" ^ (3 * (DAYOFWEEKFIRST - 1)) * LPAD(STRING(1), 2);
    FOR I = 2:DAYSINMONTH(DT)
        IF (I + DAYOFWEEKFIRST + 5) % 7 == 0
            STR *= \"\\N\" * LPAD(I, 2);
            NUMWEEKLINES += 1;
        ELSE
            STR *= LPAD(STRING(I), 3);
        END;
    END;
    STR *= NUMWEEKLINES < 6 ? \"\\N\\N\\N\" : \"\\N\\N\";
    ARR = [];
    FOR S IN SPLIT(STR, \"\\N\")
        PUSH!(ARR, RPAD(S, 20)[1:20])
    END;
    JOIN(ARR, \"\\N\");
END;

FUNCTION FORMATYEAR(DISPLAYYEAR)
    CALMONTHS = [FORMATMONTH(DISPLAYYEAR, MO) FOR MO IN 1:12];
    MONTHSPERLINE = 6;
    JOINSPACES = 2;
    STR = \"\\N\" * CENTEROBJECT(DISPLAYYEAR, 132) * \"\\N\";
    MONTHCAL = [SPLIT(FORMATMONTH(DISPLAYYEAR, I), \"\\N\") FOR I IN 1:12];
    FOR I IN 1:MONTHSPERLINE:LENGTH(CALMONTHS) - 1
        FOR J IN 1:LENGTH(MONTHCAL[1])
            MONTHLINES = MAP(X->MONTHCAL[X][J], I:I + MONTHSPERLINE - 1);
            STR *= RPAD(JOIN(MONTHLINES, \" \" ^ JOINSPACES), 132) * \"\\N\";
        END;
        STR *= \"\\N\";
    END;
    STR;
END;

PRINTLN(FORMATYEAR(1969));

END;
"""

RUNUPPERCASECODE(CODE)

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
#///////////////////////////////////////
#// File Name: predictor_test.jl
#// Author: Haruki Nishimura (hnishimura@stanford.edu)
#// Date Created: 2021/01/28
#// Description: Test code for src/predictor.jl
#///////////////////////////////////////

using Distributions
using LinearAlgebra
using PyCall
using Random

@testset "Trajectron Predictor Test" begin
    conf_file_name = "config.json"
    test_data_name = "eth_test.pkl";
    test_scene_id = 0;
    start_time_idx = 2;
    incl_robot_node = false;
    device = py"torch".device("cuda");

    scene_param = TrajectronSceneParameter(conf_file_name, test_data_name,
                                     test_scene_id, start_time_idx,
                                     incl_robot_node);
    prediction_steps = 12;
    use_robot_future = false;
    rng_seed_py = 12;
    deterministic = true;
    # Case 1: deterministic == true
    begin
        num_samples_1 = 1;
        rng_seed_py_1 = 1;
        scene_loader = TrajectronSceneLoader(scene_param, verbose=false);
        predictor_param_1 = TrajectronPredictorParameter(prediction_steps, num_samples_1,
                                                         use_robot_future, deterministic,
                                                         rng_seed_py_1);
        predictor_1 = TrajectronPredictor(predictor_param_1,
                                          scene_loader.model_dir,
                                          scene_loader.param.conf_file_name,
                                          device, verbose=false);
        initialize_scene_graph!(predictor_1, scene_loader)
        ado_states = fetch_ado_positions!(scene_loader, return_full_state=true);
        outputs_dict_1 = sample_future_ado_positions!(predictor_1, ado_states);
        @test size(collect(values(outputs_dict_1))[1]) == (num_samples_1, prediction_steps, 2);
        @test keys(convert_nodes_to_str(ado_states)) == keys(outputs_dict_1);
    end
    begin
        num_samples_2 = 1;
        rng_seed_py_2 = 123;
        scene_loader = TrajectronSceneLoader(scene_param, verbose=false);
        predictor_param_2 = TrajectronPredictorParameter(prediction_steps, num_samples_2,
                                                         use_robot_future, deterministic,
                                                         rng_seed_py_2);
        predictor_2 = TrajectronPredictor(predictor_param_2,
                                          scene_loader.model_dir,
                                          scene_loader.param.conf_file_name,
                                          device, verbose=false);
        initialize_scene_graph!(predictor_2, scene_loader)
        ado_states = fetch_ado_positions!(scene_loader, return_full_state=true);
        outputs_dict_2 = sample_future_ado_positions!(predictor_2, ado_states);
    end
    @test all(collect(values(outputs_dict_1))[1] .≈ collect(values(outputs_dict_2))[1])
    # Case 2: deterministic == false
    deterministic = false;
    begin
        num_samples_3 = 30;
        rng_seed_py_3 = 2;
        scene_loader = TrajectronSceneLoader(scene_param, verbose=false);
        predictor_param_3 = TrajectronPredictorParameter(prediction_steps, num_samples_3,
                                                         use_robot_future, deterministic,
                                                         rng_seed_py_3);
        predictor_3 = TrajectronPredictor(predictor_param_3,
                                          scene_loader.model_dir,
                                          scene_loader.param.conf_file_name,
                                          device, verbose=false);
        initialize_scene_graph!(predictor_3, scene_loader);
        ado_states = fetch_ado_positions!(scene_loader, return_full_state=true);
        outputs_dict_3 = sample_future_ado_positions!(predictor_3, ado_states);
        @test size(collect(values(outputs_dict_3))[1]) == (num_samples_3, prediction_steps, 2);
        @test keys(convert_nodes_to_str(ado_states)) == keys(outputs_dict_3);
    end
end

@testset "Trajectron Predictor Test (with Robot)" begin
    conf_file_name = "config.json"
    test_data_name = "eth_test.pkl";
    test_scene_id = 0;
    start_time_idx = 2;
    incl_robot_node = true;

    scene_param = TrajectronSceneParameter(conf_file_name, test_data_name,
                                           test_scene_id, start_time_idx,
                                           incl_robot_node);
    prediction_steps = 12;
    use_robot_future = true;
    rng_seed_py = 12;
    deterministic = true;
    device = py"torch".device("cpu");

    u_nominal_base = [0.0, 0.0];
    u_nominal_cand = append!([u_nominal_base],
                             [round.([a*cos(deg2rad(θ)), a*sin(deg2rad(θ))], digits=5)
                              for a = [2., 4.] for θ = 0.:45.:(360. - 45.)])

    ego_pos_init_vec = [5., 0.5];
    ego_pos_goal_vec = [5., 8.9];

    e_init = RobotState([ego_pos_init_vec; ego_pos_goal_vec]);
    robot_present_and_future = rand(length(u_nominal_cand), 1 + prediction_steps, 6);
    robot_present_and_future[1, :, :] .= 0.0;

    # Case 1: deterministic == true
    begin
        num_samples_1 = 1;
        rng_seed_py_1 = 1;
        scene_loader_1 = TrajectronSceneLoader(scene_param, verbose=false);
        predictor_param_1 = TrajectronPredictorParameter(prediction_steps, num_samples_1,
                                                         use_robot_future, deterministic,
                                                         rng_seed_py_1);
        predictor_1 = TrajectronPredictor(predictor_param_1,
                                          scene_loader_1.model_dir,
                                          scene_loader_1.param.conf_file_name,
                                          device, verbose=false);
        initialize_scene_graph!(predictor_1, scene_loader_1)
        ado_states_1 = fetch_ado_positions!(scene_loader_1, return_full_state=true);
        outputs_dict_1 = sample_future_ado_positions!(predictor_1, ado_states_1,
                                                      robot_present_and_future);
        @test size(collect(values(outputs_dict_1))[1]) == (length(u_nominal_cand), prediction_steps, 2);
        @test keys(convert_nodes_to_str(ado_states_1)) == keys(outputs_dict_1);
    end
    begin
        num_samples_2 = 1;
        rng_seed_py_2 = 123;
        scene_loader_2 = TrajectronSceneLoader(scene_param, verbose=false);
        predictor_param_2 = TrajectronPredictorParameter(prediction_steps, num_samples_2,
                                                         use_robot_future, deterministic,
                                                         rng_seed_py_2);
        predictor_2 = TrajectronPredictor(predictor_param_2,
                                          scene_loader_2.model_dir,
                                          scene_loader_2.param.conf_file_name,
                                          device, verbose=false);
        initialize_scene_graph!(predictor_2, scene_loader_2)
        ado_states_2 = fetch_ado_positions!(scene_loader_2, return_full_state=true);
        outputs_dict_2 = sample_future_ado_positions!(predictor_2, ado_states_2,
                                                      robot_present_and_future);
    end
    @test all(collect(values(outputs_dict_1))[1] .≈ collect(values(outputs_dict_2))[1])
    # Case 2: deterministic == false
    deterministic = false;
    begin
        num_samples_3 = 30;
        rng_seed_py_3 = 2;
        scene_loader_3 = TrajectronSceneLoader(scene_param, verbose=false);
        predictor_param_3 = TrajectronPredictorParameter(prediction_steps, num_samples_3,
                                                         use_robot_future, deterministic,
                                                         rng_seed_py_3);
        predictor_3 = TrajectronPredictor(predictor_param_3,
                                          scene_loader_3.model_dir,
                                          scene_loader_3.param.conf_file_name,
                                          device, verbose=false);
        initialize_scene_graph!(predictor_3, scene_loader_3);
        ado_states_3 = fetch_ado_positions!(scene_loader_3, return_full_state=true);
        outputs_dict_3 = sample_future_ado_positions!(predictor_3, ado_states_3,
                                                      robot_present_and_future);
        @test size(collect(values(outputs_dict_3))[1]) == (num_samples_3*length(u_nominal_cand), prediction_steps, 2);
        @test keys(convert_nodes_to_str(ado_states_3)) == keys(outputs_dict_3);
    end

    # Make sure permuted, reshaped outputs_dict in sample_future_ado_positions! is consistent with what's
    # required in forward-backward simulation. (num_samples*num_controls, prediction_steps, 2)
    begin
        dummy_array = rand(length(u_nominal_cand), num_samples_3,
                           prediction_steps, 2);
        squeezed_dummy_array = reshape(permutedims(dummy_array, [2, 1, 3, 4]), :,
                                       size(dummy_array, 3), size(dummy_array, 4));
        @test squeezed_dummy_array[1:num_samples_3, :, :] ==
                dummy_array[1, :, :, :];
        @test squeezed_dummy_array[1+num_samples_3:2*num_samples_3, :, :] ==
                dummy_array[2, :, :, :];
    end
end

@testset "Oracle Predictor Test" begin
    conf_file_name = "config.json"
    test_data_name = "eth_test.pkl";
    test_scene_id = 0;
    start_time_idx = 2;
    incl_robot_node = false;
    device = py"torch".device("cpu");

    scene_param = TrajectronSceneParameter(conf_file_name, test_data_name,
                                           test_scene_id, start_time_idx,
                                           incl_robot_node);
    prediction_steps = 50;
    scene_loader = TrajectronSceneLoader(scene_param, verbose=false);

    predictor_param = OraclePredictorParameter(prediction_steps);
    predictor = OraclePredictor(predictor_param, scene_loader);

    scene_loader.curr_time_idx = start_time_idx
    ado_pos_dict = fetch_ado_positions!(scene_loader)
    outputs_dict = sample_future_ado_positions!(predictor, ado_pos_dict);
    @test keys(convert_nodes_to_str(ado_pos_dict)) == keys(outputs_dict)

    function testfunc()
        for ii = 1:predictor.param.prediction_steps
            ado_pos_dict = fetch_ado_positions!(scene_loader)
            ado_pos_dict = convert_nodes_to_str(ado_pos_dict)
            for key in keys(outputs_dict)
                if in(key, keys(ado_pos_dict))
                    if !all(outputs_dict[key][1, ii, :] .≈ ado_pos_dict[key])
                        return false
                    end
                else
                    if !all(outputs_dict[key][1, ii, :] .== predictor.param.dummy_pos)
                        return false
                    end
                end
            end
        end
        return true;
    end
    @test testfunc()
end

@testset "Gaussian Predictor Test" begin
    rng = MersenneTwister(123);

    scene_param = SyntheticSceneParameter(rng);
    ado_pos_dict = Dict("Pedestrian/1" => [1.0, 1.0],
                        "Pedestrian/2" => [2.0, 1.0],
                        "Pedestrian/3" => [3.0, 1.0]);
    scene_loader = SyntheticSceneLoader(scene_param, ado_pos_dict);

    num_samples = 100;
    dto = 0.4;
    prediction_steps = 12;
    rng = MersenneTwister(123);
    # Case 1: deterministic == false
    deterministic = false
    begin
        predictor_param = GaussianPredictorParameter(prediction_steps, num_samples,
                                                     deterministic, rng);

        ado_vel_dict = Dict("Pedestrian/1" => MvNormal([0.0, 0.0], Diagonal([1.0, 1.0])),
                            "Pedestrian/2" => MvNormal([0.0, 0.0], Diagonal([1.0, 1.0])),
                            "Pedestrian/3" => MvNormal([0.0, 0.0], Diagonal([1.0, 1.0])));
        predictor = GaussianPredictor(predictor_param, dto, ado_vel_dict);
        outputs_dict = sample_future_ado_positions!(predictor, scene_loader.ado_pos_dict);
        @test size(collect(values(outputs_dict))[1]) == (num_samples, prediction_steps, 2);
        @test keys(outputs_dict) == keys(scene_loader.ado_pos_dict);

        ado_vel_dict_any = Dict("Any" => MvNormal([0.0, 0.0], Diagonal([1.0, 1.0])));
        predictor_any = GaussianPredictor(predictor_param, dto, ado_vel_dict_any);
        outputs_dict_any = sample_future_ado_positions!(predictor, scene_loader.ado_pos_dict);
        @test size(collect(values(outputs_dict_any))[1]) == (num_samples, prediction_steps, 2);
        @test keys(outputs_dict_any) == keys(scene_loader.ado_pos_dict);
    end
    # Case 2: deterministic == true
    deterministic = true
    begin
        rng_1 = MersenneTwister(1);
        num_samples = 1;
        predictor_param = GaussianPredictorParameter(prediction_steps, num_samples,
                                                     deterministic, rng_1);

        ado_vel_dict = Dict("Any" => MvNormal([1.0, 0.0], Diagonal([1.0, 1.0])));
        predictor = GaussianPredictor(predictor_param, dto, ado_vel_dict);
        outputs_dict_1 = sample_future_ado_positions!(predictor, scene_loader.ado_pos_dict);
        @test size(collect(values(outputs_dict_1))[1]) == (num_samples, prediction_steps, 2);
        @test keys(outputs_dict_1) == keys(scene_loader.ado_pos_dict);
        test_array = zeros(num_samples, prediction_steps, 2);
        for ii = 1:prediction_steps
            test_array[1, ii, 1] = 1.0 + 1.0*ii*dto;
            test_array[1, ii, 2] = 1.0;
        end
        @test all(collect(values(outputs_dict_1))[1] .≈ test_array)
    end
    begin
        rng_2 = MersenneTwister(123);
        num_samples = 1;
        predictor_param = GaussianPredictorParameter(prediction_steps, num_samples,
                                                     deterministic, rng_2);
        ado_vel_dict = Dict("Any" => MvNormal([1.0, 0.0], Diagonal([1.0, 1.0])));
        predictor = GaussianPredictor(predictor_param, dto, ado_vel_dict);
        outputs_dict_2 = sample_future_ado_positions!(predictor, scene_loader.ado_pos_dict);
    end
    all(collect(values(outputs_dict_1))[1] .≈ collect(values(outputs_dict_2))[1])
end


text:
"""
    read_TRI_mesh(filename) -> mesh::Mesh
"""
function read_TRI_mesh(fn::AbstractString)
    open(fn, "r") do io
        read_TRI_mesh(io)
    end
end

"""
    read_TRI_mesh(mesh_filename) -> mesh::Mesh

Imports a surface mesh (stored in an ASCII file named `mesh_filename`) into a
    `Mesh` object (i.e. node list and element list).

NOTE: The contents of `mesh_filename` must include the file extension, and the
    file must be stored in the current directory.

"""
function read_TRI_mesh(io,T=Type::Float64)

    thisLine = io |> readline |> strip
    while thisLine != "POINTS"
        thisLine = io |> readline |> strip
    end

    thisLine = io |> readline |> strip
    s = split(thisLine)
    NV = parse(Int, s[1])

    P = SVector{3,T}
    v = Vector{P}(NV)
    for i in 1:NV
        thisLine = io |> readline |>  strip
        d = readdlm(IOBuffer(thisLine), T)
        v[i] = P(d[2], d[3], d[4])
    end

    while thisLine != "TRIANGLES"
        thisLine = io |> readline |> strip
    end

    thisLine = io |> readline |> strip
    s = split(thisLine)
    NF = parse(Int, s[1])

    thisLine = io |> readline |> strip
    P = SVector{3,Int64}
    f = Vector{P}(NF); i = 0
    while thisLine != "END_TRIANGLES"
        d = readdlm(IOBuffer(thisLine), Int64)
        thisLine = io |> readline |>  strip
        f[i += 1] = P(d[2], d[3], d[4])
    end

    return Mesh(v, f)

end

max_stars_repo_name: krcools/CompScienceMeshes

max_issues_repo_name: krcools/CompScienceMeshes

max_forks_repo_name: krcools/CompScienceMeshes


text:
# default kernel function of difference types
const KERNEL_TYPE = Dict(ContinuousDim => gaussian, CategoricalDim => wang_ryzin, UnorderedCategoricalDim => aitchison_aitken)

function map_dim(candidates::Vector)
    unordered_to_index, index_to_unordered = Dict(), Dict()
    for (i, elem) in enumerate(candidates)
        unordered_to_index[elem] = i
        index_to_unordered[i] = elem
    end
    (unordered_to_index, index_to_unordered)
end

# Candidate need to be mapped from UnorderedCategoricalDim
function candidate_need_map(dim_type, candidate)
    if dim_type isa UnorderedCategoricalDim
        for _candidate in candidate
            if !(_candidate isa Real)
                return true
            end
        end
    end
    return false
end

# Observation need to be mapped from UnorderedCategoricalDim
function observation_need_map(dim_type, observation)
    if dim_type isa UnorderedCategoricalDim
        for _observation in observation
            if !(_observation isa Real)
                return true
            end
        end
    end
    return false
end

# Lazy evaluation univariate KDE
Base.@kwdef mutable struct KDEUniv
    type::DimensionType
    bandwidth::Real
    data::Vector
    kernel::Function
end
# Using default kernel for dim_type
function KDEUniv(dim_type::DimensionType, bandwidth, observation)
    KDEUniv(dim_type, bandwidth, observation, KERNEL_TYPE[typeof(dim_type)])
end

function pdf(kde::KDEUniv, x::Real; keep_all=true)
    densities = kde.kernel(kde.bandwidth, kde.data, x)
    if keep_all
        return densities
    else
        return mean(densities) / kde.bandwidth
    end
end

# Multivariate KDE based on KDEUniv
Base.@kwdef mutable struct KDEMulti
    # Type of every dimension, continuous or discrete
    dims::Vector
    # KDE from different dimensions
    KDEs::Vector
    # observations: An k*n matrix, where k is dimension of KDEs and n is number of observations
    observations::Vector
    mat_observations::Matrix
    # In UnorderedContinuous case, we assign an index 1:N to every value, where N=|D_i|, then we pass the 1:N to KDE
    # dimension i is number or not
    mapped::Vector
    unordered_to_index::Dict{KDEUniv, Dict{Any, Real}}
    index_to_unordered::Dict{KDEUniv, Dict{Real, Any}}
end

# Constructor without candidates
function KDEMulti(dims::Vector, observations::Vector)
    KDEMulti(dims, nothing, observations)
end
function KDEMulti(dims::Vector, bws::Union{Vector, Nothing}, observations::Vector)
    for (dim_type, observation) in zip(dims, observations)
        if observation_need_map(dim_type, observation)
            error("If there is Uncatogorical dimension and not a number, should specify its candidate value.")
        end
    end
    KDEMulti(dims, bws, observations, nothing)
end

# Constructor with candidates
## Convert tuple candidates to dict candidates
function get_dict_candidates(dim_types::Vector{DimensionType}, candidates::Tuple)
    dict_candidates = Dict{Int, Vector}()
    for (i, dim_type, candidate) in zip(1:length(dim_types), dim_types, candidates)
        if candidate_need_map(dim_type, candidate)
            dict_candidates[i] = candidate
        end
    end
    dict_candidates
end

## Tuple candidates
function KDEMulti(dims::Vector, observations::Vector, candidates::Tuple)
    KDEMulti(dims, nothing, observations, get_dict_candidates(dims, candidates))
end
## Dict candidates
function KDEMulti(dims::Vector, observations::Vector, candidates::Union{Dict{Int, Vector}, Nothing})
    KDEMulti(dims, nothing, observations, candidates)
end
function KDEMulti(dims::Vector, bws::Union{Vector, Nothing}, observations::Vector, candidates::Union{Dict{Int, Vector}, Nothing})
    mat_observations = hcat(observations...)
    KDEMulti(dims, bws, mat_observations, candidates)
end

# Main constructor
function KDEMulti(dims::Vector, bws::Union{Vector, Nothing}, mat_observations::Matrix, candidates::Union{Dict{Int, Vector}, Nothing})
    _KDEs, _observations, _unordered_to_index, _index_to_unordered = Vector(), Vector(), Dict{Int, Dict{Any, Real}}(),
                                                                            Dict{Int, Dict{Real, Any}}()
    mapped = Vector{Bool}()
    for (i, dim_type_i) in zip(1:size(mat_observations)[1], dims)
        _observations_i = mat_observations[i, :]
        if observation_need_map(dim_type_i, _observations_i) && ((candidates isa Nothing) || !haskey(candidates, i))
            error("No corresponding candidate at dimension. ")
        end
        if !(candidates isa Nothing) && haskey(candidates, i) && candidate_need_map(dim_type_i, candidates[i])
            _unordered_to_index_i, _index_to_unordered_i = map_dim(candidates[i])
            _unordered_to_index[i], _index_to_unordered[i] = _unordered_to_index_i, _index_to_unordered_i
            _observations_i = [_unordered_to_index_i[elem] for elem in _observations_i]
            push!(mapped, true)
        else
            push!(mapped, false)
        end
        push!(_observations, _observations_i)
    end
    if bws isa Nothing
        bws = default_bandwidth(_observations)
    end
    for (_observations_i, bandwidth_i, dim_type_i) in zip(_observations, bws, dims)
        # kde_i = KDEUniv(_observations_i, bandwidth_i, dim_type_i, type_kernel[typeof(dim_type_i)], is_number)
        kde_i = KDEUniv(dim_type_i, bandwidth_i, _observations_i)
        push!(_KDEs, kde_i)
    end
    unordered_to_index, index_to_unordered = Dict{KDEUniv, Dict{Any, Real}}(), Dict{KDEUniv, Dict{Real, Any}}()
    for i in 1:size(mat_observations)[1]
        if haskey(_index_to_unordered, i)
            unordered_to_index[_KDEs[i]] = _unordered_to_index[i]
            index_to_unordered[_KDEs[i]] = _index_to_unordered[i]
        end
    end
    KDEMulti(dims, _KDEs, _observations, mat_observations, mapped, unordered_to_index, index_to_unordered)
end

# GPKE and kernel code refers to Nonparametric part of ['statsmodels'](https://github.com/statsmodels/statsmodels)
#
# Copyright of statsmodels:
#
#     Copyright (C) 2006, Jonathan E. Taylor
#     All rights reserved.
#
#     Copyright (c) 2006-2008 Scipy Developers.
#     All rights reserved.
#
#     Copyright (c) 2009-2018 statsmodels Developers.
#     All rights reserved.

# pdf of KDEMulti, using (unnormalized) GPKE(Generalized Product Kernel Estimator)
function gpke(multi_kde::KDEMulti, x::Vector)
    Kval = Array{Real}(undef, (length(multi_kde.observations[1]), length(multi_kde.observations)))
    for (i, _kde, _x) in zip(1:length(x), multi_kde.KDEs, x)
        if multi_kde.mapped[i]
            _x = multi_kde.unordered_to_index[_kde][_x]
        end
        Kval[:, i] = pdf(_kde, _x)
    end
    iscontinuous = [_dim isa ContinuousDim ? true : false for _dim in multi_kde.dims]
    dens = prod(Kval, dims=2) / prod([kde.bandwidth for kde in multi_kde.KDEs][iscontinuous])
    sum(dens)
end

# Alias of gpke
function pdf(multi_kde::KDEMulti, x::Vector)
    gpke(multi_kde, x)
end

# Scott's normal reference rule of thumb bandwidth parameter
function default_bandwidth(observations::Vector)
    X = std.(observations)
    1.06 * X * length(observations).^(-1 / (4 + length(observations[1])))
end


text:
export OperatorTrait, TypedOperatorTrait, LeftTypedOperatorTrait, RightTypedOperatorTrait, InferableOperatorTrait, InvalidOperatorTrait
export AbstractOperator, TypedOperator, LeftTypedOperator, RightTypedOperator, InferableOperator
export as_operator, call_operator!, on_call!, operator_right
export OperatorsComposition, call_operator_composition!

export InvalidOperatorTraitUsageError, InconsistentSourceOperatorDataTypesError
export MissingOnCallImplementationError, MissingOperatorRightImplementationError

import Base: show, showerror
import Base: |>
import Base: +

"""
Abstract type for all possible operator traits

See also: [`TypedOperatorTrait`](@ref), [`LeftTypedOperatorTrait`](@ref), [`RightTypedOperatorTrait`](@ref), [`InferableOperatorTrait`](@ref), [`InvalidOperatorTrait`](@ref),
"""
abstract type OperatorTrait end

"""
Typed operator trait specifies operator to be statically typed with input and output data types.
Typed operator with input type `L` and output type `R` can only operate on input Observable with data type `L`
and will always produce an Observable with data type `R`.

# Examples

```jldoctest
using Rocket

struct MyTypedOperator <: TypedOperator{Int, Int} end

function Rocket.on_call!(::Type{Int}, ::Type{Int}, op::MyTypedOperator, source)
    return proxy(Int, source, MyTypedOperatorProxy())
end

struct MyTypedOperatorProxy <: ActorProxy end

Rocket.actor_proxy!(::Type{Int}, ::MyTypedOperatorProxy, actor::A) where A = MyTypedOperatorProxiedActor{A}(actor)

struct MyTypedOperatorProxiedActor{A} <: Actor{Int}
    actor :: A
end

function Rocket.on_next!(actor::MyTypedOperatorProxiedActor, data::Int)
    # Do something with a data and/or redirect it to actor.actor
    next!(actor.actor, data + 1)
end

Rocket.on_error!(actor::MyTypedOperatorProxiedActor, err) = error!(actor.actor, err)
Rocket.on_complete!(actor::MyTypedOperatorProxiedActor)   = complete!(actor.actor)

source = from([ 0, 1, 2 ])
subscribe!(source |> MyTypedOperator(), logger())
;

# output

[LogActor] Data: 1
[LogActor] Data: 2
[LogActor] Data: 3
[LogActor] Completed
```

See also: [`OperatorTrait`](@ref), [`TypedOperator`](@ref), [`OperatorTrait`](@ref), [`ProxyObservable`](@ref), [`ActorProxy`](@ref), [`logger`](@ref)
"""
struct TypedOperatorTrait{L, R} <: OperatorTrait end

"""
Left typed operator trait specifies operator to be statically typed with input data type.
To infer output data type this object should specify a special function `operator_right(operator, ::Type{L}) where L` which will be
used to infer output data type. Left typed operator with input type `L` can only operate on input Observable with data type `L` and
will always produce an Observable with data type inferred from `operator_right(operator, ::Type{L})`.

# Examples

```jldoctest
using Rocket

struct CountIntegersOperator <: LeftTypedOperator{Int} end

function Rocket.on_call!(::Type{Int}, ::Type{Tuple{Int, Int}}, op::CountIntegersOperator, source)
    return proxy(Tuple{Int, Int}, source, CountIntegersOperatorProxy())
end

Rocket.operator_right(::CountIntegersOperator, ::Type{Int}) = Tuple{Int, Int}

struct CountIntegersOperatorProxy <: ActorProxy end

Rocket.actor_proxy!(::Type{Tuple{Int, Int}}, ::CountIntegersOperatorProxy, actor::A) where A = CountIntegersProxiedActor{A}(0, actor)

mutable struct CountIntegersProxiedActor{A} <: Actor{Int}
    current :: Int
    actor   :: A
end

function Rocket.on_next!(actor::CountIntegersProxiedActor, data::Int)
    current = actor.current
    actor.current += 1
    next!(actor.actor, (current, data)) # e.g.
end

Rocket.on_error!(actor::CountIntegersProxiedActor, err) = error!(actor.actor, err)
Rocket.on_complete!(actor::CountIntegersProxiedActor)   = complete!(actor.actor)

source = from([ 0, 0, 0 ])
subscribe!(source |> CountIntegersOperator(), logger())
;

# output

[LogActor] Data: (0, 0)
[LogActor] Data: (1, 0)
[LogActor] Data: (2, 0)
[LogActor] Completed
```

See also: [`OperatorTrait`](@ref), [`LeftTypedOperator`](@ref), [`operator_right`](@ref), [`OperatorTrait`](@ref), [`ProxyObservable`](@ref), [`ActorProxy`](@ref), [`enumerate`](@ref), [`logger`](@ref)
"""
struct LeftTypedOperatorTrait{L} <: OperatorTrait end

"""
Right typed operator trait specifies operator to be statically typed with output data type. It can operate on input Observable with any data type `L`
but will always produce an Observable with data type `R`.

# Examples

```jldoctest
using Rocket

struct ConvertToFloatOperator <: RightTypedOperator{Float64} end

function Rocket.on_call!(::Type{L}, ::Type{Float64}, op::ConvertToFloatOperator, source) where L
    return proxy(Float64, source, ConvertToFloatProxy{L}())
end

struct ConvertToFloatProxy{L} <: ActorProxy end

function Rocket.actor_proxy!(::Type{Float64}, proxy::ConvertToFloatProxy{L}, actor::A) where { L, A }
    return ConvertToFloatProxyActor{L, A}(actor)
end

struct ConvertToFloatProxyActor{L, A} <: Actor{L}
    actor :: A
end

function Rocket.on_next!(actor::ConvertToFloatProxyActor{L}, data::L) where L
    next!(actor.actor, convert(Float64, data)) # e.g.
end

Rocket.on_error!(actor::ConvertToFloatProxyActor, err) = error!(actor.actor, err)
Rocket.on_complete!(actor::ConvertToFloatProxyActor)   = complete!(actor.actor)

source = from([ 1, 2, 3 ])
subscribe!(source |> ConvertToFloatOperator(), logger())
;

# output

[LogActor] Data: 1.0
[LogActor] Data: 2.0
[LogActor] Data: 3.0
[LogActor] Completed
```

See also: [`OperatorTrait`](@ref), [`RightTypedOperator`](@ref), [`OperatorTrait`](@ref), [`ProxyObservable`](@ref), [`ActorProxy`](@ref), [`logger`](@ref)
"""
struct RightTypedOperatorTrait{R} <: OperatorTrait end

"""
Inferable operator trait specifies operator to be statically typed neither with input data type nor with output data type.
To infer output data type this object should specify a special function `operator_right(operator, ::Type{L}) where L` where `L` is input data type
which will be used to infer output data type.

```jldoctest
using Rocket

struct IdentityOperator <: InferableOperator end

function Rocket.on_call!(::Type{L}, ::Type{L}, op::IdentityOperator, source) where L
    return proxy(L, source, IdentityProxy())
end

struct IdentityProxy <: ActorProxy end

Rocket.operator_right(::IdentityOperator, ::Type{L}) where L = L

Rocket.actor_proxy!(::Type{L}, proxy::IdentityProxy, actor::A) where L where A = IdentityProxyActor{L, A}(actor)

struct IdentityProxyActor{L, A} <: Actor{L}
    actor :: A
end

function Rocket.on_next!(actor::IdentityProxyActor{L}, data::L) where L
    next!(actor.actor, data) # e.g.
end

Rocket.on_error!(actor::IdentityProxyActor, err) = error!(actor.actor, err)
Rocket.on_complete!(actor::IdentityProxyActor)   = complete!(actor.actor)

source = from([ 1, 2, 3 ])
subscribe!(source |> IdentityOperator(), logger())

source = from([ 1.0, 2.0, 3.0 ])
subscribe!(source |> IdentityOperator(), logger())
;

# output

[LogActor] Data: 1
[LogActor] Data: 2
[LogActor] Data: 3
[LogActor] Completed
[LogActor] Data: 1.0
[LogActor] Data: 2.0
[LogActor] Data: 3.0
[LogActor] Completed

```

See also: [`OperatorTrait`](@ref), [`InferableOperator`](@ref), [`operator_right`](@ref), [`OperatorTrait`](@ref), [`ProxyObservable`](@ref), [`ActorProxy`](@ref), [`logger`](@ref)
"""
struct InferableOperatorTrait <: OperatorTrait end

"""
InvalidOperatorTrait trait specifies special 'invalid' behavior and types with such a trait specification cannot be used as an operator for an observable stream.
By default any type has InvalidOperatorTrait trait specification

See also: [`OperatorTrait`](@ref)
"""
struct InvalidOperatorTrait <: OperatorTrait end

"""
Supertype for all operators

See also: [`TypedOperator`](@ref), [`LeftTypedOperator`](@ref), [`RightTypedOperator`](@ref), [`InferableOperator`](@ref)
"""
abstract type AbstractOperator end

"""
Can be used as a supertype for any operator. Automatically specifies TypedOperatorTrait behavior.

# Examples
```jldoctest
using Rocket

struct MyOperator <: TypedOperator{Float64,String} end

as_operator(MyOperator)

# output
TypedOperatorTrait{Float64,String}()
```

See also: [`AbstractOperator`](@ref), [`TypedOperatorTrait`](@ref)
"""
abstract type TypedOperator{L, R} <: AbstractOperator end

"""
Can be used as a supertype for any operator. Automatically specifies LeftTypedOperatorTrait behavior.

# Examples
```jldoctest
using Rocket

struct MyOperator <: LeftTypedOperator{Float64} end

as_operator(MyOperator)

# output
LeftTypedOperatorTrait{Float64}()
```

See also: [`AbstractOperator`](@ref), [`LeftTypedOperatorTrait`](@ref), [`operator_right`](@ref)
"""
abstract type LeftTypedOperator{L}  <: AbstractOperator end

"""
Can be used as a supertype for any operator. Automatically specifies RightTypedOperatorTrait behavior.

# Examples
```jldoctest
using Rocket

struct MyOperator <: RightTypedOperator{Float64} end

as_operator(MyOperator)

# output
RightTypedOperatorTrait{Float64}()
```

See also: [`AbstractOperator`](@ref), [`RightTypedOperatorTrait`](@ref)
"""
abstract type RightTypedOperator{R} <: AbstractOperator end

"""
Can be used as a supertype for any operator. Automatically specifies InferableOperatorTrait behavior.

# Examples
```jldoctest
using Rocket

struct MyOperator <: InferableOperator end

as_operator(MyOperator)

# output
InferableOperatorTrait()
```

See also: [`AbstractOperator`](@ref), [`InferableOperatorTrait`](@ref), [`operator_right`](@ref)
"""
abstract type InferableOperator <: AbstractOperator end

"""
    as_operator(any)

This function checks operator trait behavior. May be used explicitly to specify operator trait behavior for any object.

See also: [`OperatorTrait`](@ref), [`AbstractOperator`](@ref)
"""
as_operator(::Type)                                            = InvalidOperatorTrait()
as_operator(::Type{ <: TypedOperator{L, R} })   where { L, R } = TypedOperatorTrait{L, R}()
as_operator(::Type{ <: LeftTypedOperator{L} })  where L        = LeftTypedOperatorTrait{L}()
as_operator(::Type{ <: RightTypedOperator{R} }) where R        = RightTypedOperatorTrait{R}()
as_operator(::Type{ <: InferableOperator })                    = InferableOperatorTrait()
as_operator(::O)                                where O        = as_operator(O)

call_operator!(operator::O, source::S) where { O, S } = check_call_operator!(as_operator(O), as_subscribable(S), operator, source)

call_operator!(operator::TypedOperator{L, R},        source::Subscribable{L}) where { L, R } = on_call!(L, R, operator, source)
call_operator!(operator::LeftTypedOperator{L},       source::Subscribable{L}) where { L    } = on_call!(L, operator_right(operator, L), operator, source)
call_operator!(operator::RightTypedOperatorTrait{R}, source::Subscribable{L}) where { L, R } = on_call!(L, R, operator, source)
call_operator!(operator::InferableOperator,          source::Subscribable{L}) where { L    } = on_call!(L, operator_right(operator, L), operator, source)

call_operator!(operator::TypedOperator{L, R},        source::ScheduledSubscribable{L}) where { L, R } = on_call!(L, R, operator, source)
call_operator!(operator::LeftTypedOperator{L},       source::ScheduledSubscribable{L}) where { L    } = on_call!(L, operator_right(operator, L), operator, source)
call_operator!(operator::RightTypedOperatorTrait{R}, source::ScheduledSubscribable{L}) where { L, R } = on_call!(L, R, operator, source)
call_operator!(operator::InferableOperator,          source::ScheduledSubscribable{L}) where { L    } = on_call!(L, operator_right(operator, L), operator, source)

check_call_operator!(::InvalidOperatorTrait, _,                          operator, source) = throw(InvalidOperatorTraitUsageError(operator))
check_call_operator!(::InvalidOperatorTrait, ::InvalidSubscribableTrait, operator, source) = throw(InvalidOperatorTraitUsageError(operator))
check_call_operator!(_,                      ::InvalidSubscribableTrait, operator, source) = throw(InvalidSubscribableTraitUsageError(source))

check_call_operator!(::TypedOperatorTrait{L},      ::SimpleSubscribableTrait{NotL}, operator, source) where { L, NotL } = throw(InconsistentSourceOperatorDataTypesError{L, NotL}(operator))
check_call_operator!(::LeftTypedOperatorTrait{L},  ::SimpleSubscribableTrait{NotL}, operator, source) where { L, NotL } = throw(InconsistentSourceOperatorDataTypesError{L, NotL}(operator))
check_call_operator!(::TypedOperatorTrait{L, R},   ::SimpleSubscribableTrait{L}, operator, source)    where { L, R }    = on_call!(L, R, operator, source)
check_call_operator!(::LeftTypedOperatorTrait{L},  ::SimpleSubscribableTrait{L}, operator, source)    where L           = on_call!(L, operator_right(operator, L), operator, source)
check_call_operator!(::RightTypedOperatorTrait{R}, ::SimpleSubscribableTrait{L}, operator, source)    where { L, R }    = on_call!(L, R, operator, source)
check_call_operator!(::InferableOperatorTrait,     ::SimpleSubscribableTrait{L},  operator, source)   where L           = on_call!(L, operator_right(operator, L), operator, source)

check_call_operator!(::TypedOperatorTrait{L},      ::ScheduledSubscribableTrait{NotL}, operator, source) where { L, NotL } = throw(InconsistentSourceOperatorDataTypesError{L, NotL}(operator))
check_call_operator!(::LeftTypedOperatorTrait{L},  ::ScheduledSubscribableTrait{NotL}, operator, source) where { L, NotL } = throw(InconsistentSourceOperatorDataTypesError{L, NotL}(operator))
check_call_operator!(::TypedOperatorTrait{L, R},   ::ScheduledSubscribableTrait{L}, operator, source)    where { L, R }    = on_call!(L, R, operator, source)
check_call_operator!(::LeftTypedOperatorTrait{L},  ::ScheduledSubscribableTrait{L}, operator, source)    where L           = on_call!(L, operator_right(operator, L), operator, source)
check_call_operator!(::RightTypedOperatorTrait{R}, ::ScheduledSubscribableTrait{L}, operator, source)    where { L, R }    = on_call!(L, R, operator, source)
check_call_operator!(::InferableOperatorTrait,     ::ScheduledSubscribableTrait{L},  operator, source)   where L           = on_call!(L, operator_right(operator, L), operator, source)

Base.:|>(source, operator::O) where { O <: AbstractOperator } = call_operator!(operator, source)

"""
    on_call!(::Type, ::Type, operator, source)

Each operator must implement its own method for `on_call!` function. This function is used to invoke operator on some Observable
and to produce another Observable with new logic (operator specific).

See also: [`AbstractOperator`](@ref)
"""
on_call!(::Type, ::Type, operator, source) = throw(MissingOnCallImplementationError(operator))

"""
    operator_right(operator, L)

Both LeftTypedOperator and InferableOperator must implement its own method for `operator_right` function. This function is used to infer
type of data of output Observable given the type of data of input Observable.

See also: [`AbstractOperator`](@ref), [`LeftTypedOperator`](@ref), [`InferableOperator`](@ref)
"""
operator_right(::TypedOperator{L, R},   ::Type{L}) where { L, R } = R
operator_right(::RightTypedOperator{R}, ::Type{L}) where { L, R } = R
operator_right(operator, _) = throw(MissingOperatorRightImplementationError(operator))

# -------------------------------- #
# Operators composition            #
# -------------------------------- #

"""
    OperatorsComposition(operators)

OperatorsComposition is an object which helps to create a composition of multiple operators. To create a composition of two or more operators
overloaded `+` or `|>` can be used.

```jldoctest
using Rocket

composition = map(Int, (d) -> d ^ 2) + filter(d -> d % 2 == 0)

source = from(1:5) |> composition

subscribe!(source, logger())
;

# output

[LogActor] Data: 4
[LogActor] Data: 16
[LogActor] Completed
```

```jldoctest
using Rocket

composition = map(Int, (d) -> d ^ 2) |> filter(d -> d % 2 == 0)

source = from(1:5) |> composition

subscribe!(source, logger())
;

# output

[LogActor] Data: 4
[LogActor] Data: 16
[LogActor] Completed
```
"""
struct OperatorsComposition{O}
    operators :: O
end

call_operator_composition!(composition::OperatorsComposition, source) = reduce(|>, composition.operators, init = source)

Base.:|>(source, composition::OperatorsComposition) = call_operator_composition!(composition, source)

# Backward compatibility
Base.:+(o1::AbstractOperator, o2::AbstractOperator)         = OperatorsComposition((o1, o2))
Base.:+(o1::AbstractOperator, c::OperatorsComposition)      = OperatorsComposition((o1, c.operators...))
Base.:+(c::OperatorsComposition, o2::AbstractOperator)      = OperatorsComposition((c.operators..., o2))
Base.:+(c1::OperatorsComposition, c2::OperatorsComposition) = OperatorsComposition((c1.operators..., c2.operators...))

Base.:|>(o1::AbstractOperator, o2::AbstractOperator)         = OperatorsComposition((o1, o2))
Base.:|>(o1::AbstractOperator, c::OperatorsComposition)      = OperatorsComposition((o1, c.operators...))
Base.:|>(c::OperatorsComposition, o2::AbstractOperator)      = OperatorsComposition((c.operators..., o2))
Base.:|>(c1::OperatorsComposition, c2::OperatorsComposition) = OperatorsComposition((c1.operators..., c2.operators...))

# -------------------------------- #
# Errors                           #
# -------------------------------- #

"""
This error will be thrown if `|>` pipe operator is called with invalid operator object

See also: [`on_call!`](@ref)
"""
struct InvalidOperatorTraitUsageError
    operator
end

function Base.showerror(io::IO, err::InvalidOperatorTraitUsageError)
    print(io, "Type $(typeof(err.operator)) is not a valid operator type. \nConsider extending your type with one of the base Operator abstract types: TypedOperator, LeftTypedOperator, RightTypedOperator, InferableOperator or implement Rocket.as_operator(::Type{<:$(typeof(err.operator))}).")
end

"""
This error will be thrown if `|>` pipe operator is called with inconsistent data type

See also: [`on_call!`](@ref)
"""
struct InconsistentSourceOperatorDataTypesError{L, NotL}
    operator
end

function Base.showerror(io::IO, err::InconsistentSourceOperatorDataTypesError{L, NotL}) where L where NotL
    print(io, "Operator of type $(typeof(err.operator)) expects source data to be of type $(L), but $(NotL) found.")
end

"""
This error will be thrown if Julia cannot find specific method of `on_call!` function for a given operator.

See also: [`on_call!`](@ref)
"""
struct MissingOnCallImplementationError
    operator
end

function Base.showerror(io::IO, err::MissingOnCallImplementationError)
    print(io, "You probably forgot to implement on_call!(::Type, ::Type, operator::$(typeof(err.operator)), source).")
end

"""
This error will be thrown if Julia cannot find specific method of `operator_right` function for a given operator.

See also: [`operator_right`](@ref)
"""
struct MissingOperatorRightImplementationError
    operator
end

function Base.showerror(io::IO, err::MissingOperatorRightImplementationError)
    print(io, "You probably forgot to implement operator_right(operator::$(typeof(err.operator)), L).")
end


text:
############################################################
# joAbstractFosterLinearOperatorInplace ####################
############################################################

# includes
include("joAbstractFosterLinearOperator/constructors.jl")
include("joAbstractFosterLinearOperator/base_functions.jl")
include("joAbstractFosterLinearOperator/extra_functions.jl")


text:
module ChannelAttribution

using DataFrames

export lastClick

include("heuristic.jl")

end


text:
function Base.:/{N,ES}(lhs::Valid{N,ES}, rhs::Valid{N,ES})

  (isempty(lhs)    || isempty(rhs))    && (return Valid{N,ES}(∅))
  (isallreals(lhs) || isallreals(rhs)) && (return Valid{N,ES}(ℝp))

  if roundsinf(lhs)
    lhs_infdiv(lhs, rhs)
  elseif roundsinf(rhs)
    rhs_infdiv(lhs, rhs)
  elseif containszero(lhs)
    lhs_zerodiv(lhs, rhs)
  elseif containszero(rhs)
    rhs_zerodiv(lhs, rhs)
  else
    stddiv(lhs, rhs)
  end
end

function lhs_infdiv{N,ES}(lhs::Valid{N,ES}, rhs::Valid{N,ES})
    if roundsinf(rhs)
        return Valid{N,ES}(ℝp)
    elseif containszero(lhs)  #lhs contains zero AND infinity.  Rhs cannot contain infinity.
        containszero(rhs) && return Valid{N,ES}(ℝp) #then we have 0/0 which is all reals.
        #canonical examples:

        #(20 ,   10) / (4,   5) -> (4, 2.5)
        #(20 ,   10) / (-5, -4) -> (-2.5, -4)
        #(-10 , -20) / (4,   5) -> (-2.5, -4)
        #(-10 , -20) / (-5, -4) -> (4, 2.5)

        _state = rounds_positive(lhs) * 1 + nonpositive(rhs) * 2

        if _state == __LHS_POS_RHS_POS
            res = ((@d_lower lhs) / (@d_upper rhs)) → ((@d_upper lhs) / (@d_lower rhs))
        elseif (_state == __LHS_NEG_RHS_POS)
            res = ((@d_lower lhs) / (@d_lower rhs)) → ((@d_upper lhs) / (@d_upper rhs))
        elseif (_state == __LHS_POS_RHS_NEG)
            res = ((@d_upper lhs) / (@d_upper rhs)) → ((@d_lower lhs) / (@d_lower rhs))
        else   #state == 3
            res = ((@d_upper lhs) / (@d_lower rhs)) → ((@d_lower lhs) / (@d_upper rhs))
        end

        (@s prev(res.lower)) <= (@s res.upper) && (return Valid{N,ES}(ℝp))
        return res

    elseif containszero(rhs)
        #lhs rounds infinity and rhs contains zero.
        #canonical examples:

        #(20, -10) / (-1, 4) -> (-5, 2.5)

        lower1 = (@d_upper lhs) / (@d_lower rhs)
        lower2 = (@d_lower lhs) / (@d_upper rhs)

        upper1 = (@d_lower lhs) / (@d_lower rhs)
        upper2 = (@d_upper lhs) / (@d_upper rhs)

        min_not_inf(lower1, lower2) → max_not_inf(upper1, upper2)
    else
        #the last case is if lhs rounds infinity but rhs is a "well-behaved" value.
        #canonical example:
        # (10, -20) / (2, 5) -> (2, -4)
        # (10, -20) / (-5, -2) -> (4, -2)

        if (rhs.lower > zero(Vnum{N,ES}))
            ((@d_lower lhs) / (@d_upper rhs)) → ((@d_upper lhs) / (@d_upper rhs))
        else
            ((@d_upper lhs) / (@d_lower rhs)) → ((@d_lower lhs) / (@d_lower rhs))
        end
    end
end

function rhs_infdiv{N,ES}(lhs::Valid{N,ES}, rhs::Valid{N,ES})

    if containszero(rhs)  #rhs contains zero AND infinity.
        #pass (for now)
        containszero(lhs) && return Valid{N,ES}(ℝp)

        #now address the situations where we are dividing by  round-both-horns.

        #(10,   20) / (5,   1) -> (4, 10)
        #(-20, -10) / (5,   1) -> (-10, -4)
        #(10,   20) / (-1, -5) -> (-10, -4)
        #(-20, -10) / (-1, -5) -> (4, 10)

        _state = nonnegative(lhs) * 1 + rounds_negative(rhs) * 2

        if _state == __LHS_POS_RHS_POS
            res = ((@d_upper lhs) / (@d_upper rhs)) → ((@d_lower lhs) / (@d_lower rhs))
        elseif (_state == __LHS_NEG_RHS_POS)
            res = ((@d_upper lhs) / (@d_lower rhs)) → ((@d_lower lhs) / (@d_upper rhs))
        elseif (_state == __LHS_POS_RHS_NEG)
            res = ((@d_lower lhs) / (@d_upper rhs)) → ((@d_upper lhs) / (@d_lower rhs))
        else
            res = ((@d_lower lhs) / (@d_lower rhs)) → ((@d_upper lhs) / (@d_upper rhs))
        end

        (@s prev(res.lower)) <= (@s res.upper) && (return Valid{N,ES}(ℝp))
        return res

    elseif containszero(lhs)
        #pass (for now)
        # (-10, 20) / (2, -5) -> (-4, 10)

        lower1 = (@d_upper lhs) / (@d_upper rhs)
        lower2 = (@d_lower lhs) / (@d_lower rhs)

        upper1 = (@d_upper lhs) / (@d_lower rhs)
        upper2 = (@d_lower lhs) / (@d_upper rhs)

        min_not_inf(lower1, lower2) → max_not_inf(upper1, upper2)
    else
        #the last case is if rhs rounds infinity but lhs is a "well-behaved" value.
        #canonical example:
        # (10, 20) / (2, -5) -> (-4, 10)
        # (-20, -10) / (2, -5) -> (-10, 4)
        if (lhs.lower > zero(Vnum{N,ES}))
            ((@d_upper lhs) / (@d_upper rhs)) → ((@d_upper lhs) / (@d_lower rhs))
        else
            ((@d_lower lhs) / (@d_lower rhs)) → ((@d_lower lhs) / (@d_upper rhs))
        end
    end
end

function lhs_zerodiv{N,ES}(lhs::Valid{N,ES}, rhs::Valid{N,ES})
    #lhs and rhs guaranteed to not cross infinity.  lhs guaranteed to contain zero.
    containszero(rhs) && return Valid{N,ES}(ℝp)

    #example: (-10, 20) / (-5, -2) -> (-10, 4)

    if nonpositive(rhs)
        #println(:a)
        ((@d_upper lhs) / (@d_upper rhs)) → ((@d_lower lhs) / (@d_upper rhs))
    else
        #println(:b)
        ((@d_lower lhs) / (@d_lower rhs)) → ((@d_upper lhs) / (@d_lower rhs))
    end
end

function rhs_zerodiv{N,ES}(lhs::Valid{N,ES}, rhs::Valid{N,ES})
    #lhs and rhs guaranteed to not contain infinity, lhs guaranteed to not contain zero.

    #example: (10, 20) / (-2, 5) -> (-10, 4)

    if nonpositive(lhs)
        ((@d_upper lhs) / (@d_lower rhs)) → ((@d_upper lhs) / (@d_upper rhs))
    else
        ((@d_lower lhs) / (@d_upper rhs)) → ((@d_lower lhs) / (@d_lower rhs))
    end
end

function stddiv{N,ES}(lhs::Valid{N,ES}, rhs::Valid{N,ES})
  #both values are "reasonable."
  _state = nonpositive(lhs) * 1 + nonpositive(rhs) * 2

  if _state == __LHS_POS_RHS_POS
    ((@d_lower lhs) / (@d_upper rhs)) → ((@d_upper lhs) / (@d_lower rhs))
  elseif _state == __LHS_NEG_RHS_POS
    ((@d_lower lhs) / (@d_lower rhs)) → ((@d_upper lhs) / (@d_upper rhs))
  elseif _state == __LHS_POS_RHS_NEG
    ((@d_upper lhs) / (@d_upper rhs)) → ((@d_lower lhs) / (@d_lower rhs))
  else #__LHS_NEG_RHS_NEG
    ((@d_upper lhs) / (@d_lower rhs)) → ((@d_lower lhs) / (@d_upper rhs))
  end
end

#do multiplicative inverses.  We cannot just chain division as a multiplication
#with this, due to the dependency problem.

function Base.inv{N,ES}(x::Valid{N,ES})
    isallreals(x) && return x
    isempty(x) && return x

    if istile(x) && !(isulp(x.lower))
        (@exact x) |> inv |> tile
    else
        inv(@upper x) → inv(@lower x)
    end
end

Base.:/{N,ES}(x::Valid{N,ES}) = inv(x)

max_stars_repo_name: ityonemo/SigmoidNumbers

max_issues_repo_name: ityonemo/SigmoidNumbers

max_forks_repo_name: ityonemo/SigmoidNumbers


text:
module JukaiDepParser

include("iddict.jl")
include("CoNLL.jl")
include("token.jl")
include("state.jl")
include("beamsearch.jl")
include("parser.jl")

end


text:
#ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля, на котором могут находиться также внутренние прямоугольные перегородки (все перегородки изолированы друг от друга, прямоугольники могут вырождаться в отрезки)

#РЕЗУЛЬТАТ: Робот - в исходном положении и в углах поля стоят маркеры
function mark_angles(r)
    num_steps=[]
    while isborder(r,Sud)==false || isborder(r,West)
        push!(num_steps, moves!(r, West))
        push!(num_steps, moves!(r, Sud))
    end

    for side in (Nord,Ost,Sud,West)
        moves!(r,side)
        putmarker!(r)
    end

    for (i,n) in enumerate(reverse!(num_steps))
        side = isodd(i) ? Ost : Nord
        moves!(r,side,n)
    end

end

function moves!(r,side)
    num_steps=0
    while isborder(r,side)==false
        move!(r,side)
        num_steps+=1
    end
    return num_steps
end

moves!(r,side,num_steps) = for _ in 1:num_steps move!(r,side) end