text:
using Blosc2_jll
export Blosc2_jll

using CEnum

const __darwin_time_t = Clong

struct timespec
    tv_sec::__darwin_time_t
    tv_nsec::Clong
end

struct blosc2_stdio_file
    file::Ptr{Libc.FILE}
end

function blosc2_stdio_open(urlpath, mode, params)
    @ccall libblosc2.blosc2_stdio_open(urlpath::Cstring, mode::Cstring, params::Ptr{Cvoid})::Ptr{Cvoid}
end

function blosc2_stdio_close(stream)
    @ccall libblosc2.blosc2_stdio_close(stream::Ptr{Cvoid})::Cint
end

function blosc2_stdio_tell(stream)
    @ccall libblosc2.blosc2_stdio_tell(stream::Ptr{Cvoid})::Int64
end

function blosc2_stdio_seek(stream, offset, whence)
    @ccall libblosc2.blosc2_stdio_seek(stream::Ptr{Cvoid}, offset::Int64, whence::Cint)::Cint
end

function blosc2_stdio_write(ptr, size, nitems, stream)
    @ccall libblosc2.blosc2_stdio_write(ptr::Ptr{Cvoid}, size::Int64, nitems::Int64, stream::Ptr{Cvoid})::Int64
end

function blosc2_stdio_read(ptr, size, nitems, stream)
    @ccall libblosc2.blosc2_stdio_read(ptr::Ptr{Cvoid}, size::Int64, nitems::Int64, stream::Ptr{Cvoid})::Int64
end

function blosc2_stdio_truncate(stream, size)
    @ccall libblosc2.blosc2_stdio_truncate(stream::Ptr{Cvoid}, size::Int64)::Cint
end

@cenum var"##Ctag#263"::UInt32 begin
    BLOSC_VERSION_FORMAT_PRE1 = 1
    BLOSC1_VERSION_FORMAT = 2
    BLOSC2_VERSION_FORMAT_ALPHA = 3
    BLOSC2_VERSION_FORMAT_BETA1 = 4
    BLOSC_VERSION_FORMAT = 4
end

@cenum var"##Ctag#264"::UInt32 begin
    BLOSC2_VERSION_FRAME_FORMAT_BETA2 = 1
    BLOSC2_VERSION_FRAME_FORMAT_RC1 = 2
    BLOSC2_VERSION_FRAME_FORMAT = 2
end

@cenum var"##Ctag#265"::UInt32 begin
    BLOSC_MIN_HEADER_LENGTH = 16
    BLOSC_EXTENDED_HEADER_LENGTH = 32
    BLOSC_MAX_OVERHEAD = 32
    BLOSC_MAX_BUFFERSIZE = 2147483615
    BLOSC_MAX_TYPESIZE = 255
    BLOSC_MIN_BUFFERSIZE = 128
end

@cenum var"##Ctag#266"::UInt32 begin
    BLOSC2_DEFINED_FILTERS_START = 0
    BLOSC2_DEFINED_FILTERS_STOP = 31
    BLOSC2_GLOBAL_REGISTERED_FILTERS_START = 32
    BLOSC2_GLOBAL_REGISTERED_FILTERS_STOP = 159
    BLOSC2_GLOBAL_REGISTERED_FILTERS = 2
    BLOSC2_USER_REGISTERED_FILTERS_START = 128
    BLOSC2_USER_REGISTERED_FILTERS_STOP = 255
    BLOSC2_MAX_FILTERS = 6
    BLOSC2_MAX_UDFILTERS = 16
end

@cenum var"##Ctag#267"::UInt32 begin
    BLOSC_NOSHUFFLE = 0
    BLOSC_NOFILTER = 0
    BLOSC_SHUFFLE = 1
    BLOSC_BITSHUFFLE = 2
    BLOSC_DELTA = 3
    BLOSC_TRUNC_PREC = 4
    BLOSC_LAST_FILTER = 5
    BLOSC_LAST_REGISTERED_FILTER = 33
end

@cenum var"##Ctag#268"::UInt32 begin
    BLOSC_DOSHUFFLE = 1
    BLOSC_MEMCPYED = 2
    BLOSC_DOBITSHUFFLE = 4
    BLOSC_DODELTA = 8
end

@cenum var"##Ctag#269"::UInt32 begin
    BLOSC2_USEDICT = 1
    BLOSC2_BIGENDIAN = 2
end

@cenum var"##Ctag#270"::UInt32 begin
    BLOSC2_MAXDICTSIZE = 131072
    BLOSC2_MAXBLOCKSIZE = 536866816
end

@cenum var"##Ctag#271"::UInt32 begin
    BLOSC2_DEFINED_CODECS_START = 0
    BLOSC2_DEFINED_CODECS_STOP = 31
    BLOSC2_GLOBAL_REGISTERED_CODECS_START = 32
    BLOSC2_GLOBAL_REGISTERED_CODECS_STOP = 159
    BLOSC2_GLOBAL_REGISTERED_CODECS = 1
    BLOSC2_USER_REGISTERED_CODECS_START = 160
    BLOSC2_USER_REGISTERED_CODECS_STOP = 255
end

@cenum var"##Ctag#272"::UInt32 begin
    BLOSC_BLOSCLZ = 0
    BLOSC_LZ4 = 1
    BLOSC_LZ4HC = 2
    BLOSC_ZLIB = 4
    BLOSC_ZSTD = 5
    BLOSC_LAST_CODEC = 6
    BLOSC_LAST_REGISTERED_CODEC = 32
end

@cenum var"##Ctag#273"::UInt32 begin
    BLOSC_BLOSCLZ_LIB = 0
    BLOSC_LZ4_LIB = 1
    BLOSC_ZLIB_LIB = 3
    BLOSC_ZSTD_LIB = 4
    BLOSC_UDCODEC_LIB = 6
    BLOSC_SCHUNK_LIB = 7
end

@cenum var"##Ctag#274"::UInt32 begin
    BLOSC_BLOSCLZ_FORMAT = 0
    BLOSC_LZ4_FORMAT = 1
    BLOSC_LZ4HC_FORMAT = 1
    BLOSC_ZLIB_FORMAT = 3
    BLOSC_ZSTD_FORMAT = 4
    BLOSC_UDCODEC_FORMAT = 6
end

@cenum var"##Ctag#275"::UInt32 begin
    BLOSC_BLOSCLZ_VERSION_FORMAT = 1
    BLOSC_LZ4_VERSION_FORMAT = 1
    BLOSC_LZ4HC_VERSION_FORMAT = 1
    BLOSC_ZLIB_VERSION_FORMAT = 1
    BLOSC_ZSTD_VERSION_FORMAT = 1
    BLOSC_UDCODEC_VERSION_FORMAT = 1
end

@cenum var"##Ctag#276"::UInt32 begin
    BLOSC_ALWAYS_SPLIT = 1
    BLOSC_NEVER_SPLIT = 2
    BLOSC_AUTO_SPLIT = 3
    BLOSC_FORWARD_COMPAT_SPLIT = 4
end

@cenum var"##Ctag#277"::UInt32 begin
    BLOSC2_CHUNK_VERSION = 0
    BLOSC2_CHUNK_VERSIONLZ = 1
    BLOSC2_CHUNK_FLAGS = 2
    BLOSC2_CHUNK_TYPESIZE = 3
    BLOSC2_CHUNK_NBYTES = 4
    BLOSC2_CHUNK_BLOCKSIZE = 8
    BLOSC2_CHUNK_CBYTES = 12
    BLOSC2_CHUNK_FILTER_CODES = 16
    BLOSC2_CHUNK_FILTER_META = 24
    BLOSC2_CHUNK_BLOSC2_FLAGS = 31
end

@cenum var"##Ctag#278"::UInt32 begin
    BLOSC2_NO_SPECIAL = 0
    BLOSC2_SPECIAL_ZERO = 1
    BLOSC2_SPECIAL_NAN = 2
    BLOSC2_SPECIAL_VALUE = 3
    BLOSC2_SPECIAL_UNINIT = 4
    BLOSC2_SPECIAL_LASTID = 4
    BLOSC2_SPECIAL_MASK = 7
end

@cenum var"##Ctag#279"::Int32 begin
    BLOSC2_ERROR_SUCCESS = 0
    BLOSC2_ERROR_FAILURE = -1
    BLOSC2_ERROR_STREAM = 2
    BLOSC2_ERROR_DATA = -3
    BLOSC2_ERROR_MEMORY_ALLOC = -4
    BLOSC2_ERROR_READ_BUFFER = -5
    BLOSC2_ERROR_WRITE_BUFFER = -6
    BLOSC2_ERROR_CODEC_SUPPORT = -7
    BLOSC2_ERROR_CODEC_PARAM = -8
    BLOSC2_ERROR_CODEC_DICT = -9
    BLOSC2_ERROR_VERSION_SUPPORT = -10
    BLOSC2_ERROR_INVALID_HEADER = -11
    BLOSC2_ERROR_INVALID_PARAM = -12
    BLOSC2_ERROR_FILE_READ = -13
    BLOSC2_ERROR_FILE_WRITE = -14
    BLOSC2_ERROR_FILE_OPEN = -15
    BLOSC2_ERROR_NOT_FOUND = -16
    BLOSC2_ERROR_RUN_LENGTH = -17
    BLOSC2_ERROR_FILTER_PIPELINE = -18
    BLOSC2_ERROR_CHUNK_INSERT = -19
    BLOSC2_ERROR_CHUNK_APPEND = -20
    BLOSC2_ERROR_CHUNK_UPDATE = -21
    BLOSC2_ERROR_2GB_LIMIT = -22
    BLOSC2_ERROR_SCHUNK_COPY = -23
    BLOSC2_ERROR_FRAME_TYPE = -24
    BLOSC2_ERROR_FILE_TRUNCATE = -25
    BLOSC2_ERROR_THREAD_CREATE = -26
    BLOSC2_ERROR_POSTFILTER = -27
    BLOSC2_ERROR_FRAME_SPECIAL = -28
    BLOSC2_ERROR_SCHUNK_SPECIAL = -29
    BLOSC2_ERROR_PLUGIN_IO = -30
    BLOSC2_ERROR_FILE_REMOVE = -31
end

function blosc_init()
    @ccall libblosc2.blosc_init()::Cvoid
end

function blosc_destroy()
    @ccall libblosc2.blosc_destroy()::Cvoid
end

function blosc_compress(clevel, doshuffle, typesize, nbytes, src, dest, destsize)
    @ccall libblosc2.blosc_compress(clevel::Cint, doshuffle::Cint, typesize::Csize_t, nbytes::Csize_t, src::Ptr{Cvoid}, dest::Ptr{Cvoid}, destsize::Csize_t)::Cint
end

function blosc_decompress(src, dest, destsize)
    @ccall libblosc2.blosc_decompress(src::Ptr{Cvoid}, dest::Ptr{Cvoid}, destsize::Csize_t)::Cint
end

function blosc_getitem(src, start, nitems, dest)
    @ccall libblosc2.blosc_getitem(src::Ptr{Cvoid}, start::Cint, nitems::Cint, dest::Ptr{Cvoid})::Cint
end

function blosc2_getitem(src, srcsize, start, nitems, dest, destsize)
    @ccall libblosc2.blosc2_getitem(src::Ptr{Cvoid}, srcsize::Int32, start::Cint, nitems::Cint, dest::Ptr{Cvoid}, destsize::Int32)::Cint
end

# typedef void ( * blosc_threads_callback ) ( void * callback_data , void ( * dojob ) ( void * ) , int numjobs , size_t jobdata_elsize , void * jobdata )
const blosc_threads_callback = Ptr{Cvoid}

function blosc_set_threads_callback(callback, callback_data)
    @ccall libblosc2.blosc_set_threads_callback(callback::blosc_threads_callback, callback_data::Ptr{Cvoid})::Cvoid
end

function blosc_get_nthreads()
    @ccall libblosc2.blosc_get_nthreads()::Cint
end

function blosc_set_nthreads(nthreads)
    @ccall libblosc2.blosc_set_nthreads(nthreads::Cint)::Cint
end

function blosc_get_compressor()
    @ccall libblosc2.blosc_get_compressor()::Cstring
end

function blosc_set_compressor(compname)
    @ccall libblosc2.blosc_set_compressor(compname::Cstring)::Cint
end

function blosc_set_delta(dodelta)
    @ccall libblosc2.blosc_set_delta(dodelta::Cint)::Cvoid
end

function blosc_compcode_to_compname(compcode, compname)
    @ccall libblosc2.blosc_compcode_to_compname(compcode::Cint, compname::Ptr{Cstring})::Cint
end

function blosc_compname_to_compcode(compname)
    @ccall libblosc2.blosc_compname_to_compcode(compname::Cstring)::Cint
end

function blosc_list_compressors()
    @ccall libblosc2.blosc_list_compressors()::Cstring
end

function blosc_get_version_string()
    @ccall libblosc2.blosc_get_version_string()::Cstring
end

function blosc_get_complib_info(compname, complib, version)
    @ccall libblosc2.blosc_get_complib_info(compname::Cstring, complib::Ptr{Cstring}, version::Ptr{Cstring})::Cint
end

function blosc_free_resources()
    @ccall libblosc2.blosc_free_resources()::Cint
end

function blosc_cbuffer_sizes(cbuffer, nbytes, cbytes, blocksize)
    @ccall libblosc2.blosc_cbuffer_sizes(cbuffer::Ptr{Cvoid}, nbytes::Ptr{Csize_t}, cbytes::Ptr{Csize_t}, blocksize::Ptr{Csize_t})::Cvoid
end

function blosc2_cbuffer_sizes(cbuffer, nbytes, cbytes, blocksize)
    @ccall libblosc2.blosc2_cbuffer_sizes(cbuffer::Ptr{Cvoid}, nbytes::Ptr{Int32}, cbytes::Ptr{Int32}, blocksize::Ptr{Int32})::Cint
end

