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

# Tests that do not really go anywhere else

# Test info
@test contains(sprint(info, "test"), "INFO:")
@test contains(sprint(info, "test"), "INFO: test")
@test contains(sprint(info, "test ", 1, 2, 3), "INFO: test 123")
@test contains(sprint(io->info(io,"test", prefix="MYINFO: ")), "MYINFO: test")

# Test warn
@test contains(sprint(Base.warn_once, "test"), "WARNING: test")
@test isempty(sprint(Base.warn_once, "test"))

@test contains(sprint(warn), "WARNING:")
@test contains(sprint(warn, "test"), "WARNING: test")
@test contains(sprint(warn, "test ", 1, 2, 3), "WARNING: test 123")
@test contains(sprint(io->warn(io, "test", prefix="MYWARNING: ")), "MYWARNING: test")
@test contains(sprint(io->warn(io, "testonce", once=true)), "WARNING: testonce")
@test isempty(sprint(io->warn(io, "testonce", once=true)))
@test !isempty(sprint(io->warn(io, "testonce", once=true, key=hash("testonce",hash("testanother")))))
let bt = backtrace()
    ws = split(chomp(sprint(warn, "test", bt)), '\n')
    bs = split(chomp(sprint(Base.show_backtrace, bt)), '\n')
    @test contains(ws[1],"WARNING: test")
    for (l,b) in zip(ws[2:end],bs)
        @test contains(l, b)
    end
end

# PR #16213
module Logging
    function bar(io)
        info(io,"barinfo")
        warn(io,"barwarn")
        Base.display_error(io,"barerror",backtrace())
    end
    function pooh(io)
        info(io,"poohinfo")
        warn(io,"poohwarn")
        Base.display_error(io,"pooherror",backtrace())
    end
end
function foo(io)
    info(io,"fooinfo")
    warn(io,"foowarn")
    Base.display_error(io,"fooerror",backtrace())
end

@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging, :bar;  kind=:info)
@test all(contains.(sprint(Logging.bar), ["WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging;  kind=:info)
@test all(contains.(sprint(Logging.bar), ["WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull;  kind=:info)
@test all(contains.(sprint(Logging.bar), ["WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(kind=:info)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging, :bar;  kind=:warn)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging;  kind=:warn)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull;  kind=:warn)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "ERROR: \"fooerror\""]))

logging(kind=:warn)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging, :bar;  kind=:error)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn"]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging;  kind=:error)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn"]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn"]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull;  kind=:error)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn"]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn"]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn"]))

logging(kind=:error)
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging, :bar)
@test sprint(Logging.bar) == ""
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull, Logging)
@test sprint(Logging.bar) == ""
@test sprint(Logging.pooh) == ""
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

logging(DevNull)
@test sprint(Logging.bar) == ""
@test sprint(Logging.pooh) == ""
@test sprint(foo) == ""

logging()
@test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn", "ERROR: \"barerror\""]))
@test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""]))
@test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""]))

# test assert() method
@test_throws AssertionError assert(false)
let res = assert(true)
    @test res === nothing
end
let
    try
        assert(false)
        error("unexpected")
    catch ex
        @test isa(ex, AssertionError)
        @test isempty(ex.msg)
    end
end

# test @assert macro
@test_throws AssertionError (@assert 1 == 2)
@test_throws AssertionError (@assert false)
@test_throws AssertionError (@assert false "this is a test")
@test_throws AssertionError (@assert false "this is a test" "another test")
@test_throws AssertionError (@assert false :a)
let
    try
        @assert 1 == 2
        error("unexpected")
    catch ex
        @test isa(ex, AssertionError)
        @test contains(ex.msg, "1 == 2")
    end
end
# test @assert message
let
    try
        @assert 1 == 2 "this is a test"
        error("unexpected")
    catch ex
        @test isa(ex, AssertionError)
        @test ex.msg == "this is a test"
    end
end
# @assert only uses the first message string
let
    try
        @assert 1 == 2 "this is a test" "this is another test"
        error("unexpected")
    catch ex
        @test isa(ex, AssertionError)
        @test ex.msg == "this is a test"
    end
end
# @assert calls string() on second argument
let
    try
        @assert 1 == 2 :random_object
        error("unexpected")
    catch ex
        @test isa(ex, AssertionError)
        @test !contains(ex.msg,  "1 == 2")
        @test contains(ex.msg, "random_object")
    end
end
# if the second argument is an expression, c
let deepthought(x, y) = 42
    try
        @assert 1 == 2 string("the answer to the ultimate question: ",
                              deepthought(6, 9))
        error("unexpected")
    catch ex
        @test isa(ex, AssertionError)
        @test ex.msg == "the answer to the ultimate question: 42"
    end
end

let # test the process title functions, issue #9957
    oldtitle = Sys.get_process_title()
    Sys.set_process_title("julia0x1")
    @test Sys.get_process_title() == "julia0x1"
    Sys.set_process_title(oldtitle)
    @test Sys.get_process_title() == oldtitle
end

# test gc_enable/disable
@test gc_enable(true)
@test gc_enable(false)
@test gc_enable(false) == false
@test gc_enable(true) == false
@test gc_enable(true)

# test methodswith
# `methodswith` relies on exported symbols
export func4union, Base
struct NoMethodHasThisType end
@test isempty(methodswith(NoMethodHasThisType))
@test !isempty(methodswith(Int))
struct Type4Union end
func4union(::Union{Type4Union,Int}) = ()
@test !isempty(methodswith(Type4Union))

# PR #10984
# Disable on windows because of issue (missing flush) when redirecting STDERR.
let
    redir_err = "redirect_stderr(STDOUT)"
    exename = Base.julia_cmd()
    script = "$redir_err; module A; f() = 1; end; A.f() = 1"
    warning_str = read(`$exename --warn-overwrite=yes --startup-file=no -e $script`, String)
    @test contains(warning_str, "f()")
end

# lock / unlock
let l = ReentrantLock()
    lock(l)
    success = Ref(false)
    @test trylock(l) do
        @test lock(l) do
            success[] = true
            return :foo
        end === :foo
        return :bar
    end === :bar
    @test success[]
    t = @async begin
        @test trylock(l) do
            @test false
        end === false
    end
    wait(t)
    unlock(l)
    @test_throws ErrorException unlock(l)
end

# task switching

@noinline function f6597(c)
    t = @schedule nothing
    finalizer(t, t -> c[] += 1)
    wait(t)
    @test c[] == 0
    wait(t)
    nothing
end
let c = Ref(0),
    t2 = @schedule (wait(); c[] += 99)
    @test c[] == 0
    f6597(c)
    gc() # this should run the finalizer for t
    @test c[] == 1
    yield()
    @test c[] == 1
    yield(t2)
    @test c[] == 100
end

# timing macros

# test that they don't introduce global vars
global v11801, t11801, names_before_timing
names_before_timing = names(@__MODULE__, true)

let t = @elapsed 1+1
    @test isa(t, Real) && t >= 0
end

let
    val, t = @timed sin(1)
    @test val == sin(1)
    @test isa(t, Real) && t >= 0
end

# problem after #11801 - at global scope
t11801 = @elapsed 1+1
@test isa(t11801,Real) && t11801 >= 0
v11801, t11801 = @timed sin(1)
@test v11801 == sin(1)
@test isa(t11801,Real) && t11801 >= 0

@test names(@__MODULE__, true) == names_before_timing

# interactive utilities

import Base.summarysize
@test summarysize(Core) > (summarysize(Core.Inference) + Base.summarysize(Core.Intrinsics)) > Core.sizeof(Core)
@test summarysize(Base) > 100_000 * sizeof(Ptr)

let R = Ref{Any}(nothing), depth = 10^6
    for i = 1:depth
        R = Ref{Any}(R)
    end
    R = Core.svec(R, R)
    @test summarysize(R) == (depth + 4) * sizeof(Ptr)
end

module _test_whos_
export x
x = 1.0
end
@test sprint(whos, Main, r"^$") == ""
let v = sprint(whos, _test_whos_)
    @test contains(v, "x      8 bytes  Float64")
end

# issue #13021
let ex = try
    Main.x13021 = 0
    nothing
catch ex
    ex
end
    @test isa(ex, ErrorException) && ex.msg == "cannot assign variables in other modules"
end

# Issue 14173
module Tmp14173
    export A
    A = randn(2000, 2000)
end
whos(IOBuffer(), Tmp14173) # warm up
const MEMDEBUG = ccall(:jl_is_memdebug, Bool, ())
@test @allocated(whos(IOBuffer(), Tmp14173)) < (MEMDEBUG ? 30000 : 10000)

## test conversion from UTF-8 to UTF-16 (for Windows APIs)

# empty arrays
@test transcode(UInt16, UInt8[]) == UInt16[]
@test transcode(UInt8, UInt16[]) == UInt8[]

# UTF-8-like sequences
V8 = [
    # 1-byte (ASCII)
    ([0x00],[0x0000])
    ([0x0a],[0x000a])
    ([0x7f],[0x007f])
    # 2-byte
    ([0xc0,0x80],[0x0000]) # overlong encoding
    ([0xc1,0xbf],[0x007f]) # overlong encoding
    ([0xc2,0x80],[0x0080])
    ([0xc3,0xbf],[0x00ff])
    ([0xc4,0x80],[0x0100])
    ([0xc4,0xa3],[0x0123])
    ([0xdf,0xbf],[0x07ff])
    # 3-byte
    ([0xe0,0x80,0x80],[0x0000]) # overlong encoding
    ([0xe0,0x81,0xbf],[0x007f]) # overlong encoding
    ([0xe0,0x82,0x80],[0x0080]) # overlong encoding
    ([0xe0,0x9f,0xbf],[0x07ff]) # overlong encoding
    ([0xe0,0xa0,0x80],[0x0800])
    ([0xe0,0xa2,0x9a],[0x089a])
    ([0xe1,0x88,0xb4],[0x1234])
    ([0xea,0xaf,0x8d],[0xabcd])
    ([0xed,0x9f,0xbf],[0xd7ff])
    ([0xed,0xa0,0x80],[0xd800]) # invalid code point – high surrogate
    ([0xed,0xaf,0xbf],[0xdbff]) # invalid code point – high surrogate
    ([0xed,0xb0,0x80],[0xdc00]) # invalid code point – low surrogate
    ([0xed,0xbf,0xbf],[0xdfff]) # invalid code point – low surrogate
    ([0xee,0x80,0x80],[0xe000])
    ([0xef,0xbf,0xbf],[0xffff])
    # 4-byte
    ([0xf0,0x80,0x80,0x80],[0x0000]) # overlong encoding
    ([0xf0,0x80,0x81,0xbf],[0x007f]) # overlong encoding
    ([0xf0,0x80,0x82,0x80],[0x0080]) # overlong encoding
    ([0xf0,0x80,0x9f,0xbf],[0x07ff]) # overlong encoding
    ([0xf0,0x80,0xa0,0x80],[0x0800]) # overlong encoding
    ([0xf0,0x8f,0xbf,0xbf],[0xffff]) # overlong encoding
    ([0xf0,0x90,0x80,0x80],[0xd800,0xdc00]) # U+10000
    ([0xf0,0x90,0x8d,0x88],[0xd800,0xdf48]) # U+10348
    ([0xf0,0x90,0x90,0xb7],[0xd801,0xdc37]) # U+10437
    ([0xf0,0xa4,0xad,0xa2],[0xd852,0xdf62]) # U+24b62
    ([0xf2,0xab,0xb3,0x9e],[0xda6f,0xdcde]) # U+abcde
    ([0xf3,0xbf,0xbf,0xbf],[0xdbbf,0xdfff]) # U+fffff
    ([0xf4,0x80,0x80,0x80],[0xdbc0,0xdc00]) # U+100000
    ([0xf4,0x8a,0xaf,0x8d],[0xdbea,0xdfcd]) # U+10abcd
    ([0xf4,0x8f,0xbf,0xbf],[0xdbff,0xdfff]) # U+10ffff
]

# non UTF-8-like sequences
X8 = Vector{UInt8}[
    # invalid 1-byte sequences
    [0x80], # 1 leading ones
    [0xbf],
    [0xc0], # 2 leading ones
    [0xdf],
    [0xe0], # 3 leading ones
    [0xef],
    [0xf0], # 4 leading ones
    [0xf7],
    [0xf8], # 5 leading ones
    [0xfb],
    [0xfc], # 6 leading ones
    [0xfd],
    [0xfe], # 7 leading ones
    [0xff], # 8 leading ones
    # other invalid sequences
    [0xf4,0x90,0xbf,0xbf],
    [0xf4,0x91,0x80,0x80],
    [0xf7,0x80,0x80,0x80],
    [0xf7,0xbf,0xbf,0xbf],
    [0xf8,0x80,0x80,0x80],
    [0xf8,0xbf,0xbf,0xbf],
    [0xff,0x80,0x80,0x80],
    [0xff,0xbf,0xbf,0xbf],
]

for s in [map(first,V8); X8],
    i = 1:length(s)-1,
    j = i+1:length(s)-(i==1)
    ss = s[i:j]
    ss in X8 || push!(X8, ss)
end
sort!(X8, lt=lexless)
sort!(X8, by=length)

I8 = [(s,map(UInt16,s)) for s in X8]

for (X,Y,Z) in ((V8,V8,V8), (I8,V8,I8), (V8,I8,V8), (V8,V8,I8), (I8,V8,V8))
    for (a8, a16) in X
        @test transcode(UInt16, a8) == a16
        for (b8, b16) in Y
            ab8 = [a8; b8]
            ab16 = [a16; b16]
            @test transcode(UInt16, ab8) == ab16
            for (c8, c16) in Z
                abc8 = [ab8; c8]
                abc16 = [ab16; c16]
                @test transcode(UInt16, abc8) == abc16
            end
        end
    end
end

# UTF-16-like sequences
V16 = [
    # 1-unit UTF-16, 1-byte UTF-8 (ASCII)
    ([0x0000],[0x00])
    ([0x000a],[0x0a])
    ([0x007f],[0x7f])
    # 1-unit UTF-16, 2-byte UTF-8
    ([0x0080],[0xc2,0x80])
    ([0x00ff],[0xc3,0xbf])
    ([0x0100],[0xc4,0x80])
    ([0x0123],[0xc4,0xa3])
    ([0x07ff],[0xdf,0xbf])
    # 1-unit UTF-16, 3-byte UTF-8
    ([0x0800],[0xe0,0xa0,0x80])
    ([0x089a],[0xe0,0xa2,0x9a])
    ([0x1234],[0xe1,0x88,0xb4])
    ([0xabcd],[0xea,0xaf,0x8d])
    ([0xd7ff],[0xed,0x9f,0xbf])
    ([0xe000],[0xee,0x80,0x80])
    ([0xffff],[0xef,0xbf,0xbf])
    # 2-unit UTF-16, 4-byte UTF-8
    ([0xd800,0xdc00],[0xf0,0x90,0x80,0x80]) # U+10000
    ([0xd800,0xdf48],[0xf0,0x90,0x8d,0x88]) # U+10348
    ([0xd801,0xdc37],[0xf0,0x90,0x90,0xb7]) # U+10437
    ([0xd852,0xdf62],[0xf0,0xa4,0xad,0xa2]) # U+24b62
    ([0xda6f,0xdcde],[0xf2,0xab,0xb3,0x9e]) # U+abcde
    ([0xdbbf,0xdfff],[0xf3,0xbf,0xbf,0xbf]) # U+fffff
    ([0xdbc0,0xdc00],[0xf4,0x80,0x80,0x80]) # U+100000
    ([0xdbea,0xdfcd],[0xf4,0x8a,0xaf,0x8d]) # U+10abcd
    ([0xdbff,0xdfff],[0xf4,0x8f,0xbf,0xbf]) # U+10ffff
]

I16 = [
    ([0xd800],[0xed,0xa0,0x80]) # high surrogate
    ([0xdbff],[0xed,0xaf,0xbf]) # high surrogate
    ([0xdc00],[0xed,0xb0,0x80]) # low surrogate
    ([0xdfff],[0xed,0xbf,0xbf]) # low surrogate
]

for (X,Y,Z) in ((V16,V16,V16), (I16,V16,I16), (V16,I16,V16), (V16,V16,I16), (I16,V16,V16))
    for (a16, a8) in X
        @test transcode(UInt8, a16) == a8
        @test transcode(UInt16, a8) == a16
        for (b16, b8) in Y
            ab16 = [a16; b16]
            ab8 = [a8; b8]
            @test transcode(UInt8, ab16) == ab8
            @test transcode(UInt16, ab8) == ab16
            for (c16, c8) in Z
                abc16 = [ab16; c16]
                abc8 = [ab8; c8]
                @test transcode(UInt8, abc16) == abc8
                @test transcode(UInt16, abc8) == abc16
            end
        end
    end
end

let s = "abcα🐨\0x\0"
    for T in (UInt8, UInt16, UInt32, Int32)
        @test transcode(T, s) == transcode(T, Vector{UInt8}(s))
        @test transcode(String, transcode(T, s)) == s
    end
end

# clipboard functionality
if Sys.iswindows()
    for str in ("Hello, world.", "∀ x ∃ y", "")
        clipboard(str)
        @test clipboard() == str
    end
end

let optstring = stringmime(MIME("text/plain"), Base.JLOptions())
    @test startswith(optstring, "JLOptions(\n")
    @test !contains(optstring, "Ptr")
    @test endswith(optstring, "\n)")
    @test contains(optstring, " = \"")
end
let optstring = repr(Base.JLOptions())
    @test startswith(optstring, "JLOptions(")
    @test endswith(optstring, ")")
    @test !contains(optstring, "\n")
    @test !contains(optstring, "Ptr")
    @test contains(optstring, " = \"")
end

# Base.securezero! functions (#17579)
import Base: securezero!, unsafe_securezero!
let a = [1,2,3]
    @test securezero!(a) === a == [0,0,0]
    a[:] = 1:3
    @test unsafe_securezero!(pointer(a), length(a)) == pointer(a)
    @test a == [0,0,0]
    a[:] = 1:3
    @test unsafe_securezero!(Ptr{Void}(pointer(a)), sizeof(a)) == Ptr{Void}(pointer(a))
    @test a == [0,0,0]
end
let creds = Base.LibGit2.CachedCredentials()
    LibGit2.get_creds!(creds, "foo", LibGit2.SSHCredentials()).pass = "bar"
    securezero!(creds)
    @test LibGit2.get_creds!(creds, "foo", nothing).pass == "\0\0\0"
end

# Test that we can VirtualProtect jitted code to writable
if Sys.iswindows()
    @noinline function WeVirtualProtectThisToRWX(x, y)
        x+y
    end

    let addr = cfunction(WeVirtualProtectThisToRWX, UInt64, Tuple{UInt64, UInt64})
        addr = addr-(UInt64(addr)%4096)
        PAGE_EXECUTE_READWRITE = 0x40
        oldPerm = Ref{UInt32}()
        err18083 = ccall(:VirtualProtect,stdcall,Cint,
            (Ptr{Void}, Csize_t, UInt32, Ptr{UInt32}),
            addr, 4096, PAGE_EXECUTE_READWRITE, oldPerm)
        err18083 == 0 && error(Libc.GetLastError())
    end
end