function blosc_cbuffer_validate(cbuffer, cbytes, nbytes)
    @ccall libblosc2.blosc_cbuffer_validate(cbuffer::Ptr{Cvoid}, cbytes::Csize_t, nbytes::Ptr{Csize_t})::Cint
end

function blosc_cbuffer_metainfo(cbuffer, typesize, flags)
    @ccall libblosc2.blosc_cbuffer_metainfo(cbuffer::Ptr{Cvoid}, typesize::Ptr{Csize_t}, flags::Ptr{Cint})::Cvoid
end

function blosc_cbuffer_versions(cbuffer, version, versionlz)
    @ccall libblosc2.blosc_cbuffer_versions(cbuffer::Ptr{Cvoid}, version::Ptr{Cint}, versionlz::Ptr{Cint})::Cvoid
end

function blosc_cbuffer_complib(cbuffer)
    @ccall libblosc2.blosc_cbuffer_complib(cbuffer::Ptr{Cvoid})::Cstring
end

@cenum var"##Ctag#280"::UInt32 begin
    BLOSC2_IO_FILESYSTEM = 0
    BLOSC_IO_LAST_BLOSC_DEFINED = 1
    BLOSC_IO_LAST_REGISTERED = 32
end

@cenum var"##Ctag#281"::UInt32 begin
    BLOSC2_IO_BLOSC_DEFINED = 32
    BLOSC2_IO_REGISTERED = 160
    BLOSC2_IO_USER_DEFINED = 256
end

# typedef void * ( * blosc2_open_cb ) ( const char * urlpath , const char * mode , void * params )
const blosc2_open_cb = Ptr{Cvoid}

# typedef int ( * blosc2_close_cb ) ( void * stream )
const blosc2_close_cb = Ptr{Cvoid}

# typedef int64_t ( * blosc2_tell_cb ) ( void * stream )
const blosc2_tell_cb = Ptr{Cvoid}

# typedef int ( * blosc2_seek_cb ) ( void * stream , int64_t offset , int whence )
const blosc2_seek_cb = Ptr{Cvoid}

# typedef int64_t ( * blosc2_write_cb ) ( const void * ptr , int64_t size , int64_t nitems , void * stream )
const blosc2_write_cb = Ptr{Cvoid}

# typedef int64_t ( * blosc2_read_cb ) ( void * ptr , int64_t size , int64_t nitems , void * stream )
const blosc2_read_cb = Ptr{Cvoid}

# typedef int64_t ( * blosc2_truncate_cb ) ( void * stream , int64_t size )
const blosc2_truncate_cb = Ptr{Cvoid}

struct blosc2_io_cb
    id::UInt8
    open::blosc2_open_cb
    close::blosc2_close_cb
    tell::blosc2_tell_cb
    seek::blosc2_seek_cb
    write::blosc2_write_cb
    read::blosc2_read_cb
    truncate::blosc2_truncate_cb
end

struct blosc2_io
    id::UInt8
    params::Ptr{Cvoid}
end

function blosc2_register_io_cb(io)
    @ccall libblosc2.blosc2_register_io_cb(io::Ptr{blosc2_io_cb})::Cint
end

function blosc2_get_io_cb(id)
    @ccall libblosc2.blosc2_get_io_cb(id::UInt8)::Ptr{blosc2_io_cb}
end

mutable struct blosc2_context_s end

const blosc2_context = blosc2_context_s

struct blosc2_btune
    btune_init::Ptr{Cvoid}
    btune_next_blocksize::Ptr{Cvoid}
    btune_next_cparams::Ptr{Cvoid}
    btune_update::Ptr{Cvoid}
    btune_free::Ptr{Cvoid}
    btune_config::Ptr{Cvoid}
end

struct blosc2_prefilter_params
    user_data::Ptr{Cvoid}
    in::Ptr{UInt8}
    out::Ptr{UInt8}
    out_size::Int32
    out_typesize::Int32
    out_offset::Int32
    tid::Int32
    ttmp::Ptr{UInt8}
    ttmp_nbytes::Csize_t
    ctx::Ptr{blosc2_context}
end

struct blosc2_postfilter_params
    user_data::Ptr{Cvoid}
    in::Ptr{UInt8}
    out::Ptr{UInt8}
    size::Int32
    typesize::Int32
    offset::Int32
    tid::Int32
    ttmp::Ptr{UInt8}
    ttmp_nbytes::Csize_t
    ctx::Ptr{blosc2_context}
end

# typedef int ( * blosc2_prefilter_fn ) ( blosc2_prefilter_params * params )
const blosc2_prefilter_fn = Ptr{Cvoid}

# typedef int ( * blosc2_postfilter_fn ) ( blosc2_postfilter_params * params )
const blosc2_postfilter_fn = Ptr{Cvoid}

struct blosc2_cparams
    compcode::UInt8
    compcode_meta::UInt8
    clevel::UInt8
    use_dict::Cint
    typesize::Int32
    nthreads::Int16
    blocksize::Int32
    splitmode::Int32
    schunk::Ptr{Cvoid}
    filters::NTuple{6, UInt8}
    filters_meta::NTuple{6, UInt8}
    prefilter::blosc2_prefilter_fn
    preparams::Ptr{blosc2_prefilter_params}
    udbtune::Ptr{blosc2_btune}
end

function Base.getproperty(x::Ptr{blosc2_cparams}, f::Symbol)
    f === :compcode && return Ptr{UInt8}(x + 0)
    f === :compcode_meta && return Ptr{UInt8}(x + 1)
    f === :clevel && return Ptr{UInt8}(x + 2)
    f === :use_dict && return Ptr{Cint}(x + 4)
    f === :typesize && return Ptr{Int32}(x + 8)
    f === :nthreads && return Ptr{Int16}(x + 12)
    f === :blocksize && return Ptr{Int32}(x + 16)
    f === :splitmode && return Ptr{Int32}(x + 20)
    f === :schunk && return Ptr{Ptr{Cvoid}}(x + 24)
    f === :filters && return Ptr{NTuple{6, UInt8}}(x + 32)
    f === :filters_meta && return Ptr{NTuple{6, UInt8}}(x + 38)
    f === :prefilter && return Ptr{blosc2_prefilter_fn}(x + 48)
    f === :preparams && return Ptr{Ptr{blosc2_prefilter_params}}(x + 56)
    f === :udbtune && return Ptr{Ptr{blosc2_btune}}(x + 64)
    return getfield(x, f)
end