function test_crc32c(crc32c)
    # CRC32c checksum (test data generated from @andrewcooke's CRC.jl package)
    for (n,crc) in [(0,0x00000000),(1,0xa016d052),(2,0x03f89f52),(3,0xf130f21e),(4,0x29308cf4),(5,0x53518fab),(6,0x4f4dfbab),(7,0xbd3a64dc),(8,0x46891f81),(9,0x5a14b9f9),(10,0xb219db69),(11,0xd232a91f),(12,0x51a15563),(13,0x9f92de41),(14,0x4d8ae017),(15,0xc8b74611),(16,0xa0de6714),(17,0x672c992a),(18,0xe8206eb6),(19,0xc52fd285),(20,0x327b0397),(21,0x318263dd),(22,0x08485ccd),(23,0xea44d29e),(24,0xf6c0cb13),(25,0x3969bba2),(26,0x6a8810ec),(27,0x75b3d0df),(28,0x82d535b1),(29,0xbdf7fc12),(30,0x1f836b7d),(31,0xd29f33af),(32,0x8e4acb3e),(33,0x1cbee2d1),(34,0xb25f7132),(35,0xb0fa484c),(36,0xb9d262b4),(37,0x3207fe27),(38,0xa024d7ac),(39,0x49a2e7c5),(40,0x0e2c157f),(41,0x25f7427f),(42,0x368c6adc),(43,0x75efd4a5),(44,0xa84c5c31),(45,0x0fc817b2),(46,0x8d99a881),(47,0x5cc3c078),(48,0x9983d5e2),(49,0x9267c2db),(50,0xc96d4745),(51,0x058d8df3),(52,0x453f9cf3),(53,0xb714ade1),(54,0x55d3c2bc),(55,0x495710d0),(56,0x3bddf494),(57,0x4f2577d0),(58,0xdae0f604),(59,0x3c57c632),(60,0xfe39bbb0),(61,0x6f5d1d41),(62,0x7d996665),(63,0x68c738dc),(64,0x8dfea7ae)]
        @test crc32c(UInt8[1:n;]) == crc == crc32c(String(UInt8[1:n;]))
    end

    # test that crc parameter is equivalent to checksum of concatenated data,
    # and test crc of subarrays:
    a = UInt8[1:255;]
    crc_256 = crc32c(a)
    @views for n = 1:255
        @test crc32c(a[n+1:end], crc32c(a[1:n])) == crc_256
    end
    @test crc32c(IOBuffer(a)) == crc_256
    let buf = IOBuffer()
        write(buf, a[1:3])
        @test crc32c(seekstart(buf)) == crc32c(a[1:3])
        @test crc32c(buf) == 0x00000000
        @test crc32c(seek(buf, 1)) == crc32c(a[2:3])
        @test crc32c(seek(buf, 0), 2) == crc32c(a[1:2])
        @test crc32c(buf) == crc32c(a[3:3])
    end

    let f = tempname()
        try
            write(f, a)
            @test open(crc32c, f) == crc_256
            open(f, "r") do io
                @test crc32c(io, 16) == crc32c(a[1:16])
                @test crc32c(io, 16) == crc32c(a[17:32])
                @test crc32c(io) == crc32c(a[33:end])
                @test crc32c(io, 1000) == 0x00000000
            end
            a = rand(UInt8, 30000)
            write(f, a)
            @test open(crc32c, f) == crc32c(a) == open(io -> crc32c(io, 10^6), f)
        finally
            rm(f, force=true)
        end
    end
end
unsafe_crc32c_sw(a, n, crc) =
    ccall(:jl_crc32c_sw, UInt32, (UInt32, Ptr{UInt8}, Csize_t), crc, a, n)
crc32c_sw(a::Union{Array{UInt8},Base.FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N},
          crc::UInt32=0x00000000) = unsafe_crc32c_sw(a, length(a), crc)
crc32c_sw(s::String, crc::UInt32=0x00000000) = unsafe_crc32c_sw(s, sizeof(s), crc)
function crc32c_sw(io::IO, nb::Integer, crc::UInt32=0x00000000)
    nb < 0 && throw(ArgumentError("number of bytes to checksum must be ≥ 0"))
    buf = Array{UInt8}(min(nb, 24576))
    while !eof(io) && nb > 24576
        n = readbytes!(io, buf)
        crc = unsafe_crc32c_sw(buf, n, crc)
        nb -= n
    end
    return unsafe_crc32c_sw(buf, readbytes!(io, buf, min(nb, length(buf))), crc)
end
crc32c_sw(io::IO, crc::UInt32=0x00000000) = crc32c_sw(io, typemax(Int64), crc)
test_crc32c(crc32c)
test_crc32c(crc32c_sw)

let
    old_have_color = Base.have_color
    try
        @eval Base have_color = true
        buf = IOBuffer()
        print_with_color(:red, buf, "foo")
        @test startswith(String(take!(buf)), Base.text_colors[:red])
    finally
        @eval Base have_color = $(old_have_color)
    end
end

# Test that `print_with_color` accepts non-string values, just as `print` does
let
    old_have_color = Base.have_color
    try
        @eval Base have_color = true
        buf_color = IOBuffer()
        args = (3.2, "foo", :testsym)
        print_with_color(:red, buf_color, args...)
        buf_plain = IOBuffer()
        print(buf_plain, args...)
        expected_str = string(Base.text_colors[:red],
                              String(take!(buf_plain)),
                              Base.text_colors[:default])
        @test expected_str == String(take!(buf_color))
    finally
        @eval Base have_color = $(old_have_color)
    end
end

let
    global c_18711 = 0
    buf = IOContext(IOBuffer(), :hascontext => true)
    Base.with_output_color(:red, buf) do buf
        global c_18711
        get(buf, :hascontext, false) && (c_18711 += 1)
    end
    @test c_18711 == 1
end

let
    old_have_color = Base.have_color
    try
        @eval Base have_color = true
        buf = IOBuffer()
        print_with_color(:red, buf, "foo")
        # Check that we get back to normal text color in the end
        @test String(take!(buf)) == "\e[31mfoo\e[39m"

        # Check that boldness is turned off
        print_with_color(:red, buf, "foo"; bold = true)
        @test String(take!(buf)) == "\e[1m\e[31mfoo\e[39m\e[22m"
    finally
        @eval Base have_color = $(old_have_color)
    end
end

abstract type DA_19281{T, N} <: AbstractArray{T, N} end
Base.convert(::Type{Array{S, N}}, ::DA_19281{T, N}) where {S,T,N} = error()
x_19281 = [(), (1,)]
mutable struct Foo_19281
    f::Vector{Tuple}
    Foo_19281() = new(x_19281)
end

@testset "test this does not segfault #19281" begin
    @test Foo_19281().f[1] == ()
    @test Foo_19281().f[2] == (1,)
end

let
    x_notdefined = Ref{String}()
    @test !isassigned(x_notdefined)

    x_defined = Ref{String}("Test")
    @test isassigned(x_defined)
end

mutable struct Demo_20254
    arr::Array{String}
end

# these cause stack overflows and are a little flaky on CI, ref #20256
if Bool(parse(Int,(get(ENV, "JULIA_TESTFULL", "0"))))
    function Demo_20254(arr::AbstractArray=Any[])
        Demo_20254(string.(arr))
    end

    _unsafe_get_19433(x::NTuple{1}) = (unsafe_get(x[1]),)
    _unsafe_get_19433(xs::Vararg) = (unsafe_get(xs[1]), _unsafe_get_19433(xs[2:end])...)

    f_19433(f_19433, xs...) = f_19433(_unsafe_get_19433(xs)...)

    @testset "test this does not crash, issue #19433 and #20254" begin
        @test_throws StackOverflowError Demo_20254()
        @test_throws StackOverflowError f_19433(+, 1, 2)
    end
end

# Test issue #19774 invokelatest fix.

# we define this in a module to allow rewriting
# rather than needing an extra eval.
module Issue19774
f(x) = 1
end

# First test the world issue condition.
let foo() = begin
        Issue19774.f(x::Int) = 2
        return Issue19774.f(0)
    end
    @test foo() == 1    # We should be using the original function.
end

# Now check that invokelatest fixes that issue.
let foo() = begin
        Issue19774.f(x::Int) = 3
        return Base.invokelatest(Issue19774.f, 0)
    end
    @test foo() == 3
end

# Check that the kwargs conditions also works
module Kwargs19774
f(x, y; z=0) = x * y + z
end

@test Kwargs19774.f(2, 3; z=1) == 7

let foo() = begin
        Kwargs19774.f(x::Int, y::Int; z=3) = z
        return Base.invokelatest(Kwargs19774.f, 2, 3; z=1)
    end
    @test foo() == 1
end

# Endian tests
# For now, we only support little endian.
# Add an `Sys.ARCH` test for big endian when/if we add support for that.
# Do **NOT** use `ENDIAN_BOM` to figure out the endianess
# since that's exactly what we want to test.
@test ENDIAN_BOM == 0x04030201
@test ntoh(0x1) == 0x1
@test hton(0x1) == 0x1
@test ltoh(0x1) == 0x1
@test htol(0x1) == 0x1
@test ntoh(0x102) == 0x201
@test hton(0x102) == 0x201
@test ltoh(0x102) == 0x102
@test htol(0x102) == 0x102
@test ntoh(0x1020304) == 0x4030201
@test hton(0x1020304) == 0x4030201
@test ltoh(0x1020304) == 0x1020304
@test htol(0x1020304) == 0x1020304
@test ntoh(0x102030405060708) == 0x807060504030201
@test hton(0x102030405060708) == 0x807060504030201
@test ltoh(0x102030405060708) == 0x102030405060708
@test htol(0x102030405060708) == 0x102030405060708

@testset "inline bug #18735" begin
    @noinline f(n) = n ? error() : Int
    g() = Union{f(true)}
    @test_throws ErrorException g()
end

include("testenv.jl")

let flags = Cmd(filter(a->!contains(a, "depwarn"), collect(test_exeflags)))
    local cmd = `$test_exename $flags deprecation_exec.jl`

    if !success(pipeline(cmd; stdout=STDOUT, stderr=STDERR))
        error("Deprecation test failed, cmd : $cmd")
    end
end

max_stars_repo_name: baggepinnen/julia

max_issues_repo_name: baggepinnen/julia

max_forks_repo_name: afniedermayer/julia


text:
#Given the changes in syntax in ParameterJuMP and the new format to create anonymous parameters
function add_jump_parameter(jump_model::JuMP.Model, val::Number)
    param = JuMP.@variable(jump_model, variable_type = PJ.Param())
    PJ.set_value(param, val)
    return param
end

function write_data(base_power::Float64, save_path::String)
    JSON.write(joinpath(save_path, "base_power.json"), JSON.json(base_power))
    return
end

function jump_value(input::JuMP.VariableRef)::Float64
    return JuMP.value(input)
end

function jump_value(input::T)::Float64 where {T <: JuMP.AbstractJuMPScalar}
    return JuMP.value(input)
end

function jump_value(input::PJ.ParameterRef)::Float64
    return PJ.value(input)
end

function jump_value(input::JuMP.ConstraintRef)::Float64
    return JuMP.dual(input)
end

function jump_value(input::Float64)::Float64
    return input
end

function jump_value(input::Vector{Tuple{Float64, Float64}})::Vector{Tuple{Float64, Float64}}
    return input
end

function to_matrix(array::DenseAxisArray{T, 1, K}) where {T, K <: NTuple{1, Any}}
    data = jump_value.(array.data)
    data = reshape(data, length(data), 1)
    return data
end

function to_matrix(array::DenseAxisArray{T, 1, K}) where {T <: Real, K <: NTuple{1, Any}}
    data = reshape(deepcopy(array.data), length(array.data), 1)
    return data
end

function to_matrix(array::DenseAxisArray{T, 2, K}) where {T, K <: NTuple{2, Any}}
    ax = axes(array)
    data = Matrix{Float64}(undef, length(ax[2]), length(ax[1]))
    for t in ax[2], (ix, name) in enumerate(ax[1])
        data[t, ix] = jump_value(array[name, t])
    end
    return data
end

function to_matrix(
    array::DenseAxisArray{T, 2, K},
) where {T <: Vector{Tuple{Float64, Float64}}, K <: NTuple{2, Any}}
    ax = axes(array)
    data = Matrix{Vector{Tuple{Float64, Float64}}}(undef, length(ax[2]), length(ax[1]))
    for t in ax[2], (ix, name) in enumerate(ax[1])
        data[t, ix] = jump_value(array[name, t])
    end
    return data
end

# to_matrix functions are used to convert JuMP.Containers to matrices that can be written into
# HDF5 Store.
function to_matrix(array::DenseAxisArray{T, 2, K}) where {T <: Real, K <: NTuple{2, Any}}
    return deepcopy(permutedims(array.data))
end

function to_matrix(::DenseAxisArray{T, N, K}) where {T, N, K <: NTuple{N, Any}}
    error(
        "Converting $(N)-dimensional DenseAxisArrays to matrix is currently not supported",
    )
end

function get_column_names(key::OptimizationContainerKey)
    return [encode_key_as_string(key)]
end

function get_column_names(
    key::OptimizationContainerKey,
    ::DenseAxisArray{T, 1, K},
) where {T, K <: NTuple{1, Any}}
    return get_column_names(key)
end

function get_column_names(
    ::OptimizationContainerKey,
    array::DenseAxisArray{T, 2, K},
) where {T, K <: NTuple{2, Any}}
    return string.(axes(array)[1])
end

function _get_column_names(arr::SparseAxisArray{T, N, K}) where {T, N, K <: NTuple{N, Any}}
    return sort!(collect(Set(encode_tuple_to_column(k[1:(N - 1)]) for k in keys(arr.data))))
end

function get_column_names(
    ::OptimizationContainerKey,
    array::SparseAxisArray{T, N, K},
) where {T, N, K <: NTuple{N, Any}}
    return get_column_names(array)
end

function get_column_names(array::SparseAxisArray{T, N, K}) where {T, N, K <: NTuple{N, Any}}
    return _get_column_names(array)
end

function encode_tuple_to_column(val::NTuple{N, <:AbstractString}) where {N}
    return join(val, PSI_NAME_DELIMITER)
end

function encode_tuple_to_column(val::Tuple{String, Int})
    return join(string.(val), PSI_NAME_DELIMITER)
end

function _to_matrix(
    array::SparseAxisArray{T, N, K},
    columns,
) where {T, N, K <: NTuple{N, Any}}
    timesteps = Set{Int}(k[N] for k in keys(array.data))
    data = Matrix{Float64}(undef, length(timesteps), length(columns))
    for (ix, col) in enumerate(columns), t in timesteps
        data[t, ix] = jump_value(array.data[(col..., t)])
    end
    return data
end

function to_matrix(array::SparseAxisArray{T, N, K}) where {T, N, K <: NTuple{N, Any}}
    # Don't use _get_column_names to avoid additional string conversion
    columns = sort!(unique!([k[1:(N - 1)] for k in keys(array.data)]))
    return _to_matrix(array, columns)
end

function to_dataframe(array::SparseAxisArray{T, N, K}) where {T, N, K <: NTuple{N, Any}}
    columns = _get_column_names(array)
    return DataFrames.DataFrame(_to_matrix(array, columns), columns)
end

to_matrix(array::Array) = array

"""
Returns the correct container specification for the selected type of JuMP Model
"""
function container_spec(::Type{T}, axs...) where {T <: Any}
    return DenseAxisArray{T}(undef, axs...)
end

"""
Returns the correct container specification for the selected type of JuMP Model
"""
function container_spec(::Type{Float64}, axs...)
    cont = DenseAxisArray{Float64}(undef, axs...)
    cont.data .= fill(NaN, size(cont.data))
    return cont
end

"""
Returns the correct container specification for the selected type of JuMP Model
"""
function sparse_container_spec(::Type{T}, axs...) where {T <: JuMP.AbstractJuMPScalar}
    indexes = Base.Iterators.product(axs...)
    contents = Dict{eltype(indexes), Any}(indexes .=> zero(T))
    return SparseAxisArray(contents)
end

function sparse_container_spec(::Type{T}, axs...) where {T <: Any}
    indexes = Base.Iterators.product(axs...)
    contents = Dict{eltype(indexes), Any}(indexes .=> 0.0)
    return SparseAxisArray(contents)
end

function remove_undef!(expression_array::AbstractArray)
    # iteration is deliberately unsupported for CartesianIndex
    # Makes this code a bit hacky to be able to use isassigned with an array of arbitrary size.
    for i in CartesianIndices(expression_array.data)
        if !isassigned(expression_array.data, i.I...)
            expression_array.data[i] = zero(eltype(expression_array))
        end
    end

    return expression_array
end

remove_undef!(expression_array::SparseAxisArray) = expression_array

function _calc_dimensions(
    array::DenseAxisArray,
    key::OptimizationContainerKey,
    num_rows::Int,
    horizon::Int,
)
    ax = axes(array)
    columns = get_column_names(key, array)
    # Two use cases for read:
    # 1. Read data for one execution for one device.
    # 2. Read data for one execution for all devices.
    # This will ensure that data on disk is contiguous in both cases.
    if length(ax) == 1
        dims = (horizon, 1, num_rows)
    elseif length(ax) == 2
        dims = (horizon, length(columns), num_rows)
    elseif length(ax) == 3
        #     # TODO: untested
        dims = (length(ax[2]), horizon, length(columns), num_rows)
    else
        error("unsupported data size $(length(ax))")
    end

    return Dict("columns" => columns, "dims" => dims)
end

function _calc_dimensions(
    array::SparseAxisArray,
    key::OptimizationContainerKey,
    num_rows::Int,
    horizon::Int,
)
    columns = get_column_names(key, array)
    dims = (horizon, length(columns), num_rows)
    return Dict("columns" => columns, "dims" => dims)
end

"""
Run this function only when getting detailed solver stats
"""
function _summary_to_dict!(optimizer_stats::OptimizerStats, jump_model::JuMP.Model)
    # JuMP.solution_summary uses a lot of try-catch so it has a performance hit and should be opt-in
    jump_summary = JuMP.solution_summary(jump_model, verbose=false)
    # Note we don't grab all the fields from the summary because not all can be encoded as Float for HDF store
    fields = [
        :has_values, # Bool
        :has_duals, # Bool
        # Candidate solution
        :objective_bound, # Union{Missing,Float64}
        :dual_objective_value, # Union{Missing,Float64}
        # Work counters
        :barrier_iterations, # Union{Missing,Int}
        :simplex_iterations, # Union{Missing,Int}
        :node_count, # Union{Missing,Int}
    ]

    for field in fields
        field_value = getfield(jump_summary, field)
        if ismissing(field_value)
            setfield!(optimizer_stats, field, missing)
        else
            setfield!(optimizer_stats, field, field_value)
        end
    end
    return
end

function supports_milp(jump_model::JuMP.Model)
    optimizer_backend = JuMP.backend(jump_model)
    return MOI.supports_constraint(optimizer_backend, MOI.VariableIndex, MOI.ZeroOne)
end

function _get_solver_time(jump_model::JuMP.Model)
    solver_solve_time = NaN

    try_s = get!(jump_model.ext, :try_supports_solvetime, (trycatch=true, supports=true))
    if try_s.trycatch
        try
            solver_solve_time = MOI.get(jump_model, MOI.SolveTimeSec())
            jump_model.ext[:try_supports_solvetime] = (trycatch=false, supports=true)
        catch
            @debug "SolveTimeSec() property not supported by the Solver"
            jump_model.ext[:try_supports_solvetime] = (trycatch=false, supports=false)
        end
    else
        if try_s.supports
            solver_solve_time = MOI.get(jump_model, MOI.SolveTimeSec())
        end
    end

    return solver_solve_time
end

function write_optimizer_stats!(optimizer_stats::OptimizerStats, jump_model::JuMP.Model)
    if JuMP.primal_status(jump_model) == MOI.FEASIBLE_POINT::MOI.ResultStatusCode
        optimizer_stats.objective_value = JuMP.objective_value(jump_model)
    else
        optimizer_stats.objective_value = Inf
    end

    optimizer_stats.termination_status = Int(JuMP.termination_status(jump_model))
    optimizer_stats.primal_status = Int(JuMP.primal_status(jump_model))
    optimizer_stats.dual_status = Int(JuMP.dual_status(jump_model))
    optimizer_stats.result_count = JuMP.result_count(jump_model)
    optimizer_stats.solve_time = _get_solver_time(jump_model)
    if optimizer_stats.detailed_stats
        _summary_to_dict!(optimizer_stats, jump_model)
    end
    return
end

"""
Exports the JuMP object in MathOptFormat
"""
function serialize_optimization_model(jump_model::JuMP.Model, save_path::String)
    MOF_model = MOPFM(format=MOI.FileFormats.FORMAT_MOF)
    MOI.copy_to(MOF_model, JuMP.backend(jump_model))
    MOI.write_to_file(MOF_model, save_path)
    return