function Base.setproperty!(x::Ptr{blosc2_cparams}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

struct blosc2_dparams
    nthreads::Cint
    schunk::Ptr{Cvoid}
    postfilter::blosc2_postfilter_fn
    postparams::Ptr{blosc2_postfilter_params}
end

function Base.getproperty(x::Ptr{blosc2_dparams}, f::Symbol)
    f === :nthreads && return Ptr{Cint}(x + 0)
    f === :schunk && return Ptr{Ptr{Cvoid}}(x + 8)
    f === :postfilter && return Ptr{blosc2_postfilter_fn}(x + 16)
    f === :postparams && return Ptr{Ptr{blosc2_postfilter_params}}(x + 24)
    return getfield(x, f)
end

function Base.setproperty!(x::Ptr{blosc2_dparams}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

function blosc2_create_cctx(cparams)
    @ccall libblosc2.blosc2_create_cctx(cparams::blosc2_cparams)::Ptr{blosc2_context}
end

function blosc2_create_dctx(dparams)
    @ccall libblosc2.blosc2_create_dctx(dparams::blosc2_dparams)::Ptr{blosc2_context}
end

function blosc2_free_ctx(context)
    @ccall libblosc2.blosc2_free_ctx(context::Ptr{blosc2_context})::Cvoid
end

function blosc2_ctx_get_cparams(ctx, cparams)
    @ccall libblosc2.blosc2_ctx_get_cparams(ctx::Ptr{blosc2_context}, cparams::Ptr{blosc2_cparams})::Cint
end

function blosc2_ctx_get_dparams(ctx, dparams)
    @ccall libblosc2.blosc2_ctx_get_dparams(ctx::Ptr{blosc2_context}, dparams::Ptr{blosc2_dparams})::Cint
end

function blosc2_set_maskout(ctx, maskout, nblocks)
    @ccall libblosc2.blosc2_set_maskout(ctx::Ptr{blosc2_context}, maskout::Ptr{Bool}, nblocks::Cint)::Cint
end

function blosc2_compress(clevel, doshuffle, typesize, src, srcsize, dest, destsize)
    @ccall libblosc2.blosc2_compress(clevel::Cint, doshuffle::Cint, typesize::Int32, src::Ptr{Cvoid}, srcsize::Int32, dest::Ptr{Cvoid}, destsize::Int32)::Cint
end

function blosc2_decompress(src, srcsize, dest, destsize)
    @ccall libblosc2.blosc2_decompress(src::Ptr{Cvoid}, srcsize::Int32, dest::Ptr{Cvoid}, destsize::Int32)::Cint
end

function blosc2_compress_ctx(context, src, srcsize, dest, destsize)
    @ccall libblosc2.blosc2_compress_ctx(context::Ptr{blosc2_context}, src::Ptr{Cvoid}, srcsize::Int32, dest::Ptr{Cvoid}, destsize::Int32)::Cint
end

function blosc2_decompress_ctx(context, src, srcsize, dest, destsize)
    @ccall libblosc2.blosc2_decompress_ctx(context::Ptr{blosc2_context}, src::Ptr{Cvoid}, srcsize::Int32, dest::Ptr{Cvoid}, destsize::Int32)::Cint
end

function blosc2_chunk_zeros(cparams, nbytes, dest, destsize)
    @ccall libblosc2.blosc2_chunk_zeros(cparams::blosc2_cparams, nbytes::Csize_t, dest::Ptr{Cvoid}, destsize::Csize_t)::Cint
end

function blosc2_chunk_nans(cparams, nbytes, dest, destsize)
    @ccall libblosc2.blosc2_chunk_nans(cparams::blosc2_cparams, nbytes::Csize_t, dest::Ptr{Cvoid}, destsize::Csize_t)::Cint
end

function blosc2_chunk_repeatval(cparams, nbytes, dest, destsize, repeatval)
    @ccall libblosc2.blosc2_chunk_repeatval(cparams::blosc2_cparams, nbytes::Csize_t, dest::Ptr{Cvoid}, destsize::Csize_t, repeatval::Ptr{Cvoid})::Cint
end

function blosc2_chunk_uninit(cparams, nbytes, dest, destsize)
    @ccall libblosc2.blosc2_chunk_uninit(cparams::blosc2_cparams, nbytes::Csize_t, dest::Ptr{Cvoid}, destsize::Csize_t)::Cint
end

function blosc2_getitem_ctx(context, src, srcsize, start, nitems, dest, destsize)
    @ccall libblosc2.blosc2_getitem_ctx(context::Ptr{blosc2_context}, src::Ptr{Cvoid}, srcsize::Int32, start::Cint, nitems::Cint, dest::Ptr{Cvoid}, destsize::Int32)::Cint
end

struct blosc2_storage
    contiguous::Bool
    urlpath::Cstring
    cparams::Ptr{blosc2_cparams}
    dparams::Ptr{blosc2_dparams}
    io::Ptr{blosc2_io}
end

function Base.getproperty(x::Ptr{blosc2_storage}, f::Symbol)
    f === :contiguous && return Ptr{Bool}(x + 0)
    f === :urlpath && return Ptr{Cstring}(x + 8)
    f === :cparams && return Ptr{Ptr{blosc2_cparams}}(x + 16)
    f === :dparams && return Ptr{Ptr{blosc2_dparams}}(x + 24)
    f === :io && return Ptr{Ptr{blosc2_io}}(x + 32)
    return getfield(x, f)
end

function Base.setproperty!(x::Ptr{blosc2_storage}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

mutable struct blosc2_frame_s end

const blosc2_frame = blosc2_frame_s

struct blosc2_metalayer
    name::Cstring
    content::Ptr{UInt8}
    content_len::Int32
end

function Base.getproperty(x::Ptr{blosc2_metalayer}, f::Symbol)
    f === :name && return Ptr{Cstring}(x + 0)
    f === :content && return Ptr{Ptr{UInt8}}(x + 8)
    f === :content_len && return Ptr{Int32}(x + 16)
    return getfield(x, f)
end

function Base.setproperty!(x::Ptr{blosc2_metalayer}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

struct blosc2_schunk
    version::UInt8
    compcode::UInt8
    compcode_meta::UInt8
    clevel::UInt8
    typesize::Int32
    blocksize::Int32
    chunksize::Int32
    filters::NTuple{6, UInt8}
    filters_meta::NTuple{6, UInt8}
    nchunks::Int32
    nbytes::Int64
    cbytes::Int64
    data::Ptr{Ptr{UInt8}}
    data_len::Csize_t
    storage::Ptr{blosc2_storage}
    frame::Ptr{blosc2_frame}
    cctx::Ptr{blosc2_context}
    dctx::Ptr{blosc2_context}
    metalayers::NTuple{16, Ptr{blosc2_metalayer}}
    nmetalayers::Int16
    vlmetalayers::NTuple{8192, Ptr{blosc2_metalayer}}
    nvlmetalayers::Int16
    udbtune::Ptr{blosc2_btune}
end

function Base.getproperty(x::Ptr{blosc2_schunk}, f::Symbol)
    f === :version && return Ptr{UInt8}(x + 0)
    f === :compcode && return Ptr{UInt8}(x + 1)
    f === :compcode_meta && return Ptr{UInt8}(x + 2)
    f === :clevel && return Ptr{UInt8}(x + 3)
    f === :typesize && return Ptr{Int32}(x + 4)
    f === :blocksize && return Ptr{Int32}(x + 8)
    f === :chunksize && return Ptr{Int32}(x + 12)
    f === :filters && return Ptr{NTuple{6, UInt8}}(x + 16)
    f === :filters_meta && return Ptr{NTuple{6, UInt8}}(x + 22)
    f === :nchunks && return Ptr{Int32}(x + 28)
    f === :nbytes && return Ptr{Int64}(x + 32)
    f === :cbytes && return Ptr{Int64}(x + 40)
    f === :data && return Ptr{Ptr{Ptr{UInt8}}}(x + 48)
    f === :data_len && return Ptr{Csize_t}(x + 56)
    f === :storage && return Ptr{Ptr{blosc2_storage}}(x + 64)
    f === :frame && return Ptr{Ptr{blosc2_frame}}(x + 72)
    f === :cctx && return Ptr{Ptr{blosc2_context}}(x + 80)
    f === :dctx && return Ptr{Ptr{blosc2_context}}(x + 88)
    f === :metalayers && return Ptr{NTuple{16, Ptr{blosc2_metalayer}}}(x + 96)
    f === :nmetalayers && return Ptr{Int16}(x + 224)
    f === :vlmetalayers && return Ptr{NTuple{8192, Ptr{blosc2_metalayer}}}(x + 232)
    f === :nvlmetalayers && return Ptr{Int16}(x + 65768)
    f === :udbtune && return Ptr{Ptr{blosc2_btune}}(x + 65776)
    return getfield(x, f)
end

function Base.setproperty!(x::Ptr{blosc2_schunk}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

function blosc2_schunk_new(storage)
    @ccall libblosc2.blosc2_schunk_new(storage::Ptr{blosc2_storage})::Ptr{blosc2_schunk}
end

function blosc2_schunk_copy(schunk, storage)
    @ccall libblosc2.blosc2_schunk_copy(schunk::Ptr{blosc2_schunk}, storage::Ptr{blosc2_storage})::Ptr{blosc2_schunk}
end

function blosc2_schunk_from_buffer(cframe, len, copy)
    @ccall libblosc2.blosc2_schunk_from_buffer(cframe::Ptr{UInt8}, len::Int64, copy::Bool)::Ptr{blosc2_schunk}
end

function blosc2_schunk_open(urlpath)
    @ccall libblosc2.blosc2_schunk_open(urlpath::Cstring)::Ptr{blosc2_schunk}
end

function blosc2_schunk_open_udio(urlpath, udio)
    @ccall libblosc2.blosc2_schunk_open_udio(urlpath::Cstring, udio::Ptr{blosc2_io})::Ptr{blosc2_schunk}
end

function blosc2_schunk_to_buffer(schunk, cframe, needs_free)
    @ccall libblosc2.blosc2_schunk_to_buffer(schunk::Ptr{blosc2_schunk}, cframe::Ptr{Ptr{UInt8}}, needs_free::Ptr{Bool})::Int64
end

function blosc2_schunk_to_file(schunk, urlpath)
    @ccall libblosc2.blosc2_schunk_to_file(schunk::Ptr{blosc2_schunk}, urlpath::Cstring)::Int64
end

function blosc2_schunk_free(schunk)
    @ccall libblosc2.blosc2_schunk_free(schunk::Ptr{blosc2_schunk})::Cint
end

function blosc2_schunk_append_chunk(schunk, chunk, copy)
    @ccall libblosc2.blosc2_schunk_append_chunk(schunk::Ptr{blosc2_schunk}, chunk::Ptr{UInt8}, copy::Bool)::Cint
end

function blosc2_schunk_update_chunk(schunk, nchunk, chunk, copy)
    @ccall libblosc2.blosc2_schunk_update_chunk(schunk::Ptr{blosc2_schunk}, nchunk::Cint, chunk::Ptr{UInt8}, copy::Bool)::Cint
end

function blosc2_schunk_insert_chunk(schunk, nchunk, chunk, copy)
    @ccall libblosc2.blosc2_schunk_insert_chunk(schunk::Ptr{blosc2_schunk}, nchunk::Cint, chunk::Ptr{UInt8}, copy::Bool)::Cint
end

function blosc2_schunk_delete_chunk(schunk, nchunk)
    @ccall libblosc2.blosc2_schunk_delete_chunk(schunk::Ptr{blosc2_schunk}, nchunk::Cint)::Cint
end

function blosc2_schunk_append_buffer(schunk, src, nbytes)
    @ccall libblosc2.blosc2_schunk_append_buffer(schunk::Ptr{blosc2_schunk}, src::Ptr{Cvoid}, nbytes::Int32)::Cint
end

function blosc2_schunk_decompress_chunk(schunk, nchunk, dest, nbytes)
    @ccall libblosc2.blosc2_schunk_decompress_chunk(schunk::Ptr{blosc2_schunk}, nchunk::Cint, dest::Ptr{Cvoid}, nbytes::Int32)::Cint
end

function blosc2_schunk_get_chunk(schunk, nchunk, chunk, needs_free)
    @ccall libblosc2.blosc2_schunk_get_chunk(schunk::Ptr{blosc2_schunk}, nchunk::Cint, chunk::Ptr{Ptr{UInt8}}, needs_free::Ptr{Bool})::Cint
end

function blosc2_schunk_get_lazychunk(schunk, nchunk, chunk, needs_free)
    @ccall libblosc2.blosc2_schunk_get_lazychunk(schunk::Ptr{blosc2_schunk}, nchunk::Cint, chunk::Ptr{Ptr{UInt8}}, needs_free::Ptr{Bool})::Cint
end

function blosc2_schunk_get_cparams(schunk, cparams)
    @ccall libblosc2.blosc2_schunk_get_cparams(schunk::Ptr{blosc2_schunk}, cparams::Ptr{Ptr{blosc2_cparams}})::Cint
end

function blosc2_schunk_get_dparams(schunk, dparams)
    @ccall libblosc2.blosc2_schunk_get_dparams(schunk::Ptr{blosc2_schunk}, dparams::Ptr{Ptr{blosc2_dparams}})::Cint
end

function blosc2_schunk_reorder_offsets(schunk, offsets_order)
    @ccall libblosc2.blosc2_schunk_reorder_offsets(schunk::Ptr{blosc2_schunk}, offsets_order::Ptr{Cint})::Cint
end

function blosc2_schunk_frame_len(schunk)
    @ccall libblosc2.blosc2_schunk_frame_len(schunk::Ptr{blosc2_schunk})::Int64
end

function blosc2_schunk_fill_special(schunk, nitems, special_value, chunksize)
    @ccall libblosc2.blosc2_schunk_fill_special(schunk::Ptr{blosc2_schunk}, nitems::Int64, special_value::Cint, chunksize::Int32)::Cint
end

function blosc2_meta_exists(schunk, name)
    @ccall libblosc2.blosc2_meta_exists(schunk::Ptr{blosc2_schunk}, name::Cstring)::Cint
end

function blosc2_meta_add(schunk, name, content, content_len)
    @ccall libblosc2.blosc2_meta_add(schunk::Ptr{blosc2_schunk}, name::Cstring, content::Ptr{UInt8}, content_len::UInt32)::Cint
end

function blosc2_meta_update(schunk, name, content, content_len)
    @ccall libblosc2.blosc2_meta_update(schunk::Ptr{blosc2_schunk}, name::Cstring, content::Ptr{UInt8}, content_len::UInt32)::Cint
end

function blosc2_meta_get(schunk, name, content, content_len)
    @ccall libblosc2.blosc2_meta_get(schunk::Ptr{blosc2_schunk}, name::Cstring, content::Ptr{Ptr{UInt8}}, content_len::Ptr{UInt32})::Cint
end

function blosc2_vlmeta_exists(schunk, name)
    @ccall libblosc2.blosc2_vlmeta_exists(schunk::Ptr{blosc2_schunk}, name::Cstring)::Cint
end

function blosc2_vlmeta_add(schunk, name, content, content_len, cparams)
    @ccall libblosc2.blosc2_vlmeta_add(schunk::Ptr{blosc2_schunk}, name::Cstring, content::Ptr{UInt8}, content_len::UInt32, cparams::Ptr{blosc2_cparams})::Cint
end

function blosc2_vlmeta_update(schunk, name, content, content_len, cparams)
    @ccall libblosc2.blosc2_vlmeta_update(schunk::Ptr{blosc2_schunk}, name::Cstring, content::Ptr{UInt8}, content_len::UInt32, cparams::Ptr{blosc2_cparams})::Cint
end

function blosc2_vlmeta_get(schunk, name, content, content_len)
    @ccall libblosc2.blosc2_vlmeta_get(schunk::Ptr{blosc2_schunk}, name::Cstring, content::Ptr{Ptr{UInt8}}, content_len::Ptr{UInt32})::Cint
end

function blosc_set_timestamp(timestamp)
    @ccall libblosc2.blosc_set_timestamp(timestamp::Ptr{timespec})::Cvoid
end

function blosc_elapsed_nsecs(start_time, end_time)
    @ccall libblosc2.blosc_elapsed_nsecs(start_time::timespec, end_time::timespec)::Cdouble
end

function blosc_elapsed_secs(start_time, end_time)
    @ccall libblosc2.blosc_elapsed_secs(start_time::timespec, end_time::timespec)::Cdouble
end

function blosc_get_blocksize()
    @ccall libblosc2.blosc_get_blocksize()::Cint
end

function blosc_set_blocksize(blocksize)
    @ccall libblosc2.blosc_set_blocksize(blocksize::Csize_t)::Cvoid
end

function blosc_set_schunk(schunk)
    @ccall libblosc2.blosc_set_schunk(schunk::Ptr{blosc2_schunk})::Cvoid
end

# typedef int ( * blosc2_codec_encoder_cb ) ( const uint8_t * input , int32_t input_len , uint8_t * output , int32_t output_len , uint8_t meta , blosc2_cparams * cparams )
const blosc2_codec_encoder_cb = Ptr{Cvoid}

# typedef int ( * blosc2_codec_decoder_cb ) ( const uint8_t * input , int32_t input_len , uint8_t * output , int32_t output_len , uint8_t meta , blosc2_dparams * dparams )
const blosc2_codec_decoder_cb = Ptr{Cvoid}

struct blosc2_codec
    compcode::UInt8
    compname::Cstring
    complib::UInt8
    compver::UInt8
    encoder::blosc2_codec_encoder_cb
    decoder::blosc2_codec_decoder_cb
end

function blosc2_register_codec(codec)
    @ccall libblosc2.blosc2_register_codec(codec::Ptr{blosc2_codec})::Cint
end

# typedef int ( * blosc2_filter_forward_cb ) ( const uint8_t * , uint8_t * , int32_t , uint8_t , blosc2_cparams * )
const blosc2_filter_forward_cb = Ptr{Cvoid}

# typedef int ( * blosc2_filter_backward_cb ) ( const uint8_t * , uint8_t * , int32_t , uint8_t , blosc2_dparams * )
const blosc2_filter_backward_cb = Ptr{Cvoid}

struct blosc2_filter
    id::UInt8
    forward::blosc2_filter_forward_cb
    backward::blosc2_filter_backward_cb
end

function blosc2_register_filter(filter)
    @ccall libblosc2.blosc2_register_filter(filter::Ptr{blosc2_filter})::Cint
end

function blosc2_remove_dir(path)
    @ccall libblosc2.blosc2_remove_dir(path::Cstring)::Cint
end

# Skipping MacroDefinition: BLOSC_NO_EXPORT __attribute__ ( ( visibility ( "hidden" ) ) )

# Skipping MacroDefinition: BLOSC_UNUSED_VAR __attribute__ ( ( unused ) )

const BLOSC_VERSION_MAJOR = 2

const BLOSC_VERSION_MINOR = 0

const BLOSC_VERSION_RELEASE = 1

const BLOSC_VERSION_STRING = "2.0.1"

const BLOSC_VERSION_DATE = "\$Date:: 2021-06-29 #\$"

const BLOSC_BLOSCLZ_COMPNAME = "blosclz"

const BLOSC_LZ4_COMPNAME = "lz4"

const BLOSC_LZ4HC_COMPNAME = "lz4hc"

const BLOSC_ZLIB_COMPNAME = "zlib"

const BLOSC_ZSTD_COMPNAME = "zstd"

const BLOSC_BLOSCLZ_LIBNAME = "BloscLZ"

const BLOSC_LZ4_LIBNAME = "LZ4"

const BLOSC_ZLIB_LIBNAME = "Zlib"

const BLOSC_ZSTD_LIBNAME = "Zstd"

const BLOSC2_MAX_METALAYERS = 16

const BLOSC2_METALAYER_NAME_MAXLEN = 31

const BLOSC2_MAX_VLMETALAYERS = 8 * 1024

const BLOSC2_VLMETALAYERS_NAME_MAXLEN = BLOSC2_METALAYER_NAME_MAXLEN

# Skipping MacroDefinition: blosc_timestamp_t struct timespec


text:
@testset "compute_laplace_eig.jl" begin

end

ext: jl


text:
export awa

"""
    awa(twa, v_s, v_t)

Calculate the apparent wind angle given true wind angle, boat speed and wind speed.

# Example

```jldoctest
using sail_route
c_awa = sail_route.awa(60, 3.086, 5.144)
isapprox(0.6669807044553968, c_awa, rtol=3)

# output

true
```
"""
function awa(twa::Float64, v_s::Float64, v_t::Float64)
    return atan(sind(twa)/(cosd(twa) + v_s/v_t))
end


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

using Markdown
using InteractiveUtils

# ╔═╡ 6fd616f6-1ea1-11eb-3814-8bfb4a096c49
using Pkg, DrWatson

# ╔═╡ 6ffe2628-1ea1-11eb-24ea-57f985146a72
begin
	@quickactivate "StatisticsWithJuliaPlutoNotebooks"
	using Random, StatsBase, DataFrames, Plots
	Random.seed!(1)
end;

# ╔═╡ ed174bc4-1ea0-11eb-1e2f-a32874cec549
md"## Listing 3.1"

# ╔═╡ e4591176-1eca-11eb-1e04-15ae5da7dbb0

# ╔═╡ 70179b62-1ea1-11eb-13ce-7fb4d54bad4b
begin
	names = ["Mary","Mel","David","John","Kayley","Anderson"]
	randomName() = rand(names)
	X = 3:8
	N = 10^6
	sampleLengths = [length(randomName()) for _ in 1:N]
end;

# ╔═╡ 6c3d1d9e-1f6b-11eb-3d29-3d9260020721
bar(X,counts(sampleLengths)/N, ylims=(0,0.35),
    xlabel="Name length", ylabel="Estimated p(x)", legend=:none)

# ╔═╡ 70182cd8-1ea1-11eb-094d-8d0d49cf15f3
md"## End of listing 3.1"

# ╔═╡ Cell order:
# ╟─ed174bc4-1ea0-11eb-1e2f-a32874cec549
# ╠═6fd616f6-1ea1-11eb-3814-8bfb4a096c49
# ╠═6ffe2628-1ea1-11eb-24ea-57f985146a72
# ╠═e4591176-1eca-11eb-1e04-15ae5da7dbb0
# ╠═70179b62-1ea1-11eb-13ce-7fb4d54bad4b
# ╠═6c3d1d9e-1f6b-11eb-3d29-3d9260020721
# ╟─70182cd8-1ea1-11eb-094d-8d0d49cf15f3


text:
using LambdaRuntime
using Test

@testset "LambdaRuntime.jl" begin
    # Write your tests here.
end


text:
function construct_inpTheta(X_test, X_domain, X_boundary, set_sigma)
    N_test = size(X_test)[1]
    N_domain = size(X_domain)[1]
    N_boundary = size(X_boundary)[1]
    inpTheta = zeros((N_test, 2*N_domain+N_boundary))
    for iter_i = 1:N_test
        for iter_j = 1:N_domain
            inpTheta[iter_i,iter_j] = Delta_x_kappa(X_test[iter_i,1],X_test[iter_i,2],X_domain[iter_j,1],X_domain[iter_j,2],set_sigma)
        end
        for iter_j = N_domain+1:2*N_domain
            inpTheta[iter_i,iter_j] = kappa(X_test[iter_i,1],X_test[iter_i,2],X_domain[iter_j-N_domain,1],X_domain[iter_j-N_domain,2],set_sigma)
        end
        for iter_j = 2*N_domain+1:2*N_domain+N_boundary
            inpTheta[iter_i,iter_j] = kappa(X_test[iter_i,1],X_test[iter_i,2],X_boundary[iter_j-2*N_domain,1],X_boundary[iter_j-2*N_domain,2],set_sigma)
        end
    end
    return inpTheta
end

function extend_solution(X_test, X_domain, X_boundary, L, v, set_sigma)
    inp_Theta = construct_inpTheta(X_test, X_domain, X_boundary, set_sigma)
    return inp_Theta*(L'\(L\v))
end

function get_extended_solution(num_pts, X_domain, X_boundary, L, sol, set_sigma)
    x = range(0,1,length=num_pts)
    y = range(0,1,length=num_pts)
    xx = x' .* ones(num_pts)
    yy = ones(num_pts)' .* y

    xxv = Matrix{Float64}(reshape(xx,(num_pts^2,1)))
    yyv = Matrix{Float64}(reshape(yy,(num_pts^2,1)))

    X_test = hcat(xxv,yyv)

    N_domain = size(X_domain)[1]
    N_boundary = size(X_boundary)[1]
    rhs_f = zeros((N_domain,1))
    bdy_g = zeros((N_boundary,1))

    for iter_i = 1:N_domain
        rhs_f[iter_i] = f(X_domain[iter_i,1],X_domain[iter_i,2])
    end
    for iter_i = 1:N_boundary
        bdy_g[iter_i] = g(X_boundary[iter_i,1],X_boundary[iter_i,2])
    end

#     X_test=hcat([[x[i];y[j]] for i = 1 : num_pts for j = 1 : num_pts])
    temp_vec = [alpha*sol.^m-rhs_f; sol; bdy_g]
    u_extended = Matrix{Float64}(reshape(extend_solution(X_test, X_domain, X_boundary, L, temp_vec, set_sigma),(num_pts,num_pts)))
    return x, y, u_extended
end


text:
# include("../src/LarSurf.jl")
# include("../src/sampledata.jl")

using LarSurf
using Plasm
using LinearAlgebraicRepresentation
Lar = LinearAlgebraicRepresentation

verts, trifaces = LarSurf.hexagon()

V, EV, FE = LarSurf.to_lar(verts, trifaces)

Lar.view(V, EV)


text:
using BenchmarkTools
using CUDA
using DataDeps
using Oceananigans
using Benchmarks

# Need a grid

ENV["DATADEPS_ALWAYS_ACCEPT"] = "true"

dd = DataDep("cubed_sphere_510_grid",
    "Conformal cubed sphere grid with 510×510 grid points on each face",
    "https://engaging-web.mit.edu/~alir/cubed_sphere_grids/cs510/cubed_sphere_510_grid.jld2"
)

DataDeps.register(dd)

# Benchmark function

# All grids have 6 * 510^2 = 1,560,600 grid points.
grids = Dict(
     (CPU, :RegularRectilinearGrid)       => RegularRectilinearGrid(size=(1445, 1080, 1), extent=(1, 1, 1)),
     (CPU, :RegularLatitudeLongitudeGrid) => RegularLatitudeLongitudeGrid(size=(1445, 1080, 1), longitude=(-180, 180), latitude=(-80, 80), z=(-1, 0)),
     (CPU, :ConformalCubedSphereFaceGrid) => ConformalCubedSphereFaceGrid(size=(1445, 1080, 1), z=(-1, 0)),
     (CPU, :ConformalCubedSphereGrid)     => ConformalCubedSphereGrid(datadep"cubed_sphere_510_grid/cubed_sphere_510_grid.jld2", Nz=1, z=(-1, 0)),
     (GPU, :RegularRectilinearGrid)       => RegularRectilinearGrid(size=(1445, 1080, 1), extent=(1, 1, 1)),
     (GPU, :RegularLatitudeLongitudeGrid) => RegularLatitudeLongitudeGrid(size=(1445, 1080, 1), longitude=(-180, 180), latitude=(-80, 80), z=(-1, 0)),
     # Uncomment when ConformalCubedSphereFaceGrids of any size can be built natively without loading from file:
     # (GPU, :ConformalCubedSphereFaceGrid) => ConformalCubedSphereFaceGrid(size=(1445, 1080, 1), z=(-1, 0), architecture=GPU()),
     (GPU, :ConformalCubedSphereGrid)     => ConformalCubedSphereGrid(datadep"cubed_sphere_510_grid/cubed_sphere_510_grid.jld2", Nz=1, z=(-1, 0), architecture=GPU()),
)

free_surfaces = Dict(
    :ExplicitFreeSurface => ExplicitFreeSurface(),
    :ImplicitFreeSurface => ImplicitFreeSurface(maximum_iterations=1, tolerance=-Inf) # Force it to take exactly 1 iteration.
)

function benchmark_hydrostatic_model(Arch, grid_type, free_surface_type)

    model = HydrostaticFreeSurfaceModel(
              architecture = Arch(),
                      grid = grids[(Arch, grid_type)],
        momentum_advection = VectorInvariant(),
              free_surface = free_surfaces[free_surface_type]
    )

    time_step!(model, 1) # warmup

    trial = @benchmark begin
        CUDA.@sync blocking=true time_step!($model, 1)
    end samples=10

    return trial
end

# Benchmark parameters

Architectures = has_cuda() ? [CPU, GPU] : [CPU]

grid_types = [
    :RegularRectilinearGrid,
    :RegularLatitudeLongitudeGrid,
    # Uncomment when ConformalCubedSphereFaceGrids of any size can be built natively without loading from file:
    # :ConformalCubedSphereFaceGrid,
    :ConformalCubedSphereGrid
]

free_surface_types = [
    :ExplicitFreeSurface,
    # ImplicitFreeSurface doesn't yet work on MultiRegionGrids like the ConformalCubedSphereGrid:
    # :ImplicitFreeSurface
]

# Run and summarize benchmarks

print_system_info()
suite = run_benchmarks(benchmark_hydrostatic_model; Architectures, grid_types, free_surface_types)

df = benchmarks_dataframe(suite)
# sort!(df, [:Architectures, :Float_types, :Ns], by=(string, string, identity))
benchmarks_pretty_table(df, title="Hydrostatic model benchmarks")


text:
module ManifoldProjections
# Manifold interface: every manifold (subtype of Manifold) defines the functions
# project_tangent!(m, g, x): project g on the tangent space to m at x
# retract!(m, x): map x back to a point on the manifold m

# For mathematical references, see e.g.

# The Geometry of Algorithms with Orthogonality Constraints
# Alan Edelman, Tomás A. Arias, and Steven T. Smith
# SIAM. J. Matrix Anal. & Appl., 20(2), 303–353. (51 pages)

# Optimization Algorithms on Matrix Manifolds
# P.-A. Absil, R. Mahony, R. Sepulchre
# Princeton University Press, 2008

import NLSolversBase
using LinearAlgebra

abstract type Manifold
end

# fallback for out-of-place ops
retract(M::Manifold, x) = retract!(M, copy(x))
project_tangent(M::Manifold, g, x) = project_tangent!(M, copy(g), x)

# Fake objective function implementing a retraction
mutable struct ManifoldObjective{T<:NLSolversBase.AbstractObjective} <: NLSolversBase.AbstractObjective
    manifold::Manifold
    inner_obj::T
end
# TODO: is it safe here to call retract! and change x?
function NLSolversBase.value!(obj::ManifoldObjective, x)
    xin = retract(obj.manifold, x)
    value!(obj.inner_obj, xin)
end
function NLSolversBase.value(obj::ManifoldObjective)
    value(obj.inner_obj)
end
function NLSolversBase.gradient(obj::ManifoldObjective)
    gradient(obj.inner_obj)
end
function NLSolversBase.gradient(obj::ManifoldObjective,i::Int)
    gradient(obj.inner_obj,i)
end
function NLSolversBase.gradient!(obj::ManifoldObjective,x)
    xin = retract(obj.manifold, x)
    gradient!(obj.inner_obj,xin)
    project_tangent!(obj.manifold,gradient(obj.inner_obj),xin)
    return gradient(obj.inner_obj)
end
function NLSolversBase.value_gradient!(obj::ManifoldObjective,x)
    xin = retract(obj.manifold, x)
    value_gradient!(obj.inner_obj,xin)
    project_tangent!(obj.manifold,gradient(obj.inner_obj),xin)
    return value(obj.inner_obj)
end

"""Flat Euclidean space {R,C}^N, with projections equal to the identity."""
struct Flat <: Manifold
end
# all the functions below are no-ops, and therefore the generated code
# for the flat manifold should be exactly the same as the one with all
# the manifold stuff removed
retract(M::Flat, x) = x
retract!(M::Flat, x) = x
project_tangent(M::Flat, g, x) = g
project_tangent!(M::Flat, g, x) = g

"""Spherical manifold {||x|| = r}."""
struct Sphere{T} <: Manifold where {T <: Real}
    r::T
    Sphere(r::T) where {T <: Real} = r < 0 ? error("radius has to be a positive number!") : new{T}(r)
end
Sphere() = Sphere(1)
retract!(S::Sphere, x) = rmul!(x, S.r/norm(x))
project_tangent!(S::Sphere,g,x) = (g .-= (real(dot(x,g))/S.r^2).*x)

"""
N x n matrices with orthonormal columns, i.e. such that X'X = I.
Special cases: N x 1 = sphere, N x N = orthogonal/unitary group.
Stiefel() uses a SVD algorithm to compute the retraction. To use a Cholesky-based orthogonalization (faster but less stable), use Stiefel(:CholQR).
When the function to be optimized depends only on the subspace X*X' spanned by a point X in the Stiefel manifold, first-order optimization algorithms are equivalent for the Stiefel and Grassmann manifold, so there is no separate Grassmann manifold.
"""
abstract type Stiefel <: Manifold end
struct Stiefel_CholQR <: Stiefel end
struct Stiefel_SVD <: Stiefel end
function Stiefel(retraction=:SVD)
    if retraction == :CholQR
        Stiefel_CholQR()
    elseif retraction == :SVD
        Stiefel_SVD()
    end
end
function retract!(S::Stiefel_SVD, X)
    U,S,V = svd(X)
    X .= U*V'
end
function retract!(S::Stiefel_CholQR, X)
    overlap = X'X
    X .= X/cholesky(overlap).U
end
#For functions depending only on the subspace spanned by X, we always have G = A*X for some A, and so X'G = G'X, and Stiefel == Grassmann
#Edelman et al. have G .-= X*G'X (2.53), corresponding to a different metric ("canonical metric"). We follow Absil et al. here and use the metric inherited from Nxn matrices.
project_tangent!(S::Stiefel, G, X) = (XG = X'G; G .-= X*((XG .+ XG')./2))

"""
Multiple copies of the same manifold. Points are stored as inner_dims x outer_dims,
e.g. the product of 2x2 Stiefel manifolds of dimension N x n would be a N x n x 2 x 2 matrix.
"""
struct PowerManifold<:Manifold
    "Type of embedded manifold"
    inner_manifold::Manifold
    "Dimension of the embedded manifolds"
    inner_dims::Tuple
    "Number of embedded manifolds"
    outer_dims::Tuple
end
function retract!(m::PowerManifold, x)
    for i=1:prod(m.outer_dims) # TODO: use for i in LinearIndices(m.outer_dims)?
        retract!(m.inner_manifold,get_inner(m, x, i))
    end
    x
end
function project_tangent!(m::PowerManifold, g, x)
    for i=1:prod(m.outer_dims)
        project_tangent!(m.inner_manifold,get_inner(m, g, i),get_inner(m, x, i))
    end
    g
end
@inline function get_inner(m::PowerManifold, x, i::Int)
    size_inner = prod(m.inner_dims)
    size_outer = prod(m.outer_dims)
    @assert 1 <= i <= size_outer
    return reshape(view(x, (i-1)*size_inner+1:i*size_inner), m.inner_dims)
end

"""
Product of two manifolds {P = (x1,x2), x1 ∈ m1, x2 ∈ m2}.
P is stored as a flat 1D array, and x1 is before x2 in memory.
Use get_inner(m, x, {1,2}) to access x1 or x2 in their original format.
"""
struct ProductManifold<:Manifold
    m1::Manifold
    m2::Manifold
    dims1::Tuple
    dims2::Tuple
end
function retract!(m::ProductManifold, x)
    retract!(m.m1, get_inner(m,x,1))
    retract!(m.m2, get_inner(m,x,2))
    x
end
function project_tangent!(m::ProductManifold, g, x)
    project_tangent!(m.m1, get_inner(m, g, 1), get_inner(m, x, 1))
    project_tangent!(m.m2, get_inner(m, g, 2), get_inner(m, x, 2))
    g
end
function get_inner(m::ProductManifold, x, i::Integer)
    N1 = prod(m.dims1)
    N2 = prod(m.dims2)
    @assert length(x) == N1+N2
    if i == 1
        return reshape(view(x, 1:N1),m.dims1)
    elseif i == 2
        return reshape(view(x, N1+1:N1+N2), m.dims2)
    else
        error("Only two components in a product manifold")
    end
end

export Manifold,
    Flat, Sphere, Stiefel, Stiefel_CholQR, Stiefel_SVD, PowerManifold, ProductManifold,
    project_tangent, project_tangent!,
    retract, retract!,
    get_inner

end # module


text:
using Cerberus
using Gurobi
using MathOptInterface
using Test

const MOI = MathOptInterface
const MOIT = MOI.Test
const MOIU = MOI.Utilities

function _build_optimizer(
    warm_start_strategy::Cerberus.WarmStartStrategy,
    model_reuse_strategy::Cerberus.ModelReuseStrategy,
)
    return MOIU.CachingOptimizer(
        MOIU.UniversalFallback(MOIU.Model{Float64}()),
        begin
            model = Cerberus.Optimizer(Cerberus.AlgorithmConfig())
            model.config.lp_solver_factory =
                (state, config) -> (
                    begin
                        model = Gurobi.Optimizer(GRB_ENV)
                        MOI.set(model, MOI.Silent(), true)
                        MOI.set(model, MOI.RawParameter("DualReductions"), 0)
                        MOI.set(model, MOI.RawParameter("InfUnbdInfo"), 1)
                        return model
                    end
                )
            model.config.silent = true
            model.config.warm_start_strategy = warm_start_strategy
            model.config.model_reuse_strategy = model_reuse_strategy
            model
        end,
    )
end

const OPTIMIZER = _build_optimizer(
    Cerberus.WARM_START_WHENEVER_POSSIBLE,
    Cerberus.REUSE_MODEL_ON_DIVES,
)

const MOI_CONFIG = MOIT.TestConfig(
    modify_lhs = false,
    duals = false,
    dual_objective_value = false,
    infeas_certificates = false,
)

@testset "basic_constraint_tests" begin
    MOIT.basic_constraint_tests(
        OPTIMIZER,
        MOI_CONFIG,
        delete = false,
        # TODO: Add support for getting F/S
        get_constraint_function = false,
        get_constraint_set = false,
        include = [
            (_SV, _LT),
            (_SV, _GT),
            (_SV, _ET),
            (_SV, _IN),
            (_SV, _ZO),
            (_SV, _GI),
            (_SAF, _LT),
            (_SAF, _GT),
            (_SAF, _ET),
        ],
    )
end

@testset "unittest" begin
    MOIT.unittest(
        OPTIMIZER,
        MOI_CONFIG,
        [
            # Should add support for:
            "solve_result_index",

            # Can test with support for MOI.UNBOUNDED status:
            "solve_unbounded_model",

            # Can test with support for vectorized constraints:
            "solve_duplicate_terms_vector_affine",

            # Can test with bridge to SAF-in-Interval:
            "solve_affine_interval",

            # Will likely not support:
            "number_threads",
            "delete_variables",
            "delete_nonnegative_variables",
            "delete_soc_variables",
            "raw_status_string",
            "solve_farkas_interval_lower",
            "solve_farkas_interval_upper",
            "update_dimension_nonnegative_variables",
            "solve_qp_edge_cases",
            "solve_qcp_edge_cases",
            "solve_affine_deletion_edge_cases",
        ],
    )
end

@testset "default_objective" begin
    MOIT.default_objective_test(OPTIMIZER)
end

@testset "default_status" begin
    # Like MOIT.default_status_test, but doesn't test dual status
    @test MOI.get(OPTIMIZER, MOI.TerminationStatus()) == MOI.OPTIMIZE_NOT_CALLED
    @test MOI.get(OPTIMIZER, MOI.PrimalStatus()) == MOI.NO_SOLUTION
end

@testset "valid" begin
    MOIT.validtest(OPTIMIZER)
end

const MOIB = MOI.Bridges

function _build_bridged_optimizer(
    warm_start_strategy::Cerberus.WarmStartStrategy,
    model_reuse_strategy::Cerberus.ModelReuseStrategy,
)
    opt = _build_optimizer(warm_start_strategy, model_reuse_strategy)
    bridged_opt = MOIB.LazyBridgeOptimizer(opt)
    MOIB.add_bridge(bridged_opt, MOIB.Constraint.ScalarizeBridge{Float64})
    MOIB.add_bridge(bridged_opt, MOIB.Constraint.SemiToBinaryBridge{Float64})
    MOIB.add_bridge(bridged_opt, MOIB.Constraint.SplitIntervalBridge{Float64})
    MOIB.add_bridge(bridged_opt, MOIB.Variable.ZerosBridge{Float64})
    return bridged_opt
end

@testset "contlinear" begin
    MOIT.contlineartest(
        _build_bridged_optimizer(
            Cerberus.WARM_START_WHENEVER_POSSIBLE,
            Cerberus.REUSE_MODEL_ON_DIVES,
        ),
        MOI_CONFIG,
        [
            # Needs setting of VariablePrimalStart
            "partial_start",
        ],
    )
end

# TODO: Add bridges to support below sets
@testset "intlinear" begin
    for ws in (
            Cerberus.NO_WARM_STARTS,
            Cerberus.WARM_START_WHEN_BACKTRACKING,
            Cerberus.WARM_START_WHENEVER_POSSIBLE,
        ),
        mr in (
            Cerberus.NO_MODEL_REUSE,
            Cerberus.REUSE_MODEL_ON_DIVES,
            Cerberus.USE_SINGLE_MODEL,
        )

        MOIT.intlineartest(
            _build_bridged_optimizer(ws, mr),
            MOI_CONFIG,
            [
                # Needs SOS1/SOS2
                "int2",

                # Needs MOI.ACTIVATE_ON_ONE
                "indicator1",
                "indicator2",
                "indicator3",
                "indicator4",
            ],
        )
    end
end


text:
include("components.jl")

using IfElse

# Gate models (activation, inactivation, etc) for voltage-gated membrane currents
# Constructors could be adjusted, made nicer, and/or convenient macro syntax made up for this
n = AlphaBeta(
    V -> IfElse.ifelse(V == -55.0, 0.1 , (0.01*(V + 55.0))/(1.0 - exp(-(V + 55.0)/10.0))),
    V -> 0.125 * exp(-(V + 65.0)/80.0),
    exponent = 4)

m = AlphaBeta(
    V -> IfElse.ifelse(V == -40.0, 1.0, (0.1*(V + 40.0))/(1.0 - exp(-(V + 40.0)/10.0))),
    V -> 4.0*exp(-(V + 65.0)/18.0),
    exponent = 3)

# h = AlphaBeta(
#     V -> 0.07*exp(-(V+65.0)/20.0),
#     V -> 1.0/(1.0 + exp(-(V + 35.0)/10.0)))
# We can also define using steady-state (g∞) and time constant (τ) as in NeuronBuilder:
h = SSTau(
    V -> 1.0/(1.0+exp((V+12.3)/-11.8)),
    V -> 7.2 - 6.4/(1.0+exp((V+28.3)/-19.2)))

# Synaptic conductances fall in the range of 10-100nS
@named FastNaV = VoltageGatedChannel{Na}([m, h], max_g = 120mS/cm^2)
@named DelayedRect = VoltageGatedChannel{K}([n], max_g = 36mS/cm^2)
@name KCaV = VoltageIonGatedChannel{K,Ca}(
MembraneLeak = PassiveChannel{Leak}(max_g = 0.3mS/cm^2)

membrane_currents = [FastNaV, DelayedRect, Leak]

eq_potentials = [Na => 50mV,
                 K  => -80mV,
                 Leak => -50mV]

# And continue on with forms similar to this...
@named SomeNeuron = Neuron(membrane_currents, eq_potentials)

@named MyCircuit = NeuronalNetwork(Vector{Neurons},

max_stars_repo_name: wsphillips/FutureNeuralSimulation

max_issues_repo_name: wsphillips/FutureNeuralSimulation

max_forks_repo_name: wsphillips/FutureNeuralSimulation


text:
const arf_rnd_t = fmpr_rnd_t

const ARF_RND_DOWN = FMPR_RND_DOWN
const ARF_RND_UP = FMPR_RND_UP
const ARF_RND_FLOOR = FMPR_RND_FLOOR
const ARF_RND_CEIL = FMPR_RND_CEIL
const ARF_RND_NEAR = FMPR_RND_NEAR

const ARF_PREC_EXACT = WORD_MAX

################################################################################
#
#  Types and memory management for arf
#
################################################################################

const arf_t = arf_struct

arf() = begin
    z = arf_struct(0, 0, 0, 0)
    ccall((:arf_init, :libarb), Void, (Ref{arf_t}, ), z)
    finalizer(z, x -> ccall((:arf_clear, :libarb), Void, (Ref{arf_t}, ), x))
    z
end

################################################################################
#
#  Conversions
#
################################################################################

convert(::Type{arf_struct}, x::Fslong)        = (y = arf(); arf_set_si(y, x); y)
convert(::Type{arf_struct}, x::Cdouble)       = (y = arf(); arf_set_d(y, x); y)
convert(::Type{arf_struct}, x::BigFloat)      = (y = arf(); arf_set_mpfr(y, x); y)
convert(::Type{arf_struct}, x::BigInt)        = (y = arf(); arf_set_mpz(y, x); y)

convert(::Type{Fslong}, x::arf_struct, rnd)   = arf_get_si(x, rnd)
convert(::Type{Cdouble}, x::arf_struct, rnd)  = arf_get_d(x, rnd)
convert(::Type{BigFloat}, x::arf_struct, rnd) = (y = BigFloat(); arf_get_mpfr(y, x, rnd); y)

################################################################################
#
#  String I/O
#
################################################################################

arf_printd(y::arf_t, d) = ccall((:arf_printd, :libarb), Void, (Ref{arf_t}, Fslong), y, d)

show(io::IO, x::arf_t) = begin
    prec = 256
    d = ceil(Int, prec * 0.30102999566398119521)
    arf_printd(x, d)
end

################################################################################
#
#  Binary operations
#
################################################################################

arf_add(z::arf_t, x::arf_t, y::arf_t, prec, rnd) = ccall((:arf_add, :libarb), Cint, (Ref{arf_t}, Ref{arf_t}, Ref{arf_t}, Fslong, arf_rnd_t), z, x, y, prec, rnd)

################################################################################
#
#  Shifting
#
################################################################################

arf_mul_2exp_si(y::arf_t, x::arf_t, e) = ccall((:arf_mul_2exp_si, :libarb), Void, (Ref{arf_t}, Ref{arf_t}, Fslong), y, x, e)

################################################################################
#
#  Unsafe setting
#
################################################################################

for (typeofy, passtoc) in ((arf_t, Ref{arf_t}), (Ptr{arf_t}, Ptr{arf_t}))
    @eval begin
        arf_set(y::($typeofy), x::arf_t)         = ccall((:arf_set,      :libarb), Void, (($passtoc), Ref{arf_t}),    y, x)
        arf_set_si(y::($typeofy), x::Fslong)     = ccall((:arf_set_si,   :libarb), Void, (($passtoc), Fslong),        y, x)
        arf_set_ui(y::($typeofy), x::Fulong)     = ccall((:arf_set_ui,   :libarb), Void, (($passtoc), Fulong),        y, x)
        arf_set_d(y::($typeofy), x::Cdouble)     = ccall((:arf_set_d,    :libarb), Void, (($passtoc), Cdouble),       y, x)
        arf_set_fmpz(y::($typeofy), x::fmpz)     = ccall((:arf_set_fmpz, :libarb), Void, (($passtoc), Ref{fmpz}),     y, x)
        arf_set_mpz(y::($typeofy), x::BigInt)    = ccall((:arf_set_mpz,  :libarb), Void, (($passtoc), Ref{BigInt}),   y, x)
        arf_set_mpfr(y::($typeofy), x::BigFloat) = ccall((:arf_set_mpfr, :libarb), Void, (($passtoc), Ref{BigFloat}), y, x)

        arf_swap(y::($typeofy), x::arf_t)        = ccall((:arf_swap,     :libarb), Void, (($passtoc), Ref{arf_t}),    y, x)
    end
end

################################################################################
#
#  Unsafe getting
#
################################################################################

arf_get_si(x::arf_t, rnd)                = ccall((:arf_get_si,   :libarb), Fslong,  (               Ref{arf_t}, Cint),    x, rnd)
arf_get_d(x::arf_t, rnd)                 = ccall((:arf_get_d,    :libarb), Cdouble, (               Ref{arf_t}, Cint),    x, rnd)
arf_get_mpfr(y::BigFloat, x::arf_t, rnd) = ccall((:arf_get_mpfr, :libarb), Void,    (Ref{BigFloat}, Ref{arf_t}, Cint), y, x, rnd)


text:
using ACE, Printf, BenchmarkTools

using ACE: evaluate, evaluate!, evaluate_d, evaluate_d!
using ACEbase: acquire_B!, acquire_dB!

TX = ACE.PositionState{Float64}
B1p = ACE.Utils.RnYlm_1pbasis()
Rn = B1p.bases[1]
cfg = ACEConfig(rand(TX, Rn, 30))

## Manual Profiling Codes

ord = 3
deg = 15
wL = 1.5
# Bsel = ACE.SimpleSparseBasis(ord, deg)
Bsel = SparseBasis(; maxorder = 3, p = 1, default_maxdeg = deg,
                     weight = Dict(:n => 1.0, :l => wL))

B1p = ACE.Utils.RnYlm_1pbasis(maxdeg = deg, maxL = ceil(Int, deg/wL),
                              Bsel = Bsel)
Rn = B1p.bases[1]
Ylm = B1p.bases[2]
basis = ACE.SymmetricBasis(ACE.Invariant(), B1p, Bsel)

TX = ACE.PositionState{Float64}
cfg = ACEConfig(rand(TX, Rn, 20))
B1 = acquire_B!(B1p, cfg)

##

# the non-allocating version here makes virtually no difference
# Further, the move from Set to Stack fixed all the weird performance
# problems; it seems our 1p basis evaluation is now very fast.

@info("profile A")
A = acquire_B!(B1p, cfg)
@btime evaluate($B1p, $cfg)
@btime evaluate!($A, $B1p, $cfg)

##

@info("profile dA")
dA = evaluate_d(B1p, cfg)
@btime evaluate_d($B1p, $cfg)
@btime evaluate_d!($dA, $B1p, $cfg)

##

@info("profile B")
B = acquire_B!(basis, cfg)
@btime evaluate($basis, $cfg)
@btime evaluate!($B, $basis, $cfg)

##

@info("profile AA")
AA = acquire_B!(basis.pibasis, cfg)
@btime evaluate!($AA, $(basis.pibasis), $cfg)

##

dB = acquire_dB!(basis, cfg)
@btime evaluate_d($basis, $cfg)
@btime evaluate_d!($dB, $basis, $cfg)

# this fits with cost(dB) ≈ cost(B) * length(cfg) * 2
# so it seems close enough to optimal to accept this.

## ------- profiling codes

# using Profile, ProfileSVG

# function runn(N, f, args...)
#    for n = 1:N
#       r = f(args...)
#    end
# end

# runn(2, evaluate_d!, dB, basis, cfg)

# # ##

# fill!(dB, zero(eltype(dB)))

# Profile.clear()
# @profile runn(300, evaluate_d!, dB, basis, cfg)
# Profile.print()

# ##

# ProfileSVG.view()

# ##


text:
module SplicedStrings

#=
FIXME

Options for fast parser traversal:

    Codunits iterator with tuple (fragment_n, max_pointer, pointer)

    64-bit index containing [fragment_n, sentinal_bits, p]
        where p is a pointer into s.v[fragment_n]
        and sentinal_bits are the last few bits for the max value of i
        if the sentinal_bits match, check bounds of s.v[fragment_n]
            otherwise, just increment pointer
=#

using Base: @propagate_inbounds

const Fragment = SubString{String}

const index_offset = 0

mutable struct SplicedString <: AbstractString
    v::Vector{Fragment}
    ncodeunits::Int
    SplicedString() = SplicedString([], 0)
    SplicedString(a) = update!(new(splice_vector(a), 0))
    SplicedString(a...) = update!(new(splice_vector(a), 0))
end

function update!(s::SplicedString)
    l = length(s.v)
    s.ncodeunits = l == 0 ? 0 : (l - 1) << fragment_bits | ncodeunits(last(s.v)) + index_offset
    return s
end

SplicedString(s::SplicedString) = s

splice_vector(s::SplicedString) = s.v
splice_vector(s::AbstractString) = splice_item(s)
splice_vector(s) = mapreduce(splice_item, vcat, s)

splice_item(i::SplicedString) = i.v
splice_item(i::AbstractString) = isempty(i) ? [] : [i]
splice_item(i) = splice_item(string(i))

function splice_item(ss::SubString{SplicedString})
    sp = ss.string
    i = 1 + ss.offset
    j = ss.offset + ss.ncodeunits
    i_f, i_n, i_i = fragment(sp, i)
    j_f, j_n, j_i = fragment(sp, j)
    if i_f === j_f
        return[SubString(i_f, i_i, j_i)]
    end
    return vcat([SubString(i_f, i_i)],
                view(sp.v, i_n+1:j_n-1),
                [SubString(j_f, 1, j_i)])
end

#https://github.com/JuliaLang/julia/issues/26200
Base.promote_rule(::Type{<:AbstractString},
                  ::Type{<:AbstractString}) = AbstractString

#https://github.com/JuliaLang/julia/issues/26202
Base.nextind(s::SubString{SplicedString}, i::Int) = nextind(s.string, i)
Base.prevind(s::SubString{SplicedString}, i::Int) = prevind(s.string, i)
Base.keys(s::SubString{SplicedString}) = keys(s.string)

function convert(::Type{String}, ss::SplicedString)
    buf = IOBuffer()
    for i in ss.v
        write(buf, i)
    end
    return String(take!(buf))
end

Base.String(ss::SplicedString) =  convert(String, ss)

# Indexing Implementation

"""
64-bit SplicedString index:

    fragment number 24 bits
    fragment index 40 bits
"""
const fragment_bits = 40
const index_mask = 2 ^ fragment_bits - 1
const fragment_mask = ~index_mask

@propagate_inbounds function fragment_si(s::SplicedString, i::Int)
    n = i >> fragment_bits + 1
    v = s.v
    f = @inbounds v[n]
    if i != 1
        i = i & index_mask - index_offset
    end
    return f, i
end

@propagate_inbounds function fragment(s::SplicedString, i::Int)
    n = i >> fragment_bits + 1
    v = s.v
    f = @inbounds v[n]
    if i != 1
        i = i & index_mask - index_offset
    end
    return f, n, i
end

# Non-sparse Code Units view
#=
mutable struct SplicedCodeUnits <: DenseVector{UInt8}
    s::SplicedString
    v::Vector{AbstractString}
    ncodeunits::Int
    fragment_i::Int
    offset::Int
    codeunits::Vector{UInt8}
    last_i::Int
    function SplicedCodeUnits(s)
        ncu = isempty(s.v) ? 0 : sum(ncodeunits, s.v)
        cu = isempty(s.v) ? UInt8[] : codeunits(s.v[1])
        new(s, s.v, ncu, 1, 0, cu, length(cu))
    end
end

Base.String(cu::SplicedCodeUnits) = cu.s

Base.length(s::SplicedCodeUnits) = s.ncodeunits
Base.sizeof(s::SplicedCodeUnits) = length(s)
Base.size(s::SplicedCodeUnits) = (length(s),)
Base.strides(s::SplicedCodeUnits) = (1,)
Base.IndexStyle(::Type{<:SplicedCodeUnits}) = IndexLinear()

@propagate_inbounds function Base.getindex(s::SplicedCodeUnits, i::Int)

    while i > s.last_i
        if i > s.ncodeunits
            return 0x00
            throw(BoundsError(s, i))
        end
        s.offset = s.last_i
        s.fragment_i += 1
        cu = codeunits(s.v[s.fragment_i])
        s.codeunits = cu
        s.last_i += length(cu)
    end
    while i - 1 < s.offset
        if i < 1
            throw(BoundsError(s, i))
        end
        s.last_i = s.offset
        s.fragment_i -= 1
        s.codeunits = codeunits(s.v[s.fragment_i])
        s.offset -= length(s.codeunits)
    end

    return s.codeunits[i - s.offset]
end

Base.start(s::SplicedCodeUnits) = 1
@propagate_inbounds Base.next(s::SplicedCodeUnits, i) = (s[i], i+1)
@inline Base.done(s::SplicedCodeUnits, i) = i == s.ncodeunits+1

function next_ichar(s::SplicedCodeUnits, i::Int)
    i -= s.offset
    f = s.v[s.fragment_i]
    c = f[i]
    return s.offset + nextind(f, i) - 1, c
end

function sparseindex(s::SplicedCodeUnits, i)
    getindex(s, i)
    return (s.fragment_i - 1) << fragment_bits | i - s.offset
end
=#

# Index Iteration Interface

#Base.keys(s::SplicedString) = Base.EachStringIndex{SplicedString}(s)

#Base.first(s::Base.EachStringIndex{SplicedString}) = firstindex(s.s)

# Modification Interface

Base.append!(ss::SplicedString, s) = append!(s, string(s))
function Base.append!(ss::SplicedString, s::AbstractString)
    push!(ss.v, s)
    update!(ss)
end

Base.splice!(s::SplicedString, i::UnitRange, x) =
    splice!(s, i.start, i.stop, x)

# Modification Implementation

function Base.splice!(s::SplicedString, i::Int, j::Int, x)

    i_f, i_n, i_i = fragment(s, i)          # Exctract fragment,
    j_f, j_n, j_i = fragment(s, j)          # number and index.

                  isvalid(i_f, i_i) || throw(ArgumentError("invalid `i`"))
    j == i - 1 || isvalid(j_f, j_i) || throw(ArgumentError("invalid `j`"))

    if i_i > 1
        i_i = prevind(i_f, i_i)             # Extract head of fragment
        s.v[i_n] = SubString(i_f, 1, i_i)   # at the start of the splice.
        i_n += 1
    end

    if j_i > 0
        j_i = nextind(j_f, j_i)             # Extract tail of fragment
        if isvalid(j_f, j_i)                # at the end of the splice.
            s.v[j_n] = SubString(j_f, j_i)
        else                                # If the enitre tail is replaced
            j_n += 1                        # skip to the next fragment.
        end
    end

    v = splice_vector(x)                    # No nested SplicedStrings!
    @assert  all(i -> i isa AbstractString, v)
    @assert !any(isempty, v)
    @assert !any(i -> i isa SplicedString, v)
    @assert !any(i -> i isa SubString{SplicedString}, v)

    splice!(s.v, i_n:j_n-1, v)              # Splice the new fragments into `s`.
    update!(s)
end

# AbstractString Interface

Base.codeunit(s::SplicedString) = UInt8

@propagate_inbounds Base.codeunit(s::SplicedString, i::Int)::UInt8 =
    codeunit(fragment_si(s, i)...)

#densecodeunits(s::SplicedString) = SplicedCodeUnits(s)

#Base.firstindex(s::SplicedString) = index_offset + 1
#Base.start(s::SplicedString) = 1

# AbstractString has fixed first index = 1
#Base.checkbounds(::Type{Bool}, s::SplicedString, i::Integer) =
#    firstindex(s) ≤ i ≤ ncodeunits(s)
#
#Base.checkbounds(::Type{Bool}, s::SplicedString, r::AbstractRange{<:Integer}) =
#    isempty(r) || (firstindex(s) ≤ minimum(r) && maximum(r) ≤ ncodeunits(s))

Base.ncodeunits(s::SplicedString) = s.ncodeunits

Base.length(s::SplicedString) = isempty(s.v) ? 0 : sum(length, s.v)

function Base.length(s::SplicedString, i::Int, j::Int)

    i_f, i_n, i_i = fragment(s, i)          # Exctract fragment,
    j_f, j_n, j_i = fragment(s, j)          # number and index.

    if i_n > j_n
        return 0
    end

    if i_n == j_n
        return length(i_f, i_i, j_i)
    end

    return length(i_f, i_i, lastindex(i_f)) +
           (j_n <= i_n + 1 ? 0 : sum(length, view(s.v, i_n+1:j_n-1))) +
           length(j_f, 1, j_i)
end

@propagate_inbounds(
function nextcodeunitindex(s::SplicedString, i::Integer)

#=
A:
    increment encoded_index
    check encoded index for overflow
        ... special case
    decode fragment number
    decode fragment index
    fetch fragment
    fetch character from fragment index

B:
    increment pointer
    fetch char
        check for overflow
=#

    if i == 1
        i += index_offset
    end
    i += 1
    fs, fi = fragment_si(s, i)
    l = ncodeunits(fs)
    if fi > l
        n = i >> fragment_bits + 1
        if n < length(s.v)
            i = n << fragment_bits | 1 + index_offset
        end
    end
    return i
end)

@propagate_inbounds(
function nextcodeunit(s::SplicedString, i::Integer)
    if i == 1
        i += index_offset
    end
    i += 1
    fs, fi = fragment_si(s, i)
    l = ncodeunits(fs)
    if fi > l
        n = i >> fragment_bits + 1
        if n < length(s.v)
            i = n << fragment_bits | 1 + index_offset
            c = @inbounds codeunit(s, i)
        else
            c = 0x00
        end
    else
        c = @inbounds codeunit(fs, fi)
    end
    return i, c
end)

@propagate_inbounds(
function Base.isvalid(s::SplicedString, i::Int)

    if isempty(s.v)
        return false
    end
    if i == 1
        return true
    end
    if i <= index_offset + 1
        return false
    end

    return isvalid(fragment_si(s, i)...)
end)

@propagate_inbounds(
function Base.iterate(s::SplicedString, i::Integer=1)
    if i == index_offset || isempty(s.v)
        return nothing
    end
    fs, fi = fragment_si(s, i)
    c, fi = @inbounds iterate(fs, fi)
    l = ncodeunits(fs)
    i = i & fragment_mask | fi + index_offset
    if fi > l
        n = i >> fragment_bits + 1
        if n < length(s.v)
            i = n << fragment_bits | 1 + index_offset
        else
            i = index_offset
        end
    end
    return c, i
end)

@propagate_inbounds(
function Base.nextind(s::SplicedString, i::Int)::Int
    if i == 0
        return 1
    end
    fs, fi = fragment_si(s, i)
    fi = @inbounds nextind(fs, fi)
    l = ncodeunits(fs)
    if fi > l
        n = i >> fragment_bits + 1
        if n < length(s.v)
            return n << fragment_bits | 1 + index_offset
        end
    end
    return i & fragment_mask | fi + index_offset
end)

@propagate_inbounds(
function Base.thisind(s::SplicedString, i::Int)

    if i <= 1 || isempty(s.v)
        return i
    end

    return i & fragment_mask | thisind(fragment_si(s, i)...) + index_offset
end)

@propagate_inbounds(
function Base.prevind(s::SplicedString, i::Int)
    if i == 1
        return 0
    end
    fs, fi = fragment_si(s, i)
    fi = prevind(fs, fi)
    if fi == 0
        n = (i >> fragment_bits)
        if n == 0
            return 0
        else
            n -= 1
            return n << fragment_bits | lastindex(s.v[n+1]) + index_offset
        end
    end
    return i & fragment_mask | fi + index_offset
end)

end # module SplicedString


text:
A = mapreduce(line -> parse.(Int8, split(line, "")), hcat, readlines("input.txt"))
const CI = CartesianIndex
const udlr = [CI(1, 0), CI(-1, 0), CI(0, -1), CI(0, 1)]
const AI = CartesianIndices(A)

function find_danger_points(A)
    danger_points = Set{CartesianIndex}()
    for I in AI
        if A[I] < minimum(A[I + x] for x in udlr if I + x in AI)
            push!(danger_points, I)
        end
    end
    return collect(danger_points)
end

function expand!(basin)
    for b in basin
        for a in udlr
          n = b + a
            if n in AI && A[b] <= A[n] < 9
                push!(basin, n)
            end
        end
    end
    return basin
end

function basin_size(I)
    basin = Set([I])
    B₀, B₁ = 0, 1
    while B₁ > B₀
        B₀ = B₁
        expand!(basin)
        B₁ = length(basin)
    end
    return B₁
end

danger_points = find_danger_points(A)
@info "Risk scores = $(sum(i -> A[i]+1, danger_points))"
@info "Product of three largest basins = $(prod(sort!(map(basin_size, danger_points), rev=true)[1:3]))"


text:
module NonconvexMMA

export MMA87, MMA02, MMA, GCMMA, MMAOptions

import NonconvexCore: addvar!, add_ineq_constraint!, getmax, getmin
import NonconvexCore: get_objective_multiple, set_objective_multiple!
import NonconvexCore: geteqconstraints, getineqconstraints, NoCallback
import NonconvexCore: geteqconstraint, getineqconstraint, getobjective
import NonconvexCore: getobjectiveconstraints, getdim, Solution
import NonconvexCore: assess_convergence!, optimize!

using Reexport, Parameters, ChainRulesCore, ForwardDiff
@reexport using NonconvexCore, Optim
using NonconvexCore: optimize
using NonconvexCore: @params, AbstractFunction, AbstractModel, VecModel
using NonconvexCore: IneqConstraint, value_gradient, value_jacobian
using NonconvexCore: AbstractOptimizer, Solution, ConvergenceCriteria
using NonconvexCore: ConvergenceState, hasconverged, debugging
using NonconvexCore: getnvars, GenericResult

"""
    Solution(dualmodel, λ)

Construct an empty solution for the dual model `dualmodel` given a sample dual solution `λ`.
"""
function Solution(dualmodel, λ)
    prevx = copy(getxk(dualmodel))
    x = copy(prevx)
    λ = copy(λ)
    prevf = Inf
    fg = getfk(dualmodel)
    ∇fg = get∇fk(dualmodel)
    f = fg[1]
    g = fg[2:end]
    ∇f = ∇fg[1, :]
    ∇g = ∇fg[2:end, :]
    convstate = ConvergenceState()
    return Solution(prevx, x, λ, prevf, f, ∇f, g, ∇g, convstate)
end

# Approximation
include("mma_approx.jl")
include("xmma_approx.jl")
include("mma_approx_docs.jl")

# Models
include("mma_model.jl")
include("mmalag_model.jl")
include("dual_model.jl")

# Algorithms
include("mma_algorithm.jl")
include("ammal.jl")

end


text:
using .BaseAgent
using Params
using Traffic.Simple
using Channel.Gilbert
using Util

export RandomChannel

type RandomChannel <: Agent
    s :: AgentState
    status :: Status
    RandomChannel(i, P, pos) = new(AgentState(i, P, pos))
end

function BaseAgent.act(a :: RandomChannel, env, t)
    if a.status == Initialized
        if a.s.B_max - a.s.B_empty == 0
            return idle(a)
        end

        chan = rand(int8(1):n_channel)
        return switch(a, chan)
    elseif a.status == Switched
        return sense(a, env, detect_traffic)
    elseif a.status == Sensed
        if detect_traffic(a.s, env.traffics[a.s.chan], a.s.t_remaining)
            return idle(a)
        else
            P_tx = Params.P_levels[rand(1:endof(Params.P_levels))]
            pkgs_to_send = min(a.s.B_max - a.s.B_empty, floor((a.s.t_remaining * capacity(env.channels[a.s.chan], P_tx, a.s.pos)) / Params.pkt_size))

            if pkgs_to_send == 0
                return idle(a)
            end
            return transmit!(a, P_tx, env, pkgs_to_send)
        end
    elseif a.status == Transmitted
        return idle(a)
    end
end


text:
using KernelAbstractions
using Documenter

makedocs(;
    modules=[KernelAbstractions],
    authors="JuliaGPU and contributors",
    repo="https://github.com/JuliaGPU/KernelAbstractions.jl/blob/{commit}{path}#L{line}",
    sitename="KernelAbstractions.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://juliagpu.github.io/KernelAbstractions.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
        "Writing kernels" => "kernels.md",
        "Examples" => [
            "examples/memcopy.md",
            "examples/memcopy_static.md",
            "examples/naive_transpose.md",
            "examples/performance.md",
            "examples/matmul.md",
        ], # Examples
        "API" => "api.md",
        "Extras" => [
            "extras/unrolling.md",
        ], # Extras
    ], # pages
)

deploydocs(;
    repo="github.com/JuliaGPU/KernelAbstractions.jl",
)


text:
# by Lazaro Alonso # HIDE
using Pkg # HIDE
Pkg.activate(@__DIR__) # HIDE #
Pkg.add(["CairoMakie","PalmerPenguins", "DataFrames", "AlgebraOfGraphics"]) # HIDE
using PalmerPenguins, DataFrames, AlgebraOfGraphics, CairoMakie
let
    penguins = dropmissing(DataFrame(PalmerPenguins.load()))
    ychi = filter(:species => x -> x == "Chinstrap", penguins)[!,:bill_depth_mm]
    yade = filter(:species => x -> x == "Adelie", penguins)[!,:bill_depth_mm]
    ygen = filter(:species => x -> x == "Gentoo", penguins)[!,:bill_depth_mm]

    penguin_bill = data(penguins) * mapping( :bill_length_mm  => "bill length mm",
        :bill_depth_mm  => "bill depth mm")

    layers = AlgebraOfGraphics.density() * visual(Contour) + linear() +
                visual(alpha = 0.5, markersize = 15)
    aesPoints = penguin_bill * layers * mapping(color = :species, marker = :species,)
    aesHist = data(penguins) * mapping(:bill_length_mm => "bill length mm",
        color = :species, stack = :species) * AlgebraOfGraphics.histogram(;bins = 20)

    estilo = (color=["#FC7808", "#8C00EC", "#107A78"],
                marker=[:circle, :utriangle, :rect])

    layer = AlgebraOfGraphics.density() * visual(Wireframe, linewidth=0.05)
    plt3d = penguin_bill * layer * mapping(color = :species)
    # the actual plot with AoG and Makie
    set_aog_theme!()
    fig = Figure(; resolution = (700, 700))
    aes3d = draw!(fig[2,1], plt3d; axis = (type = Axis3,), palettes = estilo)
    aesH = draw!(fig[1,1], aesHist, palettes = estilo)
    ax1 = Axis(aesH[1,1])
    ax2 = Axis(aes3d[1,1])

    ax3 = Axis(fig[2,2], ylabel = "bill depth mm")
    chin = density!(ax3, ychi, direction = :y, color =("#8C00EC", 0.25),
        strokewidth = 1, strokecolor = "#8C00EC")
    ade = density!(ax3, yade, direction = :y, color =("#FC7808", 0.25),
        strokewidth = 1, strokecolor = "#FC7808")
    gen = density!(ax3, ygen, direction = :y, color =("#107A78", 0.25),
        strokewidth = 1, strokecolor = "#107A78")
    leg = Legend(fig, [chin,ade,gen], ["Chinstrap", "Adelie", "Gentoo"],)
    fig[1,2] = leg
    colsize!(fig.layout, 1, Relative(3/4))
    rowsize!(fig.layout, 1, Relative(1/4))
    fig
    save(joinpath(@__DIR__, "output", "penguinsAoGsides3d.png"), fig) # HIDE
end
Pkg.status() # HIDE
Pkg.activate() # HIDE

max_stars_repo_name: MisterBiggs/BeautifulMakie

max_issues_repo_name: MisterBiggs/BeautifulMakie

max_forks_repo_name: MisterBiggs/BeautifulMakie


text:
struct ControlComplementarity <: Constraints
    n
    ineq
    n_stage
end

function constraints!(c, Z, con::ControlComplementarity, model, idx, h, T)
    for t = 1:T-1
        x⁺ = view(Z, idx.x[t+1])
        q⁺ = view(x⁺, model.nq .+ (1:model.nq))
        u = view(Z, idx.u[t])

        c[(t - 1) * con.n_stage .+ (1:1)] = u[model.idx_s] - u[model.idx_u][1] * ϕ_func(model, q⁺)
        c[(t - 1) * con.n_stage + 1 .+ (1:1)] = u[model.idx_s] - u[model.idx_u][2] * ϕ_func(model, q⁺)
    end
    nothing
end

function constraints_jacobian!(∇c, Z, con::ControlComplementarity, model, idx, h, T)

    shift = 0

    for t = 1:T-1
        x⁺ = view(Z, idx.x[t+1])
        q⁺ = view(x⁺, model.nq .+ (1:model.nq))
        u = view(Z, idx.u[t])

        cq1(y) = u[model.idx_s] - u[model.idx_u][1] * ϕ_func(model, y)
        cu1(y) = y[model.idx_s] - y[model.idx_u][1] * ϕ_func(model, q⁺)
        cq2(y) = u[model.idx_s] - u[model.idx_u][2] * ϕ_func(model, y)
        cu2(y) = y[model.idx_s] - y[model.idx_u][2] * ϕ_func(model, q⁺)

        r_idx = (t - 1) * con.n_stage .+ (1:1)

        c_idx = idx.x[t+1][model.nq .+ (1:model.nq)]
        len = length(r_idx) * length(c_idx)
        ForwardDiff.jacobian!(reshape(view(∇c, shift .+ (1:len)),
            1, model.nq),
            cq1, q⁺)
        shift += len

        c_idx = idx.u[t]
        len = length(r_idx) * length(c_idx)
        ForwardDiff.jacobian!(reshape(view(∇c, shift .+ (1:len)),
            1, model.m),
            cu1, u)
        shift += len

        r_idx = (t - 1) * con.n_stage + 1 .+ (1:1)

        c_idx = idx.x[t+1][model.nq .+ (1:model.nq)]
        len = length(r_idx) * length(c_idx)
        ForwardDiff.jacobian!(reshape(view(∇c, shift .+ (1:len)),
            1, model.nq),
            cq2, q⁺)
        shift += len

        c_idx = idx.u[t]
        len = length(r_idx) * length(c_idx)
        ForwardDiff.jacobian!(reshape(view(∇c, shift .+ (1:len)),
            1, model.m),
            cu2, u)
        shift += len
    end

    return nothing
end

function constraints_sparsity(con::ControlComplementarity, model, idx, T;
    shift_row = 0, shift_col = 0)
    row = []
    col = []

    for t = 1:T-1

        r_idx = shift_row + (t - 1) * con.n_stage .+ (1:1)

        c_idx = shift_col .+ idx.x[t+1][model.nq .+ (1:model.nq)]
        row_col!(row, col, r_idx, c_idx)

        c_idx = shift_col .+ idx.u[t]
        row_col!(row, col, r_idx, c_idx)

        r_idx = shift_row + (t - 1) * con.n_stage + 1 .+ (1:1)

        c_idx = shift_col .+ idx.x[t+1][model.nq .+ (1:model.nq)]
        row_col!(row, col, r_idx, c_idx)

        c_idx = shift_col .+ idx.u[t]
        row_col!(row, col, r_idx, c_idx)
    end

    return collect(zip(row, col))
end

max_issues_repo_name: zacmanchester/DirectMotionPlanning

max_forks_repo_name: zacmanchester/DirectMotionPlanning


text:
include("model.jl")
using Flux, Flux.Tracker
import Random
import Dates

Random.seed!(0);
ShowTime() = Dates.format(Dates.now(), "yyyy-mm-dd HH:MM:SS")

# Generate Data
N = 10000
m = [3., -1., 2.]
s = [.1, .05, .15]
w = [.5, .3, .2]
K = length(m)
y = zeros(N)
for i in 1:N
  k = rand(Categorical(w))
  y[i] = rand(Normal(m[k], s[k]))
end

K = 3
vp = VP(K)
loss_hist = zeros(0)
function loss(y::T) where T
  out = -elbo(y, vp) / N
  append!(loss_hist, out.data)
  return out
end
params = Tracker.Params([getfield(vp, fn) for fn in fieldnames(typeof(vp))])

opt = ADAM(1e-1)
minibatch_size = 500
niters = 1000

Random.seed!(3);
@time for i in 1:niters
  idx = sample(1:N, minibatch_size)
  Flux.train!(loss, params, [(y[idx], )], opt)
  if i % 100 == 0

    println("$(ShowTime()) -- $(i)/$(niters) -- ELBO: $(-loss_hist[end])")
    # println(vp.m[:, 1])
    # println(exp.(vp.log_s[:, 1]))
    # println(softmax_fullrank(vp.real_w[:, 1]))
  end
end

s_post = vcat([exp.(rsample(vp.log_s.data)) for b in 1:100]'...)
w_post = vcat([softmax_fullrank(rsample(vp.real_w)) for b in 1:100]'...)
println("m_mean: $(vp.m[:, 1].data) | s_mean: $(mean(s_post, dims=1)), | w_mean: $(mean(w_post, dims=1))")


text:
for p in (:Impedance, :Admittance)
    @eval ==(p1::($p){T}, p2::($p){T}) where {T<:Real} = ==(p1.data, p2.data)
    @eval ==(p1::($p){T}, p2::($p){S}) where {T<:Real, S<:Real} =
        ==(promote(p1.data, p2.data)...)
    for f in (:+, :-, :*, :/)
        # Operation between CircuitParams
        @eval ($f)(p1::($p){T}, p2::($p){T}) where {T<:Real} =
            ($p)(($f)(p1.data, p2.data))
        @eval ($f)(p1::($p){T}, p2::($p){S}) where {T<:Real, S<:Real} =
            ($p)(($f)(promote(p1.data, p2.data)...))
            @eval ($f)(x::Number, param::($p){T}) where {T<:Real} =
            ($p)(($f)(x, param.data))
        @eval ($f)(param::($p){T}, x::Number) where {T<:Real} =
            ($p)(($f)(param.data, x))
    end
end

^(z::Impedance{T}, n::Number) where {T<:Real} = Impedance(^(z.data, n))
^(y::Admittance{T}, n::Number) where {T<:Real} = Impedance(^(y.data, n))

"""
    ∥(param1::T, param2::T, param3::T...) where {T<:CircuitParams}
Reciprocal addition of objects `T<:CircuitParams`.
- If `T` is `Impedance`, it returns the equivalent parallel impedance of given
impedances: Zeq⁻¹ = Z1⁻¹ + Z2⁻¹ + ⋯ + Zn⁻¹
- If `T` is `Admittance` it returns the equivalent series admittance of given
admittances: Yeq⁻¹ = Y1⁻¹ + Y2⁻¹ + ⋯ + Yn⁻¹
"""
∥(x1::Number, x2::Number, x3::Number...) = 1 / +([1/x for x in [x1, x2, x3...]]...)

for p in (:Impedance, :Admittance)
    @eval ∥(p1::$p, p2::$p, p3::$p...) =
    ($p)(1 / +([1/param.data for param in [p1, p2, p3...]]...))
end

"""
    check_frequency_identical(D1::CircuitData{S, T}, D2::CircuitData{S, T},
        D3::CircuitData{S, T}...) where {S<:Real, T<:NetworkParams}
Check if all circuit data inputs share same frequency ranges.
"""
check_frequency_identical(D1::CircuitData{S, T}, D2::CircuitData{S, T},
    D3::CircuitData{S, T}...) where {S<:Real, T<:CircuitParams} =
    all([(D1.frequency == d.frequency) for d in [D2, D3...]])

op_error = "CircuitData Error: Operations between `CircuitData` are only available between same frequency datasets"

"""
    +(D1::CircuitData{S, T}, D2::CircuitData{S, T}) where {S<:Real, T<:CircuitParams}
Addition of multiple `CircuitData`. Supported only for data with same frequency
range.
"""
+(D1::CircuitData{S,T}, D2::CircuitData{S,T},
    D3::CircuitData{S,T}...) where {S<:Real, T<:CircuitParams} =
    check_frequency_identical(D1, D2, D3...) ?
    CircuitData(D1.frequency, +([d.params for d in [D1, D2, D3...]]...)) :
    error(op_error)

"""
    ∥(D1::CircuitData{S, T}, D2::CircuitData{S, T}) where {S<:Real, T<:CircuitParams}
Reciprocal addition of multiple `CircuitData`. Supported only for data with
same frequency range.
"""
∥(D1::CircuitData{S, T}, D2::CircuitData{S, T},
    D3::CircuitData{S, T}...) where {S<:Real, T<:CircuitParams} =
    check_frequency_identical(D1, D2, D3...) ?
    CircuitData(D1.frequency, .∥([d.params for d in [D1, D2, D3...]]...)) :
    error(op_error)


text:
import CombinedParsers: word, non_word, newline, whitespace_maybe, whitespace_horizontal
import CombinedParsers: Repeat_max

@testset "CombinedParsers" begin
@testset "CharIn" begin
    @test parse(CharIn(isuppercase),"A") =='A'
    @test CharIn(CombinedParsers.ConstantParser('a')) == CharIn('a')
end

@testset "NamedTuple" begin
    @test parse(Sequence(first = CharIn(isuppercase), second = CharIn(islowercase)),"Ab") == (first='A', second='b')
    @test parse(Sequence(CharIn(isuppercase), :second => CharIn(islowercase)),"Ab") == (second='b',)
end

@testset "Repeat" begin
    @test parse(join(Repeat('a'),","),"a,a") == ['a','a']
end

@testset "parse_all" begin
    @test collect(parse_all(Repeat("a"|"ab"),"aabab")) ==
        [ ["a","a"], ["a","ab","a"], ["a","ab","ab"], ["a","ab"], ["a"],[] ]
end

@testset "Either" begin
    @test parse(Either("a","ab","ac")*AtEnd(),"ab") == ("ab", AtEnd())
    @test_throws ArgumentError parse(Atomic(Either("a","ab","ac"))*AtEnd(),"ab")
end

@testset "Repeat_until" begin
    @test parse(Sequence("(", Repeat_until(!!Either(word,non_word), ")")),
                "(balanced parenthesis)") ==
        ("(",["balanced", " ", "parenthesis"])
    # Test if strings bigger than Repeat_max can be parsed using max optional ArgumentError
    new_Repeat_max = Repeat_max+10;
    dat = 'a'^(new_Repeat_max)*'b';
    @test String(parse(Repeat_until('a','b';max=new_Repeat_max), dat))==dat[1:end-1]
end

@testset "Repeat_stop" begin
    new_Repeat_max = Repeat_max+10;
    dat = 'a'^(new_Repeat_max)*'b';
    @test String(parse(Repeat_stop('a','b';max=new_Repeat_max), dat))==dat[1:end-1]
end

@testset "Bytes" begin
    # simple test for binary parsing
    iterate_state(Bytes(1,UInt8),[0x33],1,1,1,nothing)
    @test parse(Bytes(1,UInt8),[0x33]) == 0x33
    @test parse(Bytes(2,UInt16),[0x33,0x66]) == 0x6633
    @test parse(Bytes(4,Float32),[0x55,0x77,0x33,0x66]) == reinterpret(Float32,0x66337755)
end

@testset "@with_names #29" begin
    p = @with_names begin
        foo =  Either{Any}(Any["A", "B"])
        bar = Repeat1("b")

        foobar = foo | bar
    end
    @test p("A") == "A"
    @test p("B") == "B"
    @test p("bbb") == ["b","b","b"]
end

end

@testset "FlatMap" begin
    @test parse(
        after(with_log("left",Either("a","ab"))) do v
        parser(v)
        end,
        "abab")=="ab"
    # parse(pattern,with_options(Base.PCRE.MULTILINE,"^"))
end
decimal = CharIn(UnicodeClass(:Nd))
decimals = Repeat1(decimal)
@test parse(decimals,"123") == [ "123"... ]

decimal = CharIn('0':'9')
decimals = Repeat1(decimal)
@test parse(decimals,"123") == [ "123"... ]

attribute_parser =
    map(
        (v) -> (lowercase(v[1]) => "$(v[5])")::Pair{String,String},
        Sequence(
            !Repeat1(word), whitespace_maybe,"=", whitespace_maybe,
            Either(Sequence(2,"\"", Repeat_until(AnyChar(),"\"",wrap=JoinSubstring)),
                   Sequence(2,"'", Repeat_until(AnyChar(),"'",wrap=JoinSubstring)),
                   !Sequence(decimals, "%"),
                   !Sequence(CharIn("+-"), decimals),
                   !Repeat1(word),
                   !Sequence("#", Repeat(6,6,hex_digit)))
        ));

attributes = join(attribute_parser, whitespace_maybe);

@testset "html attributes" begin
    @test parse(attributes,"a = 1 b=6% font=\"+1asd\" some=word color=#ffffff increment=+1 decrement=-1") ==
    [ "a" => "1", "b" => "6%", "font" => "+1asd", "some" => "word", "color" => "#ffffff",
      "increment" => "+1", "decrement" => "-1" ]
    @test parse(attributes, "size=10% class=1") == [ "size"=>"10%", "class"=>"1" ]
end

function html(tags::CombinedParser, inner::CombinedParser, attrs=attributes)
    html(result_type(inner), tags, attrs) do until
        Repeat_until(inner, until)
    end
end

function html(inner::Function, T::Type, tags::CombinedParser, attrs_parser=attributes)
    A = eltype(result_type(attrs_parser))
    function nested_html(x,)
        (tag,attrs) = x
        Either{Any}(map(parser("/>")) do v
                    (tag=tag, attrs=attrs, children=T[])
                    end,
                    Sequence(">",
                             inner(Sequence("</",tag,">"))) do v
                    (tag=tag, attrs=attrs, children=v[2])
                    end)
    end
    FlatMap{Any}(
        nested_html,
        Sequence(
            2,
            "<",
            Sequence(
                tags,
                Optional(Sequence(
                    2,
                    whitespace_horizontal,
                    attrs_parser,
                    whitespace_maybe)))))
end

@testset "html" begin
    inner = Either{Any}(Any[!Repeat(CharNotIn("<>"))]);
    pushfirst!(inner,html(!Repeat1(ValueIn('a':'z')),inner,attributes));
    parse(inner,"ba")
    @test parse(inner,"iboldj") ==
        (tag="a", attrs=["font"=>"+1"], children=[
            "i",
            (tag="b", attrs=[], children=["bold"]),
            "j"])

    @test parse(inner,"") ==
        (tag="a", attrs=["font"=>"+1"], children=[])
end


text:
isexpr(x, head) = isa(x, Expr) && x.head == head

macro parent(expr::Expr)
  @assert isexpr(expr, :type)
  tname = expr.args[2]
  tfields = filter(x->!isexpr(x,:line), expr.args[3].args)
  quote
    $(esc(tname)) = $tfields
  end
end

macro inherit(expr::Expr, parents::Symbol...)
  @assert isexpr(expr, :type)
  for parent in parents
    append!(expr.args[end].args, eval(parent))
  end
  quote
    $expr
  end
end

abstract Animal

@parent type CatOrDog
  age::Int
  weight::Float64
end

kilo(x) = x.weight * 0.4535

@inherit type Cat <: Animal end CatOrDog
@inherit type Dog <: Animal end CatOrDog

abstract Country
type USA <: Country end
type UK <: Country end

incharge(a::Animal, ::USA) = "Mike"
incharge(a::Animal, ::UK) = "The Queen?"

play{T<:Animal}(a1::T, a2::T) = "no toys? boring"
play{T<:Animal}(a1::T, a2::T, toys::Int...) = "playing with Ints: $toys"
play{T<:Animal}(a1::T, a2::T, toys::String...) = "playing with Strings: $toys"

play(a1::Cat, a2::Dog, args...) = play(a2, a1, args...)
play(a1::Dog, a2::Cat, args...) = "Grrrrrrrrrrrrr.... meow"

cat = Cat(10, 8.0)
dog = Dog(20, 15.0);

# u = 0
# spikes = [1, 4, 8, 15]
# tstep = 0.1

# α(q, s) = q / (τs - τr) * exp(-s / τs)

# current = 0.
# for t in tstep:tstep:30.
#   du =
#   ut+1 = (1-lambda) * u
#   du = lambda * u
# end

# # -----------------------------------------------------------------------
# # general algo for each timestep:

# foreach neuron
#   step!(neuron)  # this should decay u towards urest, as well as setting n.fired=false...
#                   # also decay q (:= total current (pulse)) from all synapses towards 0, then add it to u
# end

# while true
#   didfire = false
#   foreach neuron
#     if u >= threshold

#       # reset neuron
#       didfire = true
#       fired=true
#       u = u_refractory

#       # transmit pulse
#       foreach n.synapses
#         pn = synapse.postneuron
#         pulse = basepulse * syn.weight
#         pn.q += pulse

#         # don't increate u if it already fired
#         if !pn.fired
#           pn.u += pulse
#         end
#       end
#     end
#   end
# end

# # now that we broke out, everything has stepped forward, fired, and transmitted


text:
# exercise estimating a linear model by iterative minimization,
# and verifying that OLS gives same results.
# If the data is missing, run BasicDataAnalysis.jl
# in the Examples/Julia directory

using CSV, DataFrames, StatsModels, Econometrics
# prepare the data
card = CSV.read("../Julia/cooked.csv", DataFrame)
display(card)

y = card[:,1]
x = Matrix{Float64}([ones(size(card,1)) card[:,2:7]])

# define the objective function and start value
obj = theta -> (y-x*theta)'*(y-x*theta)
startval = zeros(size(x,2))
# do the minimization
thetahat, objvalue = fminunc(obj, startval)
println("the OLS estimates by numeric min: obj. value: ", round(objvalue,digits=5))
prettyprint(thetahat)

# verify by using OLS, which uses the analytic solution
println("verifying by OLS:")
ols( @formula(lnwage ~ 1 + educ + exper + expsq + black + south + smsa), card)
nothing

max_stars_repo_name: Hiroakiyusheng/Econometrics

max_issues_repo_name: Hiroakiyusheng/Econometrics

max_forks_repo_name: Hiroakiyusheng/Econometrics


text:
for cnt = 1:10
    println(string (cnt, ": Hello from Julia program."))
end

max_stars_repo_name: mraitmaier/pyrus

max_issues_repo_name: mraitmaier/pyrus

max_forks_repo_name: mraitmaier/pyrus