end

# check_conflict_status functions can't be tested on CI because free solvers don't support IIS
function check_conflict_status(
    jump_model::JuMP.Model,
    constraint_container::DenseAxisArray{JuMP.ConstraintRef},
)
    conflict_indices = Vector()
    dims = axes(constraint_container)
    for index in Iterators.product(dims...)
        if MOI.get(
            jump_model,
            MOI.ConstraintConflictStatus(),
            constraint_container[index...],
        ) != MOI.NOT_IN_CONFLICT
            push!(conflict_indices, index)
        end
    end
    return conflict_indices
end

function check_conflict_status(
    jump_model::JuMP.Model,
    constraint_container::SparseAxisArray{JuMP.ConstraintRef},
)
    conflict_indices = Vector()
    for (index, constraint) in constraint_container
        if MOI.get(jump_model, MOI.ConstraintConflictStatus(), constraint) !=
           MOI.NOT_IN_CONFLICT
            push!(conflict_indices, index)
        end
    end
    return conflict_indices
end

ext: jl


text:
"""
    BuildSTree(S,n,u,d)

Build binomial tree, starting at `S` and having `n` steps with up move `u` and down move `d`

# Output
- `STree:: Vector or vectors`: each (sub-)vector is for a time step. `STree[0] = [S]` and `STree[n]` is for time period n.

"""
function BuildSTree(S,n,u,d)
    STree = [fill(NaN,i) for i = 1:n+1]  #vector of vectors (of different lengths)
    STree = OffsetArray(STree,0:n)       #convert so the indices are 0:n
    STree[0][1] = S                      #step 0 is in STree[0], element 1
    for i = 1:n                          #move forward in time
        STree[i][1:end-1] = u*STree[i-1]   #up move from STree[i-1][1:end]
        STree[i][end] = d*STree[i-1][end]  #down move from STree[i-1][end]
    end
    return STree
end

"""
    EuOptionPrice(STree,K,y,h,p;isPut=false)

Calculate price of European option from binomial model

# Output
- `Value:: Vector of vectors`: option values at different nodes, same structure as STree

"""
function EuOptionPrice(STree,K,y,h,p;isPut=false)     #price of European option
    Value = similar(STree)                            #tree for derivative, to fill
    n     = length(STree) - 1                         #number of steps in STree
    if isPut
        Value[n] = max.(0,K.-STree[n])            #put, at last time node
    else
        Value[n] = max.(0,STree[n].-K)            #call, at last time node
    end
    for i = n-1:-1:0                                   #move backward in time
        Value[i] = exp(-y*h)*(p*Value[i+1][1:end-1] + (1-p)*Value[i+1][2:end])
    end                                           #p*up + (1-p)*down, discount
    return Value
end

"""
    AmOptionPrice(STree,K,y,h,p;isPut=false)

Calculate price of American option from binomial model

# Output
- `Value:: Vector of vectors`: option values at different nodes, same structure as STree
- `Exerc::` Vector of vectors`: true if early exercise at the node, same structure as STree

"""
function AmOptionPrice(STree,K,y,h,p;isPut=false)     #price of American option
    Value = similar(STree)                            #tree for derivative, to fill
    n     = length(STree) - 1
    Exerc = similar(Value,BitArray)               #same structure as STree, but BitArrays, empty
    if isPut
        Value[n] = max.(0,K.-STree[n])            #put, at last time node
    else
        Value[n] = max.(0,STree[n].-K)            #call, at last time node
    end
    Exerc[n] = Value[n] .> 0                      #exercise
    for i = n-1:-1:0                                    #move backward in time
        fa  = exp(-y*h)*(p*Value[i+1][1:end-1] + (1-p)*Value[i+1][2:end])
        if isPut
            Value[i] = max.(K.-STree[i],fa)         #put
        else
            Value[i] = max.(STree[i].-K,fa)         #call
        end
        Exerc[i] = Value[i] .> fa                   #early exercise
    end
    return Value, Exerc
end

"""
    Φ(x)

Calculate Pr(z<=x) for N(0,1) variable z
"""
function Φ(x)
    Pr = cdf(Normal(0,1),x)
    return Pr
end

"""
    OptionBlackSPs(S,K,m,y,σ,δ=0,PutIt=false)

Calculate Black-Scholes European call or put option price, continuous dividends of δ
"""
function OptionBlackSPs(S,K,m,y,σ,δ=0;isPut=false)
    d1 = ( log(S/K) + (y-δ+0.5*σ^2)*m ) / (σ*sqrt(m))
    d2 = d1 - σ*sqrt(m)
    c  = exp(-δ*m)*S*Φ(d1) - K*exp(-y*m)*Φ(d2)
    if isPut
        price = c - exp(-δ*m)*S + exp(-y*m)*K
    else
        price = c
    end
    return price
end

max_stars_repo_name: snowdj/FinancialTheoryMSc

max_issues_repo_name: snowdj/FinancialTheoryMSc

max_forks_repo_name: snowdj/FinancialTheoryMSc


text:
module AdaptivelySampledDistanceFields

using StaticArrays
using RegionTrees
import RegionTrees: needs_refinement, refine_data
using Interpolations

@generated function evaluate(itp::AbstractInterpolation, point::SVector{N}) where N
    Expr(:ref, :itp, [:(point[$i]) for i in 1:N]...)
end

function evaluate(itp::AbstractInterpolation, point::AbstractArray)
    itp[point...]
end

function evaluate(cell::Cell{D}, point::AbstractArray) where D <: AbstractInterpolation
    leaf = findleaf(cell, point)
    evaluate(leaf.data, leaf.boundary, point)
end

function evaluate(interp::AbstractInterpolation, boundary::HyperRectangle, point::AbstractArray)
    coords = (point - boundary.origin) ./ boundary.widths + 1
    evaluate(interp, coords)
end

mutable struct SignedDistanceRefinery{F <: Function} <: AbstractRefinery
    signed_distance_func::F
    atol::Float64
    rtol::Float64
end

function needs_refinement(refinery::SignedDistanceRefinery, cell::Cell)
    minimum(cell.boundary.widths) > refinery.atol && needs_refinement(cell, refinery.signed_distance_func, refinery.atol, refinery.rtol)
end

function needs_refinement(cell::Cell, signed_distance_func, atol, rtol)
    for c in body_and_face_centers(cell.boundary)
        value_interp = evaluate(cell, c)
        value_true = signed_distance_func(c)
        if !isapprox(value_interp, value_true, rtol=rtol, atol=atol)
            return true
        end
    end
    false
end

function refine_data(refinery::SignedDistanceRefinery, cell::Cell, indices)
    refine_data(refinery, child_boundary(cell, indices))
end

function refine_data(refinery::SignedDistanceRefinery, boundary::HyperRectangle)
    interpolate!(refinery.signed_distance_func.(vertices(boundary)),
                 BSpline(Linear()),
                 OnGrid())
end

function ASDF(signed_distance::Function, origin::AbstractArray,
              widths::AbstractArray,
              rtol=1e-2,
              atol=1e-2)
    refinery = SignedDistanceRefinery(signed_distance, atol, rtol)
    boundary = HyperRectangle(origin, widths)
    root = Cell(boundary, refine_data(refinery, boundary))
    adaptivesampling!(root, refinery)
end

end


text:
module Context
using Printf
using Markdown
using Cairo
using ComplexVisual
@ComplexVisual.import_huge

import Main.DocGenerator: DocSource, DocCreationEnvironment, DocContext,
        Document, substitute_marker_in_markdown, create_doc_icon, append_md

"""
# [![./Context_docicon.png]({image_from_canvas: get_doc_icon()}) Context](./Context.md)

Contexts (i.e. subtypes of `CV_Context`) are very thin wrappers for Cairo
contexts. They are used to draw/paint (typically inside canvases).

## `doc: CV_Context`

## `doc: CV_CanvasContext`

## `doc: CV_2DCanvasContext`

## `doc: cv_create_context`
"""
context_intro() = nothing

function get_doc_icon()
    layout = CV_2DLayout()
    can = cv_filled_canvas(220, 220, cv_color(0, 0, 0.4))

    can_l = cv_add_canvas!(layout, can, cv_anchor(can, :center), (0, 0))

    stext = cv_text("Context", cv_white → cv_fontface("serif") → cv_fontsize(45))
    ptext = cv_add_canvas!(layout, stext, cv_anchor(stext, :center), (0, 0))

    can_layout = cv_canvas_for_layout(layout)
    cv_create_context(can_layout) do con_layout
        can_l(con_layout)
        ptext(con_layout)
    end

    icon = create_doc_icon(can_layout)
    return icon
end

function create_document(doc_env::DocCreationEnvironment)
    doc_source = DocSource("Context", @__MODULE__)
    context = DocContext(doc_env, doc_source)

    md = Markdown.MD()
    for part in (context_intro, )
        part_md = Base.Docs.doc(part)
        substitute_marker_in_markdown(context, part_md)

        append_md(md, part_md)
    end

    doc = Document(doc_source, md)
    return doc
end

end
# vim:syn=julia:cc=79:fdm=marker:sw=4:ts=4:


text:
x = 3
y = 3.3

@test UncertainValue(x) isa CertainValue
@test UncertainValue(y) isa CertainValue


text:
using E2ga
using Test

@testset "promote" begin
    a = E2ga.Geometric2(2.0, 5, 11, 17)
    @test typeof(a.α) == Float64
    @test typeof(a.x) == Float64
    @test typeof(a.y) == Float64
    @test typeof(a.β) == Float64
    @test "$(a)" == "2.0 + 5.0e1 + 11.0e2 + 17.0I"
end

@testset "scalar" begin
    a = E2ga.Geometric2(1)
    @test a.α == 1
    @test a.x == 0
    @test a.y == 0
    @test a.β == 0
end

@testset "+" begin
    a = E2ga.Geometric2(1, 3, 7, 13)
    b = E2ga.Geometric2(2, 5, 11, 17)
    c = a + b
    @test c.α == 3
    @test c.x == 8
    @test c.y == 18
    @test c.β == 30
end

@testset "-" begin
    a = E2ga.Geometric2(2, 5, 11, 17)
    b = E2ga.Geometric2(1, 3, 7, 13)
    c = a - b
    @test c.α == 1
    @test c.x == 2
    @test c.y == 4
    @test c.β == 4
end

@testset "*" begin
    a = E2ga.Geometric2(2, 5, 11, 17)
    b = E2ga.Geometric2(1, 3, 7, 13)
    c = a * b
    @test c.α == (2 * 1) + (5 * 3) + (11 * 7) - (17 * 13)
    @test c.x == (2 * 3) + (5 * 1) - (11 * 13) + (17 * 7)
    @test c.y == (2 * 7) + (5 * 13) + (11 * 1) - (17 * 3)
    @test c.β == (2 * 13) + (5 * 7) - (11 * 3) + (17 * 1)
end

@testset "one" begin
    one = E2ga.Geometric2(1)
    @test one.α == 1
    @test one.x == 0
    @test one.y == 0
    @test one.β == 0
end

@testset "e1" begin
    e1 = E2ga.Geometric2(0, 1, 0, 0)
    @test e1.α == 0
    @test e1.x == 1
    @test e1.y == 0
    @test e1.β == 0
end

@testset "e2" begin
    e2 = E2ga.Geometric2(0, 0, 1, 0)
    @test e2.α == 0
    @test e2.x == 0
    @test e2.y == 1
    @test e2.β == 0
end

@testset "I" begin
    I = E2ga.Geometric2(0, 0, 0, 1)
    @test I.α == 0
    @test I.x == 0
    @test I.y == 0
    @test I.β == 1
end

@testset "show" begin
    a = E2ga.Geometric2(2, 5, 11, 17)
    @test "$(a)" == "2 + 5e1 + 11e2 + 17I"
end


text:
# Shaddow DOM defaults

s = open(f->read(f, String), "src/Data/tab.sml")
tab = readSml(s)[1]

s = open(f->read(f, String), "src/Data/navigation.sml")
navigation = readSml(s)

s = open(f->read(f, String), "src/Data/tabControls.sml")
tabControls = readSml(s)[1]

newPage = Dict( ">" => "page", "display" => "block", "color" => [0.8,0.8,0.8], "nodes"   => [] )


text:
"""
$(TYPEDEF)

Simplex grid builder: wrapper around array based mesh generator interface.
It allows to build up the input data incrementally.

"""
mutable struct SimplexGridBuilder
    Generator::Union{Module,Nothing}
    current_facetregion::Cint
    current_cellregion::Cint
    current_cellvolume::Cdouble
    point_identity_tolerance::Cdouble
    facetregions::Vector{Cint}
    facets::Vector{Vector{Cint}}
    pointlist::BinnedPointList{Cdouble}
    regionpoints::ElasticArray{Cdouble,2}
    regionnumbers::Vector{Cint}
    regionvolumes::Vector{Cdouble}
    options::Dict{Symbol, Any}
    checkexisting::Bool
    SimplexGridBuilder(x::Nothing) = new()
end

"""
```
SimplexGridBuilder(; Generator=nothing,
                     tol=1.0e-12,
                     checkexisting=true)
```

Create a SimplexGridBuilder.

- `Generator`: module corresponding to mesh generator package.
   Valid choices are `TetGen` and `Triangulate`, corresponding to the
   respective Julia packages.
- `checkexisting`: whether to check for already existing points
- `tol`: two points below this tolerance will be merged if `checkexisting` is true
"""
function SimplexGridBuilder(;Generator=nothing,tol=1.0e-12,checkexisting=true)
    builder=SimplexGridBuilder(nothing)

    if isnothing(Generator)
        throw(ArgumentError("Missing Generator: SimplexGridBuilder needs Generator=TetGen or Generator=Triangulate as argument"))
    end

    builder.Generator=Generator

    if istetgen(Generator)
        dim=3
        # Heuristic version test via expected features. This could be made
        # into a real test for later versions were we can have a constant TetGen.TetGenVersion
        # for this purpose.
        # Testing via pkg does not cover all relevant use cases.
        if !isdefined(Generator,:tetunsuitable)
            throw(ArgumentError("Outdated TetGen.jl version, need at least v1.1.1"))
        end
    elseif istriangulate(Generator)
        dim=2
        if !isdefined(Generator,:tricircumcenter!)
            throw(ArgumentError("Outdated Triangulate.jl version, need at least v1.0.1"))
        end
    else
        throw(ArgumentError("Wrong Generator: SimplexGridBuilder needs Generator=TetGen or Generator=Triangulate as argument"))
    end

    builder.current_facetregion=1
    builder.current_cellregion=1
    builder.current_cellvolume=1

    builder.point_identity_tolerance=tol
    builder.facets=[]
    builder.facetregions=[]
    builder.pointlist=BinnedPointList(dim,tol=tol)
    builder.regionpoints=ElasticArray{Cdouble}(undef,dim,0)
    builder.regionvolumes=[]
    builder.regionnumbers=[]
    builder.options=default_options()
    builder.checkexisting=checkexisting
    builder
end

"""
$(SIGNATURES)

Whether to check for already existing points
"""
checkexisting!(builder,b)=builder.checkexisting=b

"""
$(SIGNATURES)

Set some mesh generation options, see [`default_options`](@ref)
"""
options!(builder::SimplexGridBuilder; kwargs...)=blendoptions!(builder.options; kwargs...)

"""
$(SIGNATURES)

Space dimension of builder.
"""
ExtendableGrids.dim_space(builder::SimplexGridBuilder)=size(builder.pointlist.points,1)

"""
```
point!(builder,x)
point!(builder,x,y)
point!(builder,x,y,z)
point!(builder,vec_or_tuple)
```

Add point or merge with already existing point. Returns its index
which can be used to set up facets with [`facet!`](@ref).
"""
function point!(builder::SimplexGridBuilder,x)
    dim_space(builder)==1||throw(DimensionMismatch())
    insert!(builder.pointlist,[x])
end

function point!(builder::SimplexGridBuilder,x,y)
    dim_space(builder)==2||throw(DimensionMismatch())
    insert!(builder.pointlist,[x,y])
end

function point!(builder::SimplexGridBuilder,x,y,z)
    dim_space(builder)==3||throw(DimensionMismatch())
    insert!(builder.pointlist,[x,y,z])
end

point!(builder::SimplexGridBuilder, p::Union{AbstractVector,Tuple})=point!(builder,p...)

"""
```
cellregion!(builder,region)
```

Set the current cell region (acts on subsequent regionpoint() calls)

Cell regions can be used to distinguish cells of different materials etc.
In the API they are characterized by
- region number set via `cellregion!`
- maximum cell volume set via [`maxvolume!`](@ref)
- region point set via  [`regionpoint!`](@ref). This is some point located
  within the respective region which must be surrounded by facets in a watertight
  manner.
"""
cellregion!(builder::SimplexGridBuilder,i)=builder.current_cellregion=i

"""
```
maxvolume!(builder,vol)
```

Set the current cell volume resp. area (acts on subsequent regionpoint() calls).
See [`cellregion!`](@ref).
"""
maxvolume!(builder::SimplexGridBuilder,vol)=builder.current_cellvolume=vol

"""
```
regionpoint!(builder,x)
regionpoint!(builder,x,y)
regionpoint!(builder,x,y,z)
regionpoint!(builder,vec_or_tuple)
```
Add a region point marking a region, using current cell volume an cell region
See [`cellregion!`](@ref).
"""
function regionpoint!(builder::SimplexGridBuilder,x)
    dim_space(builder)==1||throw(DimensionMismatch())
    append!(builder.regionpoints,(x))
    push!(builder.regionvolumes,builder.current_cellvolume)
    push!(builder.regionnumbers,builder.current_cellregion)
end

function regionpoint!(builder::SimplexGridBuilder,x,y)
    dim_space(builder)==2||throw(DimensionMismatch())
    append!(builder.regionpoints,(x,y))
    push!(builder.regionvolumes,builder.current_cellvolume)
    push!(builder.regionnumbers,builder.current_cellregion)
end

function regionpoint!(builder::SimplexGridBuilder,x,y,z)
    dim_space(builder)==3||throw(DimensionMismatch())
    append!(builder.regionpoints,(x,y,z))
    push!(builder.regionvolumes,builder.current_cellvolume)
    push!(builder.regionnumbers,builder.current_cellregion)
end

regionpoint!(builder::SimplexGridBuilder,p::Union{Vector,Tuple})=regionpoint!(builder,p...)

"""
```
holepoint!(builder,x)
holepoint!(builder,x,y)
holepoint!(builder,x,y,z)
holepoint!(builder,vec_or_tuple)
```
Add a point marking a hole region. Hole regions need to be surrounded by facets
in a watertight manner.
"""
function holepoint!(builder::SimplexGridBuilder, x)
    dim_space(builder)==1||throw(DimensionMismatch())
    append!(builder.regionpoints,(x))
    push!(builder.regionvolumes,0)
    push!(builder.regionnumbers,0)
    nothing
end

function holepoint!(builder::SimplexGridBuilder, x,y)
    dim_space(builder)==2||throw(DimensionMismatch())
    append!(builder.regionpoints,(x,y))
    push!(builder.regionvolumes,0)
    push!(builder.regionnumbers,0)
    nothing
end

function holepoint!(builder::SimplexGridBuilder, x,y,z)
    dim_space(builder)==3||throw(DimensionMismatch())
    append!(builder.regionpoints,(x,y,z))
    push!(builder.regionvolumes,0)
    push!(builder.regionnumbers,0)
    nothing
end

holepoint!(builder::SimplexGridBuilder, p::Union{Vector,Tuple})=holepoint!(builder,p...)

"""
```
facetregion!(builder,region)
```
Set the current facet region. Subsequent facets will be marked with this number.
Facet regions can be used to mark different parts ot the boundary, e.g. for
distinguishing boundary conditions.
"""
facetregion!(builder::SimplexGridBuilder,i)=builder.current_facetregion=i

"""
```
facet!(builder,i1)
facet!(builder,i1,i2)
facet!(builder,i1,i2,i3,i4)
facet!(builder,vector_or_tuple)
```

Add a facet via the corresponding point indices returned
by [`point!`](@ref).

Facets of two points are solely used for 2D grids. Facets
with more than two poins are used for 3D grids and must be
planar.
"""
function facet!(builder::SimplexGridBuilder,i)
    dim_space(builder)==1||throw(DimensionMismatch())
    push!(builder.facets,[i])
    push!(builder.facetregions,builder.current_facetregion)
    length(builder.facets)
end

function facet!(builder::SimplexGridBuilder,i1,i2)
    dim_space(builder)==2||throw(DimensionMismatch())
    push!(builder.facets,[i1,i2])
    push!(builder.facetregions,builder.current_facetregion)
    length(builder.facets)
end

function facet!(builder::SimplexGridBuilder,i1,i2,i3)
    dim_space(builder)==3||throw(DimensionMismatch())
    push!(builder.facets,[i1,i2,i3])
    push!(builder.facetregions,builder.current_facetregion)
    length(builder.facets)
end

function facet!(builder::SimplexGridBuilder,i1,i2,i3,i4)
    dim_space(builder)==3||throw(DimensionMismatch())
    push!(builder.facets,[i1,i2,i3,i4])
    push!(builder.facetregions,builder.current_facetregion)
    length(builder.facets)
end

function facet!(builder::SimplexGridBuilder,p::Union{Vector,Tuple})
    if dim_space(builder)==1
        length(p)==1 || throw(DimensionMismatch())
    end
    if dim_space(builder)==2
        length(p)==2 || throw(DimensionMismatch())
    end
    if dim_space(builder)==3
        length(p)>=3 || throw(DimensionMismatch())
    end
    push!(builder.facets,[p...])
    push!(builder.facetregions,builder.current_facetregion)
    length(builder.facets)
end

"""
```
simplexgrid(builder; kwargs...)
```

Build simplex grid from the current state of the builder.
`kwargs` overwrite those set with the [`options!`](@ref) method.
See [`default_options`](@ref) for available `kwargs`.
"""
function ExtendableGrids.simplexgrid(builder::SimplexGridBuilder; kwargs...)

    if dim_space(builder)==2
        facets=Array{Cint,2}(undef,2,length(builder.facets))
        for i=1:length(builder.facets)
            facets[1,i]=builder.facets[i][1]
            facets[2,i]=builder.facets[i][2]
        end
    else
        facets=builder.facets
    end

    options=blendoptions!(copy(builder.options);kwargs...)

    ExtendableGrids.simplexgrid(builder.Generator,
                                points=builder.pointlist.points,
                                bfaces=facets,
                                bfaceregions=builder.facetregions,
                                regionpoints=builder.regionpoints,
                                regionnumbers=builder.regionnumbers,
                                regionvolumes=builder.regionvolumes,
                                Generator=builder.Generator;
                                options...)
end

function flags(builder::SimplexGridBuilder)
    if istetgen(builder.Generator)
        makeflags(builder.options,:tetgen)
    elseif istriangulate(builder.Generator)
        makeflags(builder.options,:triangle)
    else
        nothing
    end
end


text:
"""
There are following options available:
- `abstol::Float64`: the absolute tolerance used in the convergence test (*deprecated, use `metrics` parameter of a particular optimization algorithm*)
- `reltol::Float64`: the relative tolerance used in the convergence test (*deprecated, use `metrics` parameter of a particular optimization algorithm*)
- `successive_f_tol::Integer`: the additional number of the iterations of the optimization algorithm after the convergence test is satisfied (*default: 10*)
- `iterations::Integer`: the total number of the iterations of the optimization algorithm (*default: 1000*)
- `show_trace::Bool`: enable the trace information display during the optimization (*default: false*).
- `store_trace::Bool`: enable the trace information capturing during the optimization (*default: false*). The trace can be accessed by using [`trace`](@ref) function after optimization is finished.
- `show_every::Integer`: show every `n`s successive trace message (*default: 1*)
- `time_limit::Float64`: the time limit for the optimization run in seconds. If the value set to `NaN` then the limit is not set. (*default: NaN*)
- `callback`: the callback function that is called after each iteration of the optimization algorithm. The function accepts as parameter a trace dictionary, and **must** return a `Bool` value which if `true` terminates the optimization. (*default: nothing*)
- `parallelization::Symbol`: allows parallelization of the population fitness evaluation if set to `:thread` using multiple threads (*default: `:serial`*)
- `rng::AbstractRNG`: a random number generator object that is used to control generation of random data during the evolutionary optimization (*default: `Random.default_rng()`*)
"""
Base.@kwdef struct Options{TCallback<:Union{Nothing,Function},TRNG<:AbstractRNG}
    abstol::Float64 = Inf
    reltol::Float64 = Inf
    successive_f_tol::Int = 10
    iterations::Int = 1000
    store_trace::Bool = false
    show_trace::Bool = false
    show_every::Int = 1
    callback::TCallback = nothing
    time_limit::Float64 = NaN
    parallelization::Symbol = :serial
    rng::TRNG = Random.default_rng()
    state_callback = nothing
end

function show(io::IO, o::Options)
    for k in fieldnames(typeof(o))
        v = getfield(o, k)
        if v === nothing
            print(io, lpad("$(k)", 24) * " = nothing\n")
        else
            print(io, lpad("$(k)", 24) * " = $v\n")
        end
    end
end


text:
using BinDeps

@BinDeps.setup

libopenslide = library_dependency("libopenslide", aliases = ["libopenslide-0"])

#=
@windows_only begin
  using WinRPM

  osld_win_url = "https://github.com/openslide/openslide-winbuild/releases/download/v20140125/openslide-win$(WORD_SIZE)-20140125.zip"
  provides(Binaries, {URI(osld_win_url) => libopenslide}, os = :Windows)
  push!(DL_LOAD_PATH, "bin")
end
=#

provides(SimpleBuild, (), libopenslide, os = :Windows)

@BinDeps.install [:libopenslide => :los]


text:
for (fname, elty) in ((:dgemv_, :Float64),
                        (:sgemv_, :Float32),
                        (:zgemv_, :ComplexF64),
                        (:cgemv_, :ComplexF32))
    @eval begin
        function mul!(y::VecOrMat{$elty}, A::Matrix{$elty}, x::VecOrMat{$elty}, istart::Int, jstart::Int, INCX::Int, INCY::Int)
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                    Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                    Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                    'N', size(A,1), size(A,2), $elty(1.0),
                    A, max(1,stride(A,2)), pointer(x, jstart), INCX,
                    $elty(1.0), pointer(y, istart), INCY)
            y
        end
        function mul!(y::VecOrMat{$elty}, At::Transpose{$elty,Matrix{$elty}}, x::VecOrMat{$elty}, istart::Int, jstart::Int, INCX::Int, INCY::Int)
            A = parent(At)
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                    Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                    Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                    'T', size(A,1), size(A,2), $elty(1.0),
                    A, max(1,stride(A,2)), pointer(x, jstart), INCX,
                    $elty(1.0), pointer(y, istart), INCY)
            y
        end
        function mul!(y::VecOrMat{$elty}, Ac::Adjoint{$elty,Matrix{$elty}}, x::VecOrMat{$elty}, istart::Int, jstart::Int, INCX::Int, INCY::Int)
            A = parent(Ac)
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                    Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                    Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                    'C', size(A,1), size(A,2), $elty(1.0),
                    A, max(1,stride(A,2)), pointer(x, jstart), INCX,
                    $elty(1.0), pointer(y, istart), INCY)
            y
        end
    end
end

for (fname, elty) in ((:dgemv_,:Float64),
                      (:sgemv_,:Float32),
                      (:zgemv_,:ComplexF64),
                      (:cgemv_,:ComplexF32))
    @eval begin
        function mul!(y::VecOrMat{$elty}, L::LowRankMatrix{$elty}, x::VecOrMat{$elty}, istart::Int, jstart::Int, INCX::Int, INCY::Int)
            fill!(L.temp, zero($elty))
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                 Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                 Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                 'T', size(L,2), rank(L), $elty(1.0),
                 L.V, max(1,stride(L.V,2)), pointer(x, jstart), INCX,
                 $elty(1.0), L.temp, 1)
            unsafe_broadcasttimes!(L.temp, L.Σ.diag)
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                 Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                 Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                 'N', size(L,1), rank(L), $elty(1.0),
                 L.U, max(1,stride(L.U,2)), L.temp, 1,
                 $elty(1.0), pointer(y, istart), INCY)

             y
        end
    end
end

for (fname, elty) in ((:dgemv_,:Float64),
                      (:sgemv_,:Float32),
                      (:zgemv_,:ComplexF64),
                      (:cgemv_,:ComplexF32))
    @eval begin
        function mul!(u::Vector{$elty}, B::BarycentricMatrix2D{$elty}, v::Vector{$elty}, istart::Int, jstart::Int)
            fill!(B.temp1, zero($elty))
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                 Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                 Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                 'T', size(B.V,1), size(B.V,2), $elty(1.0),
                 B.V, max(1,stride(B.V,2)), pointer(v, jstart), 1,
                 $elty(1.0), B.temp1, 1)
            fill!(B.temp2, zero($elty))
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                 Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                 Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                 'N', size(B.B.F,1), size(B.B.F,2), $elty(1.0),
                 B.B.F, max(1,stride(B.B.F,2)), B.temp1, 1,
                 $elty(1.0), B.temp2, 1)
            ccall((@blasfunc($fname), libblas), Nothing,
                (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty},
                 Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
                 Ref{$elty}, Ptr{$elty}, Ref{BlasInt}),
                 'N', size(B.U,1), size(B.U,2), $elty(1.0),
                 B.U, max(1,stride(B.U,2)), B.temp2, 1,
                 $elty(1.0), pointer(u, istart), 1)
             u
        end
    end
end


text:
@testset "Colorspace transforms tests" begin
    # f = Chain(x->HSV.(x),channelify,flatten,Dense(768,16),Dense(16,10),x->σ.(x))
    # g_3 = Chain(Conv((3,3),7=>4,relu),
    #           Conv((3,3),4=>3,relu),
    #           x->colorify(RGB,x),
    #           x->HSV.(x),
    #           channelify,
    #           flatten,
    #           Dense(256*3,16),
    #           Dense(16,10),
    #           x->σ.(x))
    # g_1 = Chain(Conv((3,3),7=>4,relu),
    #           Conv((3,3),4=>3,relu),
    #           x->colorify(RGB,x),
    #           x->Gray.(x),
    #           channelify,
    #           flatten,
    #           Dense(256*1,16),
    #           Dense(16,10),
    #           x->σ.(x))
    ds = (7, 7, 5)
    ds4 = (7, 7, 4, 5)
    ds3 = (7, 7, 3, 5)
    ds2 = (7, 7, 2, 5)
    ds1 = (7, 7, 1, 5)

    cspaces_with_random = (YIQ,
                           LCHab,
                           Lab,
                           BGRA, ABGR, BGR,
                           RGBA, ARGB, RGB,
                           HSL,
                           AGray, GrayA, Gray,
                           HSV) # colorspaces those have samplers defined for Base.Random

    cspaces_all = (HSV, AHSV, HSVA,
               Gray, AGray, GrayA,
               HSL, AHSL, HSLA,
               RGB, ARGB, RGBA,
               BGR, ABGR, BGRA,
               XYZ, AXYZ, XYZA,
               xyY, AxyY, xyYA,
               Lab, ALab, LabA,
               Luv, ALuv, LuvA,
               LCHab, ALCHab, LCHabA,
               LCHuv, ALCHuv, LCHuvA,
               DIN99, ADIN99, DIN99A,
               LMS, ALMS, LMSA,
               YIQ, AYIQ, YIQA) # tuple of all of Colorspaces and their transparent variants

    cspaces_4 = (BGRA, ABGR,
                 RGBA, ARGB,
                 AHSL, HSLA,
                 AHSV, HSVA,
                 AXYZ, XYZA,
                 AxyY, xyYA,
                 ALab, LabA,
                 ALuv, LuvA,
                 ALCHab, LCHabA,
                 ALCHuv, LCHuvA,
                 ADIN99, DIN99A,
                 ALMS, LMSA,
                 AYIQ, YIQA) # all 4 channel colorspaces

    i_2 = rand(BGR, 5, 3) # 2-dim input testing
    i_4 = rand(RGBA, 9, 9, 2) # 4-channel testing; RGBA chosen because Random sampler available
    @testset "Testing channelify" begin
        @test size(channelify(i_2)) == (5, 3, 3) # to check if 2-dim inputs are working. Currently no use of them.
        @test size(channelify(i_4)) == (9, 9, 4, 2) # to check if 4 channel outputs are correct.
        for cs in cspaces_with_random
            i = rand(cs, ds...)
            if cs ∈ (Gray,)
                @test size(channelify(i)) == (ds[1:end - 1]..., 1, ds[end])
            elseif cs ∈ (AGray, GrayA)
                @test size(channelify(i)) == (ds[1:end - 1]..., 2, ds[end])
            elseif cs ∈ (BGRA, ABGR, RGBA, ARGB)
                @test size(channelify(i)) == (ds[1:end - 1]..., 4, ds[end])
            else
                @test size(channelify(i)) == (ds[1:end - 1]..., 3, ds[end])
            end
        end
    end
    @testset "Testing colorify" begin
        for cs in cspaces_all
            if cs ∈ cspaces_4
                i = rand(ds4...)
                @test size(colorify(cs, i)) == (ds4[1:end - 2]..., ds4[end])
            elseif cs ∈ (AGray, GrayA)
                i = rand(ds2...)
                @test size(colorify(cs, i)) == (ds4[1:end - 2]..., ds4[end])
            elseif cs ∈ (Gray,)
                i = rand(ds1...)
                @test size(colorify(cs, i)) == (ds4[1:end - 2]..., ds4[end])
            else
                i = rand(ds3...)
                @test size(colorify(cs, i)) == (ds4[1:end - 2]..., ds4[end])
            end
        end
    end
    @testset "Testing reversibilty" begin
        for cs in cspaces_all
            if cs ∈ cspaces_4
                i = rand(ds4...)
                @test channelify(colorify(cs, i)) == i
            elseif cs ∈ (AGray, GrayA)
                i = rand(ds2...)
                @test channelify(colorify(cs, i)) == i
            elseif cs ∈ (Gray,)
                i = rand(ds1...)
                @test channelify(colorify(cs, i)) == i
            else
                i = rand(ds3...)
                @test channelify(colorify(cs, i)) == i
            end
        end
    end
    @testset "Testing Differentiability" begin
        # channelview
        @testset "Testing channelview" begin
            for cs in cspaces_with_random
                i = rand(cs, ds...)
                if cs ∈ (Gray,)
                    @test channelview(gradient(x -> sum(channelview(x)), i)[1]) == ones(Float64, ds...)
                elseif cs ∈ (AGray, GrayA)
                    @test channelview(gradient(x -> sum(channelview(x)), i)[1]) == ones(Float64, 2, ds...)
                elseif cs ∈ (BGRA, ABGR, RGBA, ARGB)
                    @test channelview(gradient(x -> sum(channelview(x)), i)[1]) == ones(Float64, 4, ds...)
                else
                    @test channelview(gradient(x -> sum(channelview(x)), i)[1]) == ones(Float64, 3, ds...)
                end
            end
        end
        # colorview
        # TODO: colorview(T, gray1, gray2...) tests will have to be written, after writing their adjoints.
        @testset "Testing colorview" begin
            for cs in cspaces_all
                if cs ∈ cspaces_4
                    i = rand(ds4[end - 1], ds4[1:end - 2]..., ds4[end])
                    @test gradient(x->sum(channelview(colorview(cs,x))),i)[1]==ones(size(i))
                elseif cs ∈ (AGray, GrayA)
                    i = rand(ds2[end - 1], ds2[1:end - 2]..., ds2[end])
                    @test gradient(x->sum(channelview(colorview(cs,x))),i)[1]==ones(size(i))
                elseif cs ∈ (Gray,)
                    i = rand(ds1[1:end - 2]..., ds1[end])
                    @test gradient(x->sum(channelview(colorview(cs,x))),i)[1]==ones(size(i))
                else
                    i = rand(ds3[end - 1], ds3[1:end - 2]..., ds3[end])
                    @test gradient(x->sum(channelview(colorview(cs,x))),i)[1]==ones(size(i))
                end
            end
        end
        # channelify
        @testset "Testing channelify" begin
            for cs in cspaces_with_random
                i = rand(cs, ds...)
                if cs ∈ (Gray,)
                    @test channelify(gradient(x -> sum(channelify(x)), i)[1]) == ones(Float64, ds[1:end-1]..., 1, ds[end])
                elseif cs ∈ (AGray, GrayA)
                    @test channelify(gradient(x -> sum(channelify(x)), i)[1]) == ones(Float64, ds[1:end-1]..., 2, ds[end])
                elseif cs ∈ (BGRA, ABGR, RGBA, ARGB)
                    @test channelify(gradient(x -> sum(channelify(x)), i)[1]) == ones(Float64, ds[1:end-1]..., 4, ds[end])
                else
                    @test channelify(gradient(x -> sum(channelify(x)), i)[1]) == ones(Float64, ds[1:end-1]..., 3, ds[end])
                end
            end
        end
        # colorify
        @testset "Testing colorify" begin
            for cs in cspaces_all
                if cs ∈ cspaces_4
                    i = rand(ds4...)
                    @test gradient(x->sum(channelify(colorify(cs,x))),i)[1]==ones(size(i))
                elseif cs ∈ (AGray, GrayA)
                    i = rand(ds2...)
                    @test gradient(x->sum(channelify(colorify(cs,x))),i)[1]==ones(size(i))
                elseif cs ∈ (Gray,)
                    i = rand(ds1...)
                    @test gradient(x->sum(channelify(colorify(cs,x))),i)[1]==ones(size(i))
                else
                    i = rand(ds3...)
                    @test gradient(x->sum(channelify(colorify(cs,x))),i)[1]==ones(size(i))
                end
            end
        end
    end
end


text:
using .CUDA
import .CUDA: CuDevice, CuContext, devices, attribute

export CuArrayProc, CuArrayDeviceProc, CuArraySMProc

"Represents a single CUDA GPU device."
struct CuArrayDeviceProc <: Dagger.Processor
    owner::Int
    #ctx::CuContext
    device::CuDevice
end
@gpuproc(CuArrayDeviceProc, CuArray)
const CuArrayProc = CuArrayDeviceProc
#= FIXME: CUDA IPC
function Dagger.move(ctx, from::CuArrayDeviceProc, to::CuArrayDeviceProc, x)
    if from === to
        return x
    else
        error("Not implemented")
    end
end
=#
function Dagger.execute!(proc::CuArrayDeviceProc, func, args...)
    #CUDA.context!(proc.ctx)
    CUDA.@sync func(args...)
end

"Represents a single CUDA GPU Streaming Multiprocessor."
struct CuArraySMProc <: Dagger.Processor
    owner::Int
    #ctx::CuContext
    device::CuDevice
    sm::Int
end
@gpuproc(CuArraySMProc, CuArray)
#= FIXME: CUDA IPC
function Dagger.move(ctx, from::CuArraySMProc, to::CuArraySMProc, x)
    if from.device === to.device
        return x
    else
        error("Not implemented")
    end
end
=#
function Dagger.execute!(proc::CuArraySMProc, func, args...)
    #CUDA.context!(proc.ctx)
    CUDA.@sync func(args...)
end

processor(::Val{:CUDA}) = CuArrayDeviceProc
cancompute(::Val{:CUDA}) = CUDA.has_cuda()
# TODO: CuArraySMProc

if CUDA.has_cuda()
    for dev in devices()
        Dagger.add_callback!(proc -> begin
            return CuArrayDeviceProc(Distributed.myid(), #=CuContext(dev),=# dev)
        end)
        for i in 1:attribute(dev, CUDA.CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT)
            Dagger.add_callback!(proc -> begin
                return CuArraySMProc(Distributed.myid(), #=CuContext(dev),=# dev, i)
            end)
        end
    end
end