text:
# Automatically generated using Clang.jl wrap_c, version 0.0.0

export
    unix,
    linux,
    AVIO_SEEKABLE_NORMAL,
    AVIO_SEEKABLE_TIME,
    AVSEEK_SIZE,
    AVSEEK_FORCE,
    AVIO_FLAG_READ,
    AVIO_FLAG_WRITE,
    AVIO_FLAG_READ_WRITE,
    AVIO_FLAG_NONBLOCK,
    AVIO_FLAG_DIRECT,
    AVIOInterruptCB,
    AVIODirEntryType,
    AVIO_ENTRY_UNKNOWN,
    AVIO_ENTRY_BLOCK_DEVICE,
    AVIO_ENTRY_CHARACTER_DEVICE,
    AVIO_ENTRY_DIRECTORY,
    AVIO_ENTRY_NAMED_PIPE,
    AVIO_ENTRY_SYMBOLIC_LINK,
    AVIO_ENTRY_SOCKET,
    AVIO_ENTRY_FILE,
    AVIO_ENTRY_SERVER,
    AVIO_ENTRY_SHARE,
    AVIO_ENTRY_WORKGROUP,
    AVIODirEntry,
    AVIODirContext,
    AVIODataMarkerType,
    AVIO_DATA_MARKER_HEADER,
    AVIO_DATA_MARKER_SYNC_POINT,
    AVIO_DATA_MARKER_BOUNDARY_POINT,
    AVIO_DATA_MARKER_UNKNOWN,
    AVIO_DATA_MARKER_TRAILER,
    AVIO_DATA_MARKER_FLUSH_POINT,
    AVIOContext,
    AVBPrint,
    AVPROBE_SCORE_MAX,
    AVPROBE_SCORE_RETRY,
    AVPROBE_SCORE_STREAM_RETRY,
    AVPROBE_SCORE_EXTENSION,
    AVPROBE_SCORE_MIME,
    AVPROBE_PADDING_SIZE,
    AVFMT_NOFILE,
    AVFMT_NEEDNUMBER,
    AVFMT_SHOW_IDS,
    AVFMT_GLOBALHEADER,
    AVFMT_NOTIMESTAMPS,
    AVFMT_GENERIC_INDEX,
    AVFMT_TS_DISCONT,
    AVFMT_VARIABLE_FPS,
    AVFMT_NODIMENSIONS,
    AVFMT_NOSTREAMS,
    AVFMT_NOBINSEARCH,
    AVFMT_NOGENSEARCH,
    AVFMT_NO_BYTE_SEEK,
    AVFMT_ALLOW_FLUSH,
    AVFMT_TS_NONSTRICT,
    AVFMT_TS_NEGATIVE,
    AVFMT_SEEK_TO_PTS,
    AVINDEX_KEYFRAME,
    AVINDEX_DISCARD_FRAME,
    AV_DISPOSITION_DEFAULT,
    AV_DISPOSITION_DUB,
    AV_DISPOSITION_ORIGINAL,
    AV_DISPOSITION_COMMENT,
    AV_DISPOSITION_LYRICS,
    AV_DISPOSITION_KARAOKE,
    AV_DISPOSITION_FORCED,
    AV_DISPOSITION_HEARING_IMPAIRED,
    AV_DISPOSITION_VISUAL_IMPAIRED,
    AV_DISPOSITION_CLEAN_EFFECTS,
    AV_DISPOSITION_ATTACHED_PIC,
    AV_DISPOSITION_TIMED_THUMBNAILS,
    AV_DISPOSITION_CAPTIONS,
    AV_DISPOSITION_DESCRIPTIONS,
    AV_DISPOSITION_METADATA,
    AV_DISPOSITION_DEPENDENT,
    AV_DISPOSITION_STILL_IMAGE,
    AV_PTS_WRAP_IGNORE,
    AV_PTS_WRAP_ADD_OFFSET,
    AV_PTS_WRAP_SUB_OFFSET,
    AVSTREAM_EVENT_FLAG_METADATA_UPDATED,
    MAX_STD_TIMEBASES,
    MAX_REORDER_DELAY,
    AV_PROGRAM_RUNNING,
    AVFMTCTX_NOHEADER,
    AVFMTCTX_UNSEEKABLE,
    AVFMT_FLAG_GENPTS,
    AVFMT_FLAG_IGNIDX,
    AVFMT_FLAG_NONBLOCK,
    AVFMT_FLAG_IGNDTS,
    AVFMT_FLAG_NOFILLIN,
    AVFMT_FLAG_NOPARSE,
    AVFMT_FLAG_NOBUFFER,
    AVFMT_FLAG_CUSTOM_IO,
    AVFMT_FLAG_DISCARD_CORRUPT,
    AVFMT_FLAG_FLUSH_PACKETS,
    AVFMT_FLAG_BITEXACT,
    AVFMT_FLAG_MP4A_LATM,
    AVFMT_FLAG_SORT_DTS,
    AVFMT_FLAG_PRIV_OPT,
    AVFMT_FLAG_KEEP_SIDE_DATA,
    AVFMT_FLAG_FAST_SEEK,
    AVFMT_FLAG_SHORTEST,
    AVFMT_FLAG_AUTO_BSF,
    AVFMT_EVENT_FLAG_METADATA_UPDATED,
    AVFMT_AVOID_NEG_TS_AUTO,
    AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE,
    AVFMT_AVOID_NEG_TS_MAKE_ZERO,
    AVSEEK_FLAG_BACKWARD,
    AVSEEK_FLAG_BYTE,
    AVSEEK_FLAG_ANY,
    AVSEEK_FLAG_FRAME,
    AVSTREAM_INIT_IN_WRITE_HEADER,
    AVSTREAM_INIT_IN_INIT_OUTPUT,
    AV_FRAME_FILENAME_FLAGS_MULTIPLE,
    AVCodecTag,
    AVInputFormat,
    AVOutputFormat,
    AVStreamParseType,
    AVSTREAM_PARSE_NONE,
    AVSTREAM_PARSE_FULL,
    AVSTREAM_PARSE_HEADERS,
    AVSTREAM_PARSE_TIMESTAMPS,
    AVSTREAM_PARSE_FULL_ONCE,
    AVSTREAM_PARSE_FULL_RAW,
    AVPacketList,
    AVProbeData,
    AVIndexEntry,
    AVStreamInternal,
    AVStream,
    AVProgram,
    AVChapter,
    AVDurationEstimationMethod,
    AVFMT_DURATION_FROM_PTS,
    AVFMT_DURATION_FROM_STREAM,
    AVFMT_DURATION_FROM_BITRATE,
    AVFormatInternal,
    av_format_control_message,
    AVFormatContext,
    AVDeviceInfoList,
    AVDeviceCapabilitiesQuery,
    AVOpenCallback,
    AVTimebaseSource,
    AVFMT_TBCF_AUTO,
    AVFMT_TBCF_DECODER,
    AVFMT_TBCF_DEMUXER,
    AVFMT_TBCF_R_FRAMERATE,
    LIBAVFORMAT_VERSION_MAJOR,
    LIBAVFORMAT_VERSION_MINOR,
    LIBAVFORMAT_VERSION_MICRO
    # LIBAVFORMAT_BUILD

const unix = 1
const linux = 1
const AVIO_SEEKABLE_NORMAL = 1 << 0
const AVIO_SEEKABLE_TIME = 1 << 1
const AVSEEK_SIZE = 0x00010000
const AVSEEK_FORCE = 0x00020000
const AVIO_FLAG_READ = 1
const AVIO_FLAG_WRITE = 2
const AVIO_FLAG_READ_WRITE = AVIO_FLAG_READ | AVIO_FLAG_WRITE
const AVIO_FLAG_NONBLOCK = 8
const AVIO_FLAG_DIRECT = 0x8000

struct AVIOInterruptCB
    callback::Ptr{Cvoid}
    opaque::Ptr{Cvoid}
end

# begin enum AVIODirEntryType
const AVIODirEntryType = UInt32
const AVIO_ENTRY_UNKNOWN = 0 |> UInt32
const AVIO_ENTRY_BLOCK_DEVICE = 1 |> UInt32
const AVIO_ENTRY_CHARACTER_DEVICE = 2 |> UInt32
const AVIO_ENTRY_DIRECTORY = 3 |> UInt32
const AVIO_ENTRY_NAMED_PIPE = 4 |> UInt32
const AVIO_ENTRY_SYMBOLIC_LINK = 5 |> UInt32
const AVIO_ENTRY_SOCKET = 6 |> UInt32
const AVIO_ENTRY_FILE = 7 |> UInt32
const AVIO_ENTRY_SERVER = 8 |> UInt32
const AVIO_ENTRY_SHARE = 9 |> UInt32
const AVIO_ENTRY_WORKGROUP = 10 |> UInt32
# end enum AVIODirEntryType

struct AVIODirEntry
    name::Cstring
    _type::Cint
    utf8::Cint
    size::Int64
    modification_timestamp::Int64
    access_timestamp::Int64
    status_change_timestamp::Int64
    user_id::Int64
    group_id::Int64
    filemode::Int64
end

struct AVIODirContext
    # url_context::Ptr{URLContext}
    url_context::Ptr{Cvoid}
end

# begin enum AVIODataMarkerType
const AVIODataMarkerType = UInt32
const AVIO_DATA_MARKER_HEADER = 0 |> UInt32
const AVIO_DATA_MARKER_SYNC_POINT = 1 |> UInt32
const AVIO_DATA_MARKER_BOUNDARY_POINT = 2 |> UInt32
const AVIO_DATA_MARKER_UNKNOWN = 3 |> UInt32
const AVIO_DATA_MARKER_TRAILER = 4 |> UInt32
const AVIO_DATA_MARKER_FLUSH_POINT = 5 |> UInt32
# end enum AVIODataMarkerType

struct AVIOContext
    av_class::Ptr{AVClass}
    buffer::Ptr{Cuchar}
    buffer_size::Cint
    buf_ptr::Ptr{Cuchar}
    buf_end::Ptr{Cuchar}
    opaque::Ptr{Cvoid}
    read_packet::Ptr{Cvoid}
    write_packet::Ptr{Cvoid}
    seek::Ptr{Cvoid}
    pos::Int64
    eof_reached::Cint
    write_flag::Cint
    max_packet_size::Cint
    checksum::Culong
    checksum_ptr::Ptr{Cuchar}
    update_checksum::Ptr{Cvoid}
    error::Cint
    read_pause::Ptr{Cvoid}
    read_seek::Ptr{Cvoid}
    seekable::Cint
    maxsize::Int64
    direct::Cint
    bytes_read::Int64
    seek_count::Cint
    writeout_count::Cint
    orig_buffer_size::Cint
    short_seek_threshold::Cint
    protocol_whitelist::Cstring
    protocol_blacklist::Cstring
    write_data_type::Ptr{Cvoid}
    ignore_boundary_point::Cint
    current_type::AVIODataMarkerType
    last_time::Int64
    short_seek_get::Ptr{Cvoid}
    written::Int64
    buf_ptr_max::Ptr{Cuchar}
    min_packet_size::Cint
end

struct AVBPrint
end

const AVPROBE_SCORE_MAX = 100
const AVPROBE_SCORE_RETRY = AVPROBE_SCORE_MAX / 4
const AVPROBE_SCORE_STREAM_RETRY = AVPROBE_SCORE_MAX / 4 - 1
const AVPROBE_SCORE_EXTENSION = 50
const AVPROBE_SCORE_MIME = 75
const AVPROBE_PADDING_SIZE = 32
const AVFMT_NOFILE = 0x0001
const AVFMT_NEEDNUMBER = 0x0002
const AVFMT_SHOW_IDS = 0x0008
const AVFMT_GLOBALHEADER = 0x0040
const AVFMT_NOTIMESTAMPS = 0x0080
const AVFMT_GENERIC_INDEX = 0x0100
const AVFMT_TS_DISCONT = 0x0200
const AVFMT_VARIABLE_FPS = 0x0400
const AVFMT_NODIMENSIONS = 0x0800
const AVFMT_NOSTREAMS = 0x1000
const AVFMT_NOBINSEARCH = 0x2000
const AVFMT_NOGENSEARCH = 0x4000
const AVFMT_NO_BYTE_SEEK = 0x8000
const AVFMT_ALLOW_FLUSH = 0x00010000
const AVFMT_TS_NONSTRICT = 0x00020000
const AVFMT_TS_NEGATIVE = 0x00040000
const AVFMT_SEEK_TO_PTS = 0x04000000
const AVINDEX_KEYFRAME = 0x0001
const AVINDEX_DISCARD_FRAME = 0x0002
const AV_DISPOSITION_DEFAULT = 0x0001
const AV_DISPOSITION_DUB = 0x0002
const AV_DISPOSITION_ORIGINAL = 0x0004
const AV_DISPOSITION_COMMENT = 0x0008
const AV_DISPOSITION_LYRICS = 0x0010
const AV_DISPOSITION_KARAOKE = 0x0020
const AV_DISPOSITION_FORCED = 0x0040
const AV_DISPOSITION_HEARING_IMPAIRED = 0x0080
const AV_DISPOSITION_VISUAL_IMPAIRED = 0x0100
const AV_DISPOSITION_CLEAN_EFFECTS = 0x0200
const AV_DISPOSITION_ATTACHED_PIC = 0x0400
const AV_DISPOSITION_TIMED_THUMBNAILS = 0x0800
const AV_DISPOSITION_CAPTIONS = 0x00010000
const AV_DISPOSITION_DESCRIPTIONS = 0x00020000
const AV_DISPOSITION_METADATA = 0x00040000
const AV_DISPOSITION_DEPENDENT = 0x00080000
const AV_DISPOSITION_STILL_IMAGE = 0x00100000
const AV_PTS_WRAP_IGNORE = 0
const AV_PTS_WRAP_ADD_OFFSET = 1
const AV_PTS_WRAP_SUB_OFFSET = -1
const AVSTREAM_EVENT_FLAG_METADATA_UPDATED = 0x0001
const MAX_STD_TIMEBASES = 30 * 12 + 30 + 3 + 6
const MAX_REORDER_DELAY = 16
const AV_PROGRAM_RUNNING = 1
const AVFMTCTX_NOHEADER = 0x0001
const AVFMTCTX_UNSEEKABLE = 0x0002
const AVFMT_FLAG_GENPTS = 0x0001
const AVFMT_FLAG_IGNIDX = 0x0002
const AVFMT_FLAG_NONBLOCK = 0x0004
const AVFMT_FLAG_IGNDTS = 0x0008
const AVFMT_FLAG_NOFILLIN = 0x0010
const AVFMT_FLAG_NOPARSE = 0x0020
const AVFMT_FLAG_NOBUFFER = 0x0040
const AVFMT_FLAG_CUSTOM_IO = 0x0080
const AVFMT_FLAG_DISCARD_CORRUPT = 0x0100
const AVFMT_FLAG_FLUSH_PACKETS = 0x0200
const AVFMT_FLAG_BITEXACT = 0x0400
const AVFMT_FLAG_MP4A_LATM = 0x8000
const AVFMT_FLAG_SORT_DTS = 0x00010000
const AVFMT_FLAG_PRIV_OPT = 0x00020000
const AVFMT_FLAG_KEEP_SIDE_DATA = 0x00040000
const AVFMT_FLAG_FAST_SEEK = 0x00080000
const AVFMT_FLAG_SHORTEST = 0x00100000
const AVFMT_FLAG_AUTO_BSF = 0x00200000
const FF_FDEBUG_TS = 0x0001
const AVFMT_EVENT_FLAG_METADATA_UPDATED = 0x0001
const AVFMT_AVOID_NEG_TS_AUTO = -1
const AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE = 1
const AVFMT_AVOID_NEG_TS_MAKE_ZERO = 2
const AVSEEK_FLAG_BACKWARD = 1
const AVSEEK_FLAG_BYTE = 2
const AVSEEK_FLAG_ANY = 4
const AVSEEK_FLAG_FRAME = 8
const AVSTREAM_INIT_IN_WRITE_HEADER = 0
const AVSTREAM_INIT_IN_INIT_OUTPUT = 1
const AV_FRAME_FILENAME_FLAGS_MULTIPLE = 1

struct AVCodecTag
end

struct AVInputFormat
    name::Cstring
    long_name::Cstring
    flags::Cint
    extensions::Cstring
    codec_tag::Ptr{Ptr{AVCodecTag}}
    priv_class::Ptr{AVClass}
    mime_type::Cstring
    next::Ptr{AVInputFormat}
    raw_codec_id::Cint
    priv_data_size::Cint
    read_probe::Ptr{Cvoid}
    read_header::Ptr{Cvoid}
    read_packet::Ptr{Cvoid}
    read_close::Ptr{Cvoid}
    read_seek::Ptr{Cvoid}
    read_timestamp::Ptr{Cvoid}
    read_play::Ptr{Cvoid}
    read_pause::Ptr{Cvoid}
    read_seek2::Ptr{Cvoid}
    get_device_list::Ptr{Cvoid}
    create_device_capabilities::Ptr{Cvoid}
    free_device_capabilities::Ptr{Cvoid}
end

struct AVOutputFormat
    name::Cstring
    long_name::Cstring
    mime_type::Cstring
    extensions::Cstring
    audio_codec::AVCodecID
    video_codec::AVCodecID
    subtitle_codec::AVCodecID
    flags::Cint
    codec_tag::Ptr{Ptr{AVCodecTag}}
    priv_class::Ptr{AVClass}
    next::Ptr{AVOutputFormat}
    priv_data_size::Cint
    write_header::Ptr{Cvoid}
    write_packet::Ptr{Cvoid}
    write_trailer::Ptr{Cvoid}
    interleave_packet::Ptr{Cvoid}
    query_codec::Ptr{Cvoid}
    get_output_timestamp::Ptr{Cvoid}
    control_message::Ptr{Cvoid}
    write_uncoded_frame::Ptr{Cvoid}
    get_device_list::Ptr{Cvoid}
    create_device_capabilities::Ptr{Cvoid}
    free_device_capabilities::Ptr{Cvoid}
    data_codec::AVCodecID
    init::Ptr{Cvoid}
    deinit::Ptr{Cvoid}
    check_bitstream::Ptr{Cvoid}
end

# begin enum AVStreamParseType
const AVStreamParseType = UInt32
const AVSTREAM_PARSE_NONE = 0 |> UInt32
const AVSTREAM_PARSE_FULL = 1 |> UInt32
const AVSTREAM_PARSE_HEADERS = 2 |> UInt32
const AVSTREAM_PARSE_TIMESTAMPS = 3 |> UInt32
const AVSTREAM_PARSE_FULL_ONCE = 4 |> UInt32
const AVSTREAM_PARSE_FULL_RAW = 5 |> UInt32
# end enum AVStreamParseType

struct AVPacketList
    pkt::AVPacket
    next::Ptr{AVPacketList}
end

struct AVProbeData
    filename::Cstring
    buf::Ptr{Cuchar}
    buf_size::Cint
    mime_type::Cstring
end

struct AVIndexEntry
    pos::Int64
    timestamp::Int64
    flags::Cint
    size::Cint
    min_distance::Cint
end

struct AVStreamInternal
end

struct AVStream
    index::Cint
    id::Cint
    codec::Ptr{AVCodecContext}
    priv_data::Ptr{Cvoid}
    time_base::AVRational
    start_time::Int64
    duration::Int64
    nb_frames::Int64
    disposition::Cint
    discard::AVDiscard
    sample_aspect_ratio::AVRational
    metadata::Ptr{AVDictionary}
    avg_frame_rate::AVRational
    attached_pic::AVPacket
    side_data::Ptr{AVPacketSideData}
    nb_side_data::Cint
    event_flags::Cint
    r_frame_rate::AVRational
    recommended_encoder_configuration::Cstring
    codecpar::Ptr{AVCodecParameters}
    info::Ptr{}
    pts_wrap_bits::Cint
    first_dts::Int64
    cur_dts::Int64
    last_IP_pts::Int64
    last_IP_duration::Cint
    probe_packets::Cint
    codec_info_nb_frames::Cint
    need_parsing::AVStreamParseType
    parser::Ptr{AVCodecParserContext}
    last_in_packet_buffer::Ptr{AVPacketList}
    probe_data::AVProbeData
    pts_buffer::NTuple{17, Int64}
    index_entries::Ptr{AVIndexEntry}
    nb_index_entries::Cint
    index_entries_allocated_size::UInt32
    stream_identifier::Cint
    program_num::Cint
    pmt_version::Cint
    pmt_stream_idx::Cint
    interleaver_chunk_size::Int64
    interleaver_chunk_duration::Int64
    request_probe::Cint
    skip_to_keyframe::Cint
    skip_samples::Cint
    start_skip_samples::Int64
    first_discard_sample::Int64
    last_discard_sample::Int64
    nb_decoded_frames::Cint
    mux_ts_offset::Int64
    pts_wrap_reference::Int64
    pts_wrap_behavior::Cint
    update_initial_durations_done::Cint
    pts_reorder_error::NTuple{17, Int64}
    pts_reorder_error_count::NTuple{17, UInt8}
    last_dts_for_order_check::Int64
    dts_ordered::UInt8
    dts_misordered::UInt8
    inject_global_side_data::Cint
    display_aspect_ratio::AVRational
    internal::Ptr{AVStreamInternal}
end

struct AVProgram
    id::Cint
    flags::Cint
    discard::AVDiscard
    stream_index::Ptr{UInt32}
    nb_stream_indexes::UInt32
    metadata::Ptr{AVDictionary}
    program_num::Cint
    pmt_pid::Cint
    pcr_pid::Cint
    pmt_version::Cint
    start_time::Int64
    end_time::Int64
    pts_wrap_reference::Int64
    pts_wrap_behavior::Cint
end

struct AVChapter
    id::Cint
    time_base::AVRational
    start::Int64
    _end::Int64
    metadata::Ptr{AVDictionary}
end

# begin enum AVDurationEstimationMethod
const AVDurationEstimationMethod = UInt32
const AVFMT_DURATION_FROM_PTS = 0 |> UInt32
const AVFMT_DURATION_FROM_STREAM = 1 |> UInt32
const AVFMT_DURATION_FROM_BITRATE = 2 |> UInt32
# end enum AVDurationEstimationMethod

struct AVFormatInternal
end

const av_format_control_message = Ptr{Cvoid}

struct AVFormatContext
    av_class::Ptr{AVClass}
    iformat::Ptr{AVInputFormat}
    oformat::Ptr{AVOutputFormat}
    priv_data::Ptr{Cvoid}
    pb::Ptr{AVIOContext}
    ctx_flags::Cint
    nb_streams::UInt32
    streams::Ptr{Ptr{AVStream}}
    filename::NTuple{1024, UInt8}
    url::Cstring
    start_time::Int64
    duration::Int64
    bit_rate::Int64
    packet_size::UInt32
    max_delay::Cint
    flags::Cint
    probesize::Int64
    max_analyze_duration::Int64
    key::Ptr{UInt8}
    keylen::Cint
    nb_programs::UInt32
    programs::Ptr{Ptr{AVProgram}}
    video_codec_id::AVCodecID
    audio_codec_id::AVCodecID
    subtitle_codec_id::AVCodecID
    max_index_size::UInt32
    max_picture_buffer::UInt32
    nb_chapters::UInt32
    chapters::Ptr{Ptr{AVChapter}}
    metadata::Ptr{AVDictionary}
    start_time_realtime::Int64
    fps_probe_size::Cint
    error_recognition::Cint
    interrupt_callback::AVIOInterruptCB
    debug::Cint
    max_interleave_delta::Int64
    strict_std_compliance::Cint
    event_flags::Cint
    max_ts_probe::Cint
    avoid_negative_ts::Cint
    ts_id::Cint
    audio_preload::Cint
    max_chunk_duration::Cint
    max_chunk_size::Cint
    use_wallclock_as_timestamps::Cint
    avio_flags::Cint
    duration_estimation_method::AVDurationEstimationMethod
    skip_initial_bytes::Int64
    correct_ts_overflow::UInt32
    seek2any::Cint
    flush_packets::Cint
    probe_score::Cint
    format_probesize::Cint
    codec_whitelist::Cstring
    format_whitelist::Cstring
    internal::Ptr{AVFormatInternal}
    io_repositioned::Cint
    video_codec::Ptr{AVCodec}
    audio_codec::Ptr{AVCodec}
    subtitle_codec::Ptr{AVCodec}
    data_codec::Ptr{AVCodec}
    metadata_header_padding::Cint
    opaque::Ptr{Cvoid}
    control_message_cb::av_format_control_message
    output_ts_offset::Int64
    dump_separator::Ptr{UInt8}
    data_codec_id::AVCodecID
    open_cb::Ptr{Cvoid}
    protocol_whitelist::Cstring
    io_open::Ptr{Cvoid}
    io_close::Ptr{Cvoid}
    protocol_blacklist::Cstring
    max_streams::Cint
    skip_estimate_duration_from_pts::Cint
end

struct AVDeviceInfoList
end

struct AVDeviceCapabilitiesQuery
end

const AVOpenCallback = Ptr{Cvoid}

# begin enum AVTimebaseSource
const AVTimebaseSource = Cint
const AVFMT_TBCF_AUTO = -1 |> Int32
const AVFMT_TBCF_DECODER = 0 |> Int32
const AVFMT_TBCF_DEMUXER = 1 |> Int32
const AVFMT_TBCF_R_FRAMERATE = 2 |> Int32
# end enum AVTimebaseSource

const LIBAVFORMAT_VERSION_MAJOR = 58
const LIBAVFORMAT_VERSION_MINOR = 20
const LIBAVFORMAT_VERSION_MICRO = 100

# Skipping MacroDefinition: LIBAVFORMAT_VERSION_INT AV_VERSION_INT ( LIBAVFORMAT_VERSION_MAJOR , LIBAVFORMAT_VERSION_MINOR , LIBAVFORMAT_VERSION_MICRO )
# Skipping MacroDefinition: LIBAVFORMAT_VERSION AV_VERSION ( LIBAVFORMAT_VERSION_MAJOR , LIBAVFORMAT_VERSION_MINOR , LIBAVFORMAT_VERSION_MICRO )

# const LIBAVFORMAT_BUILD = LIBAVFORMAT_VERSION_INT

# Skipping MacroDefinition: LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY ( LIBAVFORMAT_VERSION )
# Skipping MacroDefinition: FF_API_COMPUTE_PKT_FIELDS2 ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_OLD_OPEN_CALLBACKS ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_LAVF_AVCTX ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_HTTP_USER_AGENT ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_HLS_WRAP ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_HLS_USE_LOCALTIME ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_LAVF_KEEPSIDE_FLAG ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_OLD_ROTATE_API ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_FORMAT_GET_SET ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_OLD_AVIO_EOF_0 ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_LAVF_FFSERVER ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_FORMAT_FILENAME ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_OLD_RTSP_OPTIONS ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_NEXT ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_DASH_MIN_SEG_DURATION ( LIBAVFORMAT_VERSION_MAJOR < 59 )
# Skipping MacroDefinition: FF_API_LAVF_MP4A_LATM ( LIBAVFORMAT_VERSION_MAJOR < 59 )

const FF_API_R_FRAME_RATE = 1


text:
using Base.Test
using MCMC

my_tests = ["test/test_syntax.jl",
            "test/test_diff.jl",
            "test/test_dists.jl"]

println("Running tests:")

for my_test in my_tests
    println(" * $(my_test)")
    include(my_test)
end

ext: jl


text:
export pitch2xml, xml2pitch

using Base.Meta, Base.Unicode
const PITCH_TO_NAME = Dict(
0=>"C", 1=>"C♯", 2=>"D", 3=>"D♯", 4=>"E", 5=>"F", 6=>"F♯", 7=>"G", 8=>"G♯", 9=>"A",
10 =>"A♯", 11=>"B")
const SHARPS = [1, 3, 6, 8, 10]
const NAME_TO_PITCH = Dict(
v => k for (v, k) in zip(values(PITCH_TO_NAME), keys(PITCH_TO_NAME)))

"""
    pitch2xml(pitch)

Return the musicxmls values of the given pitch (MIDI)

pitch::UInt8 : starting from C-1 = 0, adding one per semitone.

![Step Alter Octave on Staff](docs/pitchesonstaff.png)
![Pitch on Guitar](docs/pitchesonguitar.png)
![Pitch on Full Keyboard](docs/fullpiano.gif)

Modified from MIDI.jl

# Examples:
```julia
pitch = 0 # for C-1
step, alter, octave = pitch2xml()
```
"""
function pitch2xml(pitch::UInt8)
    intpitch = Int(pitch)
    # TODO: microtonals
    rem = mod(intpitch, 12)
    notename = PITCH_TO_NAME[rem]

    if rem in SHARPS
        step = notename[1]
        alter = 1 # using sharps by default (this is only for sound)
    else
        step = notename
        alter = 0
    end

    octave = (intpitch÷12)-1
    return step, alter, octave
end
################################################################
"""
    xml2pitch(step, alter, octave) -> Int
Return the pitch value of the given note

See [`Pitch`](@ref)

Modified from MIDI.jl

# Examples:
```julia
pitch = xml2pitch(step, alter, octave)
```
"""
function xml2pitch(step, alter, octave)

    pitch = NAME_TO_PITCH[step]

    return pitch + alter + 12(octave+1) # lowest possible octave is -1 but pitch starts from 0
end


text:
# plot PonctualDataset :
function vizualize(pds::PonctualDataset, series_var::Symbol, xys::Vararg{T,N}) where {T,N}
    dg = groupby(pds.data, series_var)
    colnames = names(pds.data)
    f = Figure()
    ax = Axis(f[1,1])
    for i in 1:length(dg)
        for j in eachindex(xys)
            idx = findfirst(colnames.== string(xys[j][1]))
            idy = findfirst(colnames.== string(xys[j][2]))
            scatter!(ax,-dg[i][:,idx], -dg[i][:,idy])
        end
    end
    f, ax
end

export vizualize

max_stars_repo_name: Leooop/DataFormatter

max_issues_repo_name: Leooop/DataFormatter

max_forks_repo_name: Leooop/DataFormatter


text:
"""
    UCB1 Implementation
    Based on: Figure-1, Auer, P., Bianchi, N. C., & Fischer, P. (2002). Finite time analysis of the multiarmed bandit problem. Machine Learning, 47, 235–256.
"""

type UCB1 <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    c::Float64

    cummReward::Vector{Float64}
    count::Vector{Int64}
    ucbIndices::Vector{Float64}

    function UCB1( noOfArms::Int, c::Real = √2 )
        new( noOfArms,
             0,
             0,
             c,
             zeros(Float64,noOfArms),
             zeros(Int64,noOfArms),
             zeros(Float64,noOfArms)
        )
    end
end

function get_arm_index( agent::UCB1 )
    if any(agent.count.==0)
        agent.lastPlayedArm =  rand( find(agent.count.==0) )
    else
        agent.lastPlayedArm = findmax(agent.ucbIndices)[2]
    end

    return agent.lastPlayedArm
end

function update_reward!( agent::UCB1, r::Real )

    # Update cummulative reward
    agent.cummReward[agent.lastPlayedArm] += r

    # Update play count for arm
    agent.count[agent.lastPlayedArm] += 1

    # Update number of steps played
    agent.noOfSteps += 1

    # Update UCB indices
    agent.ucbIndices = agent.cummReward./agent.count +
                        agent.c * sqrt.(log(agent.noOfSteps)./agent.count)

    nothing
end

function reset!( agent::UCB1 )
    agent.noOfSteps     = 0
    agent.lastPlayedArm = 0

    agent.cummReward    = zeros( Float64, agent.noOfArms )
    agent.count         = zeros( Int64, agent.noOfArms )
    agent.ucbIndices    = zeros( Float64, agent.noOfArms )

    nothing
end

function info_str( agent::UCB1, latex::Bool )
    if agent.c == √2
        return @sprintf( "UCB1" )
    else
        return @sprintf( "UCB1 (c=%3.2f)", agent.c )
    end
end

# """
#     UCB2 Implementation
#     Based on: Figure-2, Auer, P., Bianchi, N. C., & Fischer, P. (2002). Finite time analysis of the multiarmed bandit problem. Machine Learning, 47, 235–256.
# """
# type UCB2 <: BanditAlgorithmBase
#     noOfArms::Int64
#     noOfSteps::Int64
#     lastPlayedArm::Int64
#     α::Float64
#
#     cummReward::Vector{Float64}
#     count::Vector{Int64}
#
#     function UCB2( noOfArms::Int, α::Float64 )
#         new( noOfArms,
#              0,
#              0,
#              α,
#              zeros(Float64,noOfArms),
#              zeros(Int64,noOfArms)
#         )
#     end
# end

# function getArmIndex( agent::UCB2 )
#
# end
#
# function updateReward( agent::UCB2, r::Float64 )
#
# end

"""
    UCB-Normal Implementation
    Based on: Figure-4, Auer, P., Bianchi, N. C., & Fischer, P. (2002). Finite time analysis of the multiarmed bandit problem. Machine Learning, 47, 235–256.
"""

type UCBNormal <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    cummReward::Vector{Float64}
    count::Vector{Int64}
    cummSqReward::Vector{Float64}
    ucbIndices::Vector{Float64}

    function UCBNormal( noOfArms::Int )
        new( noOfArms,
             0,
             0,
             zeros(Float64,noOfArms),
             zeros(Int64,noOfArms),
             zeros(Float64,noOfArms),
             zeros(Float64,noOfArms)
        )
    end
end

function get_arm_index( agent::UCBNormal )
    tmp_lb      = ceil( 8 * log(agent.noOfSteps) )  # Quantity for comparison
    tmp_lbArms  = find( agent.count .< tmp_lb )     # Find index of under played arms
    if( size(tmp_lbArms,1) > 0 )    # if any machine is played less than ceil(8 log n), play that arm
        agent.lastPlayedArm = rand( tmp_lbArms )    # Randomly play one of those arms
    else    # else play arm with highest UCB index
        agent.lastPlayedArm = findmax(agent.ucbIndices)[2]
    end
    return agent.lastPlayedArm
end

function update_reward!( agent::UCBNormal, r::Real )
    # Update cummulative reward
    agent.cummReward[agent.lastPlayedArm] += r
    # Update squared cummulative reward
    agent.cummSqReward[agent.lastPlayedArm] += (r^2)
    # Update count for last played arm
    agent.count[agent.lastPlayedArm] += 1
    # Update number of steps
    agent.noOfSteps += 1
    # Update UCB indices
    agent.ucbIndices    = agent.cummReward ./ agent.count +
                            sqrt.(16 *
                                (agent.cummSqReward-((agent.cummReward).^2)./agent.count) ./ (agent.count-1) *
                                log(agent.noOfSteps-1)./agent.count )

    nothing
end

function reset!( agent::UCBNormal )
    agent.noOfSteps     = 0
    agent.lastPlayedArm = 0

    agent.cummReward    = zeros( Float64, agent.noOfArms )
    agent.count         = zeros( Int64, agent.noOfArms )
    agent.cummSqReward  = zeros( Float64, agent.noOfArms )
    agent.ucbIndices    = zeros( Float64, agent.noOfArms )

    nothing
end

function info_str( agent::UCBNormal, latex::Bool )
    return @sprintf( "UCB Normal" )
end

"""
    Discounted UCB
    Based on: Moulines, E., & Paristech, T. (2008). On Upper-Confidence Bound Policies for Non-Stationary Bandit Problems. arXiv Preprint, (2008), 1–24.
"""

type DUCB <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    γ::Float64                      # Discouting factor
    ξ::Float64                      # Confidence Scale Parameter
    cummReward::Vector{Float64}     # Cummulattive Reward from each arm
    discCumReward::Vector{Float64}  # Discounted reward
    count::Vector{Int64}            # Count of how many time an arm is pulled
    discCount::Vector{Float64}      # Discounted Count
    indices::Vector{Float64}        # Calculated Indices

    function DUCB( noOfArms::Int, γ::Float64, ξ::Float64 = 0.5 )
        new( noOfArms,
             0,
             0,
             γ,
             ξ,
             zeros(Float64,noOfArms),
             zeros(Float64,noOfArms),
             zeros(Int64,noOfArms),
             zeros(Float64,noOfArms),
             zeros(Float64,noOfArms)
        )
    end
end

function get_arm_index( agent::DUCB )
    if any(agent.count.==0)
        agent.lastPlayedArm =  rand( find(agent.count.==0) )
    else
        agent.lastPlayedArm = findmax(agent.indices)[2]
    end

    return agent.lastPlayedArm
end

function update_reward!( agent::DUCB, r::Real )
    # Update cummulative reward
    agent.cummReward[agent.lastPlayedArm] += r
    # Update play count for arm
    agent.count[agent.lastPlayedArm] += 1
    # Update number of steps played
    agent.noOfSteps += 1
    # Update discounted cummulative reward
    agent.discCumReward *= agent.γ                  # Discount for all arms
    agent.discCumReward[agent.lastPlayedArm] += r   # Update reward to last played arm
    # Update discounted count
    agent.discCount *= agent.γ
    agent.discCount[agent.lastPlayedArm] += 1
    # Update UCB indices
    agent.indices   = agent.discCumReward./agent.discCount +
                        2*sqrt.(agent.ξ*log(sum(agent.discCount))./agent.discCount)

    nothing
end

function reset!( agent::DUCB )
    agent.noOfSteps     = 0;
    agent.lastPlayedArm = 0;

    agent.cummReward    = zeros( Float64, agent.noOfArms );
    agent.discCumReward = zeros( Float64, agent.noOfArms );
    agent.count         = zeros( Int64, agent.noOfArms );
    agent.discCount     = zeros( Float64, agent.noOfArms );
    agent.indices       = zeros( Float64, agent.noOfArms );

    nothing
end

function info_str( agent::DUCB, latex::Bool )
    if latex
        return @sprintf( "Discounted-UCB\$(\\gamma = %4.3f,\\xi = %4.3f)\$", agent.γ, agent.ξ );
    else
        return @sprintf( "Discounted-UCB(γ = %4.3f, ξ = %4.3f)", agent.γ, agent.ξ );
    end
end

"""
    Sliding Window UCB
    Based on: Moulines, E., & Paristech, T. (2008). On Upper-Confidence Bound Policies for Non-Stationary Bandit Problems. arXiv Preprint, (2008), 1–24.
"""

type SWUCB <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    τ::Int64                        # Window Length
    ξ::Float64                      # Confidence Scale Parameter
    cummReward::Vector{Float64}     # Cummulative Reward from each arm
    count::Vector{Int64}            # Count of how many time an arm is pulled
    swCount::Vector{Int64}          # Count of how many times an arm is picked in this sliding Window
    armsInWindow::Vector{Int64}     # Vector of Arms picked in window
    rewardsInWindow::Vector{Float64}# Vector of Rewards corresponding to arms picked in this window
    swCumRew::Vector{Float64}       # Cummulative reward of arms in this window
    indices::Vector{Float64}        # Calculated Indices

    function SWUCB( noOfArms::Int, τ::Int64, ξ::Float64 = 2.0 )
        new( noOfArms,
             0,
             0,
             τ,
             ξ,
             zeros(Float64,noOfArms),
             zeros(Int64,noOfArms),
             zeros(Int64,noOfArms),
             Vector{Int64}(),
             Vector{Float64}(),
             zeros(Float64,noOfArms),
             zeros(Float64,noOfArms)
        )
    end
end

function get_arm_index( agent::SWUCB )
    if any(agent.swCount.==0)
        agent.lastPlayedArm =  rand( find(agent.swCount.==0) )
    else
        agent.lastPlayedArm = findmax(agent.indices)[2]
    end
    return agent.lastPlayedArm
end

function update_reward!( agent::SWUCB, r::Real )
    # Update cummulative reward
    agent.cummReward[agent.lastPlayedArm] += r
    # Update play count for arm
    agent.count[agent.lastPlayedArm] += 1
    # Update number of steps played
    agent.noOfSteps += 1

    # For sliding window
    push!( agent.armsInWindow, agent.lastPlayedArm )
    push!( agent.rewardsInWindow, r )
    agent.swCount[agent.lastPlayedArm]  += 1
    agent.swCumRew[agent.lastPlayedArm] += r
    if length(agent.armsInWindow) > agent.τ
        _arm    = shift!( agent.armsInWindow )
        _r      = shift!( agent.rewardsInWindow )
        agent.swCount[_arm]     -= 1
        agent.swCumRew[_arm]    -= _r
    end

    # Sanity check
    assert( length(agent.armsInWindow) == length(agent.rewardsInWindow) <= agent.τ )

    # Update UCB indices
    agent.indices = agent.swCumRew./agent.swCount +
                        sqrt.(agent.ξ*log(min(agent.noOfSteps,agent.τ))./agent.swCount)

    nothing
end

function reset!( agent::SWUCB )
    agent.noOfSteps         = 0
    agent.lastPlayedArm     = 0
    agent.cummReward        = zeros(Float64,agent.noOfArms)
    agent.count             = zeros(Int64,agent.noOfArms)
    agent.swCount           = zeros(Int64,agent.noOfArms)
    agent.armsInWindow      = Vector{Int64}()
    agent.rewardsInWindow   = Vector{Int64}()
    agent.indices           = zeros(Float64,agent.noOfArms)

    nothing
end

function info_str( agent::SWUCB, latex::Bool )
    if latex
        return @sprintf( "SW-UCB\$(\\tau = %3.2f,\\xi = %3.2f)\$", agent.τ, agent.ξ );
    else
        return @sprintf( "SW-UCB(τ = %3.2f, ξ = %3.2f)", agent.τ, agent.ξ );
    end
end

"""
    UCB-V: Variance Aware UCB Implementation
    Based on: Audibert, J. Y., Munos, R., & Szepesvári, C. (2009). Exploration-exploitation tradeoff using variance estimates in multi-armed bandits. Theoretical Computer Science, 410(19), 1876–1902. http://doi.org/10.1016/j.tcs.2009.01.016
"""

type UCBV <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    # Parameters
    ζ::Float64
    c::Float64
    b::Float64

    empiricalMean::Vector{Float64}
    empiricalVariance::Vector{Float64}
    count::Vector{Int64}
    ucbIndices::Vector{Float64}

    function UCBV( noOfArms::Int; ζ::Real = 1.0, c::Real = 1/3, b::Real = 1.0 )
        new( noOfArms,
             0,
             0,
             ζ,
             c,
             b,
             zeros(Float64,noOfArms),
             zeros(Float64,noOfArms),
             zeros(Int64,noOfArms),
             zeros(Float64,noOfArms)
        )
    end
end

function get_arm_index( agent::UCBV )
    if any(agent.count.==0)
        agent.lastPlayedArm =  rand( find(agent.count.==0) )
    else
        agent.lastPlayedArm = findmax(agent.ucbIndices)[2]
    end

    return agent.lastPlayedArm
end

function update_reward!( agent::UCBV, r::Real )

    # Save old mean
    μ = agent.empiricalMean[agent.lastPlayedArm]

    # Update cummulative reward
    agent.empiricalMean[agent.lastPlayedArm] = (agent.empiricalMean[agent.lastPlayedArm]*agent.count[agent.lastPlayedArm]+r) /
                                                    (agent.count[agent.lastPlayedArm]+1)
    # Update empirical Variance : Based on (30) in http://mathworld.wolfram.com/SampleVarianceComputation.html
    if agent.count[agent.lastPlayedArm] != 0
        agent.empiricalVariance[agent.lastPlayedArm] = (agent.count[agent.lastPlayedArm]-1)/agent.count[agent.lastPlayedArm] *
                                                            agent.empiricalVariance[agent.lastPlayedArm] +
                                                        1/(agent.count[agent.lastPlayedArm]+1) * (r-μ)^2
    end

    # Update play count for arm
    agent.count[agent.lastPlayedArm] += 1

    # Update number of steps played
    agent.noOfSteps += 1

    # Update UCB indices
    agent.ucbIndices = agent.empiricalMean +
                        sqrt.(2*agent.ζ*log(agent.noOfSteps)*agent.empiricalVariance./agent.count) +
                            3*agent.c*agent.b*log(agent.noOfSteps)./agent.count
    nothing
end

function reset!( agent::UCBV )
    agent.noOfSteps     = 0
    agent.lastPlayedArm = 0

    agent.empiricalMean     = zeros( Float64, agent.noOfArms )
    agent.empiricalVariance = zeros( Float64, agent.noOfArms )
    agent.count             = zeros( Int64, agent.noOfArms )
    agent.ucbIndices        = zeros( Float64, agent.noOfArms )

    nothing
end

function info_str( agent::UCBV, latex::Bool )
    if latex
        return @sprintf( "UCB-V(\$\\zeta=%3.2f,c=%3.2f,b=%3.2f\$)", agent.ζ, agent.c, agent.b )
    else
        return @sprintf( "UCB-V(ζ=%3.2f,c=%3.2f,b=%3.2f)", agent.ζ, agent.c, agent.b )
    end
end

"""
    Bayes-UCB Implementation
    Based on: Kaufmann, E., Cappé, O., & Garivier, A. (2012). On Bayesian upper confidence bounds for bandit problems. International Conference on Artificial Intelligence and Statistics, 592–600.
    Using 1 - 1/t as quantile
"""
type BayesUCB <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    count::Vector{Int64}
    α0::Vector{Int64}
    β0::Vector{Int64}
    cummSuccess::Vector{Int64}
    cummFailure::Vector{Int64}

    samplingDist::Vector{Distributions.Beta}

    function BayesUCB( noOfArms::Integer )
        new( noOfArms,
             0,
             0,
             zeros(Int64,noOfArms),
             ones(Int64,noOfArms),
             ones(Int64,noOfArms),
             zeros(Float64,noOfArms),
             zeros(Float64,noOfArms),
             fill(Distributions.Beta(1,1),noOfArms)
        )
    end

    function BayesUCB( armParams::Array{Tuple{Int64,Int64},1} )
        _noOfArms   = length( armParams )
        _priorDist  = [ Distributions.Beta(armParams[idx][1],armParams[idx][2]) for idx=1:_noOfArms ]
        new( _noOfArms,
             0,
             0,
             zeros(Int64,noOfArms),
             [ armParams[idx][1] for idx=1:_noOfArms ],
             [ armParams[idx][2] for idx=1:_noOfArms ],
             zeros(Float64,_noOfArms),
             zeros(Float64,_noOfArms),
             _priorDist
        )
    end
end

function get_arm_index( agent::BayesUCB )
    if any(agent.count.==0)
        agent.lastPlayedArm =  rand( find(agent.count.==0) )
    else
        agent.lastPlayedArm = findmax(  map(dist->quantile(dist,1-1/agent.noOfSteps),agent.samplingDist) )[2]
    end
    return agent.lastPlayedArm
end

function update_reward!( agent::BayesUCB, r::Int64 )
    # Update S and F
    agent.cummSuccess[agent.lastPlayedArm] += (r==0?0:1)
    agent.cummFailure[agent.lastPlayedArm] += (r==0?1:0)

    # Update Distributions
    agent.samplingDist[agent.lastPlayedArm] = Distributions.Beta(
                                                agent.cummSuccess[agent.lastPlayedArm]+agent.α0[agent.lastPlayedArm],
                                                agent.cummFailure[agent.lastPlayedArm]+agent.β0[agent.lastPlayedArm]
                                            )

    # Update play count for arm
    agent.count[agent.lastPlayedArm] += 1

    # Update time steps
    agent.noOfSteps += 1

    nothing
end

function reset!( agent::BayesUCB )
    agent.noOfSteps     = 0
    agent.lastPlayedArm = 0

    agent.count         = zeros( Int64, agent.noOfArms )
    agent.cummSuccess   = zeros( Float64, agent.noOfArms )
    agent.cummFailure   = zeros( Float64, agent.noOfArms )
    agent.samplingDist  = fill( Distributions.Beta(1,1), agent.noOfArms )

    nothing
end

function info_str( agent::BayesUCB, latex::Bool )
    return @sprintf( "Bayes UCB" )
end

"""
    KL-UCB Implementation
    Based on: Garivier, A., & Cappe, O. (2011). The KL-UCB Algorithm for Bounded Stochastic Bandits and Beyond. In CoLT (Vol. 24).
"""
type KLUCB <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    cummReward::Vector{Float64}
    count::Vector{Int64}
    ucbIndices::Vector{Float64}

    function KLUCB( noOfArms::Int )
        new( noOfArms,
             0,
             0,
             zeros(Float64,noOfArms),
             zeros(Int64,noOfArms),
             zeros(Float64,noOfArms)
        )
    end
end

function get_arm_index( agent::KLUCB )
    if any(agent.count.==0)
        agent.lastPlayedArm =  rand( find(agent.count.==0) )
    else
        agent.lastPlayedArm = findmax(agent.ucbIndices)[2]
    end

    return agent.lastPlayedArm
end

function update_reward!( agent::KLUCB, r::Real )

    # Update cummulative reward
    agent.cummReward[agent.lastPlayedArm] += r

    # Update play count for arm
    agent.count[agent.lastPlayedArm] += 1

    # Update number of steps played
    agent.noOfSteps += 1

    # Update UCB indices
    agent.ucbIndices = find_q.( agent.cummReward, agent.count, agent.noOfSteps )

    nothing
end

function reset!( agent::KLUCB )
    agent.noOfSteps     = 0
    agent.lastPlayedArm = 0

    agent.cummReward    = zeros( Float64, agent.noOfArms )
    agent.count         = zeros( Int64, agent.noOfArms )
    agent.ucbIndices    = zeros( Float64, agent.noOfArms )

    nothing
end

function info_str( agent::KLUCB, latex::Bool )
    return @sprintf( "KL-UCB" )
end

# Utility functions
function kl_div( p::Float64, q::Float64 )
    if p==q
        return 0.00
    elseif p == 0.0
        return -log(1-q)
    elseif p == 1.0
        return -log(q)
    else
        return p*log(p/q) + (1-p)*log((1-p)/(1-q))
    end
end

function kl_div( X1::Distributions.Bernoulli, X2::Distributions.Bernoulli )
   kl_div( X1.p, X2.p )
end

function find_q( sa, na, t; ϵ = 1e-5 )
    lQ = sa/na
    uQ = min( 1, sa/na+√(log(t)/na/2))      # Applying Pinkser's Inequality
    q̄ = 1.0
    q  = (lQ+uQ)/2
    while abs(q̄-q) > ϵ
        q̄  = q
        # print( @sprintf( "lQ = %f, q = %f, uQ = %f", lQ, q, uQ ) )
        klDiv = kl_div( sa/na, q )
        # println( @sprintf( "    kl = %f, d = %f", klDiv, log(t)/na ))
        if klDiv < (log(t)/na)
            lQ = q
        else
            uQ = q
        end
        q  = (lQ+uQ)/2
    end
    return lQ
end

"""
    M-UCB
    Based on: Cao, Y., Zheng, W., Kveton, B., & Xie, Y. (2018). Nearly Optimal Adaptive Procedure for Piecewise-Stationary Bandit: a Change-Point Detection Approach. Retrieved from http://arxiv.org/abs/1802.03692
"""

type MUCB <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    # Algorithm params
    w::Int              # Test window length - Should be a even number
    b::Float64          # Test threshold
    γ::Float64          # Expoloration parameter

    # Internal
    τ::Int              # Last detected change point
    _ucb::UCB1          # UCB agent to run
    rew::Vector{Vector{Float64}}    # Past rewards from each arm

    function MUCB( noOfArms::Int, w::Int, b::Float64, γ::Float64 )
        new(
            noOfArms,
            0,
            0,
            w,
            b,
            γ,
            0,
            UCB1(noOfArms),
            [ Vector{Float64}() for k = 1:noOfArms ]
        )
    end
end

function get_arm_index( agent::MUCB )
    A = (agent.noOfSteps-agent.τ) % floor(agent.noOfArms/agent.γ)
    if A < agent.noOfArms   # Uniform Exploration
        agent.lastPlayedArm = A+1
        agent._ucb.lastPlayedArm = agent.lastPlayedArm
    else
        agent.lastPlayedArm = get_arm_index( agent._ucb )
    end
    return agent.lastPlayedArm
end

function update_reward!( agent::MUCB, r::Real )
    agent.noOfSteps += 1
    push!( agent.rew[agent.lastPlayedArm], r )
    update_reward!( agent._ucb, r )
    if length(agent.rew[agent.lastPlayedArm]) > agent.w # If the window length is reached
        # Then discard the oldest reward
        shift!( agent.rew[agent.lastPlayedArm] )
        # Also do the test
        if mucb_cd( agent.rew[agent.lastPlayedArm], agent.b )   # If test detects a change
            # Reset UCB1
            reset!( agent._ucb )
            # Update last detection point
            agent.τ = agent.noOfSteps
            agent.rew = [ Vector{Float64}() for k = 1:agent.noOfArms ]
        end
    end
    nothing
end

function reset!( agent::MUCB )
    agent.noOfSteps     = 0
    agent.lastPlayedArm = 0
    agent.τ             = 0
    agent.rew           = [ Vector{Float64}() for k = 1:agent.noOfArms ]

    reset!( agent._ucb )    # Reset internal UCB1 agent also
end

function info_str( agent::MUCB, latex::Bool )
    if latex
        return @sprintf( "M-UCB( w = %d, b = %4.3f, \$\\gamma\$ = %4.3f )", agent.w, agent.b, agent.γ )
    else
        return @sprintf( "M-UCB( w = %d, b = %4.3f, γ = %4.3f )", agent.w, agent.b, agent.γ )
    end
end

#=
    Change Detection algorithm for M-UCB
        b - detection threshold
        rew - list of rewards; must be of length 'w' an even number
=#
function mucb_cd( rew::Vector{Float64}, b::Float64 )
    l = length( rew )
    assert( l%2 == 0 )
    return abs( sum(rew[1:Int(l/2)])-sum(rew[Int(l/2)+1:end]) ) > b
end


text:
"""
    CallbackFunction()

Set a generic Xpress callback function.
"""

struct CallbackFunction <: MOI.AbstractCallback end

function MOI.set(model::Optimizer, ::CallbackFunction, ::Nothing)
    if model.callback_data !== nothing
        removecboptnode(model.inner, C_NULL, C_NULL)
        model.callback_data = nothing
    end
    model.has_generic_callback = false
    return
end

function MOI.set(model::Optimizer, ::CallbackFunction, f::Function)
    if model.callback_data !== nothing
        Xpress.removecboptnode(model.inner, C_NULL, C_NULL)
        model.callback_data = nothing
    end
    model.has_generic_callback = true
    # Starting with this callback to test
    model.callback_data = set_callback_optnode!(model.inner, (cb_data) -> begin
        model.callback_state = CB_GENERIC
        f(cb_data)
        model.callback_state = CB_NONE
    end)
    return
end
MOI.supports(::Optimizer, ::CallbackFunction) = true

function get_cb_solution(model::Optimizer, model_inner::XpressProblem)
    reset_callback_cached_solution(model)
    Xpress.Lib.XPRSgetlpsol(model_inner,
            model.callback_cached_solution.variable_primal,
            model.callback_cached_solution.linear_primal,
            model.callback_cached_solution.linear_dual,
            model.callback_cached_solution.variable_dual)
    return
end

function applycuts(opt::Optimizer, model::XpressProblem)
    itype = Cint(1)
    interp = Cint(-1) # Get all cuts
    delta = 0.0#Xpress.Lib.XPRS_MINUSINFINITY
    ncuts = Array{Cint}(undef,1)
    size = Cint(length(opt.cb_cut_data.cutptrs))
    mcutptr = Array{Xpress.Lib.XPRScut}(undef,size)
    dviol = Array{Cdouble}(undef,size)
    getcpcutlist(model, itype, interp, delta, ncuts, size, mcutptr, dviol) # requires an availabel solution
    loadcuts(model, itype, interp, ncuts[1], mcutptr)
    return ncuts[1] > 0
end

# ==============================================================================
#    MOI callbacks
# ==============================================================================

function default_moi_callback(model::Optimizer)
    return (cb_data) -> begin
        get_cb_solution(model, cb_data.model)
        if model.heuristic_callback !== nothing
            model.callback_state = CB_HEURISTIC
            # only allow one heuristic solution per LP optimal node
            if Xpress.getintattrib(cb_data.model, Xpress.Lib.XPRS_CALLBACKCOUNT_OPTNODE) > 1
                return
            end
            model.heuristic_callback(cb_data)
        end
        if model.user_cut_callback !== nothing
            model.callback_state = CB_USER_CUT
            # apply stored cuts if any
            if length(model.cb_cut_data.cutptrs) > 0
                added = applycuts(model, cb_data.model)
                if added
                    return
                end
            end
            # only allow one user cut solution per LP optimal node
            # limiting two calls to guarantee th user has a chance to add
            # a cut. if the user cut is loose the problem will be resolved anyway.
            if Xpress.getintattrib(cb_data.model, Xpress.Lib.XPRS_CALLBACKCOUNT_OPTNODE) > 2
                return
            end
            model.user_cut_callback(cb_data)
        end
        if model.lazy_callback !== nothing
            model.callback_state = CB_LAZY
            # add previous cuts if any
            # to gurantee the user is dealing with a optimal solution
            # feasibile for exisitng cuts
            if length(model.cb_cut_data.cutptrs) > 0
                added = applycuts(model, cb_data.model)
                if added
                    return
                end
            end
            model.lazy_callback(cb_data)
        end
    end
    return
end

function MOI.get(model::Optimizer, attr::MOI.CallbackNodeStatus{CallbackData})
    if check_moi_callback_validity(model)
        mip_infeas = Xpress.getintattrib(attr.callback_data.model, Xpress.Lib.XPRS_MIPINFEAS)
        if mip_infeas == 0
            return MOI.CALLBACK_NODE_STATUS_INTEGER
        elseif mip_infeas > 0
            return MOI.CALLBACK_NODE_STATUS_FRACTIONAL
        end
    end
    return MOI.CALLBACK_NODE_STATUS_UNKNOWN
end

function MOI.get(
    model::Optimizer,
    ::MOI.CallbackVariablePrimal{CallbackData},
    x::MOI.VariableIndex
)
    return model.callback_cached_solution.variable_primal[_info(model, x).column]
end

# ==============================================================================
#    MOI.UserCutCallback  & MOI.LazyConstraint
# ==============================================================================

function MOI.set(model::Optimizer, ::MOI.UserCutCallback, cb::Function)
    model.user_cut_callback = cb
    return
end

function MOI.set(model::Optimizer, ::MOI.LazyConstraintCallback, cb::Function)
    model.lazy_callback = cb
    return
end

MOI.supports(::Optimizer, ::MOI.UserCutCallback) = true
MOI.supports(::Optimizer, ::MOI.UserCut{CallbackData}) = true

MOI.supports(::Optimizer, ::MOI.LazyConstraintCallback) = true
MOI.supports(::Optimizer, ::MOI.LazyConstraint{CallbackData}) = true

function MOI.submit(
    model::Optimizer,
    cb::CB,
    f::MOI.ScalarAffineFunction{Float64},
    s::Union{MOI.LessThan{Float64}, MOI.GreaterThan{Float64}, MOI.EqualTo{Float64}}
) where CB <: Union{MOI.UserCut{CallbackData},MOI.LazyConstraint{CallbackData}}

    model_cb = cb.callback_data.model
    model.cb_cut_data.submitted = true
    if model.callback_state == CB_HEURISTIC
        cache_exception(model,
            MOI.InvalidCallbackUsage(MOI.HeuristicCallback(), cb))
        Xpress.interrupt(model_cb, Xpress.Lib.XPRS_STOP_USER)
        return
    elseif model.callback_state == CB_LAZY && CB <: MOI.UserCut{CallbackData}
        cache_exception(model,
            MOI.InvalidCallbackUsage(MOI.LazyConstraintCallback(), cb))
        Xpress.interrupt(model_cb, Xpress.Lib.XPRS_STOP_USER)
        return
    elseif model.callback_state == CB_USER_CUT && CB <: MOI.LazyConstraint{CallbackData}
        cache_exception(model,
            MOI.InvalidCallbackUsage(MOI.UserCutCallback(), cb))
        Xpress.interrupt(model_cb, Xpress.Lib.XPRS_STOP_USER)
        return
    elseif !iszero(f.constant)
        cache_exception(model,
            MOI.ScalarFunctionConstantNotZero{Float64, typeof(f), typeof(s)}(f.constant))
        Xpress.interrupt(model_cb, Xpress.Lib.XPRS_STOP_USER)
        return
    end
    indices, coefficients = _indices_and_coefficients(model, f)
    sense, rhs = _sense_and_rhs(s)

    mtype = Int32[1] # Cut type
    mstart = Int32[0, length(indices)]
    mindex  = Array{Xpress.Lib.XPRScut}(undef,1)
    ncuts = Cint(1)
    ncuts_ptr = Cint[0]
    nodupl = Cint(2) # Duplicates are excluded from the cut pool, ignoring cut type
    sensetype = Cchar[Char(sense)]
    drhs = Float64[rhs]
    indices .-= 1
    mcols = Cint.(indices)
    interp = Cint(-1) # Load all cuts

    ret = Xpress.storecuts(model_cb, ncuts, nodupl, mtype, sensetype, drhs, mstart, mindex, mcols, coefficients)
    Xpress.loadcuts(model_cb, mtype[], interp, ncuts, mindex)
    push!(model.cb_cut_data.cutptrs, mindex[1])
    model.cb_cut_data.cutptrs
    return
end

# ==============================================================================
#    MOI.HeuristicCallback
# ==============================================================================

function MOI.set(model::Optimizer, ::MOI.HeuristicCallback, cb::Function)
    model.heuristic_callback = cb
    return
end
MOI.supports(::Optimizer, ::MOI.HeuristicCallback) = true

function MOI.submit(
    model::Optimizer,
    cb::MOI.HeuristicSolution{CallbackData},
    variables::Vector{MOI.VariableIndex},
    values::MOI.Vector{Float64}
)
    model_cb = cb.callback_data.model::Xpress.XpressProblem
    model_cb2 = cb.callback_data.model_root::Xpress.XpressProblem
    if model.callback_state == CB_LAZY
        cache_exception(model,
            MOI.InvalidCallbackUsage(MOI.LazyConstraintCallback(), cb))
        Xpress.interrupt(model_cb, Xpress.Lib.XPRS_STOP_USER)
        return
    elseif model.callback_state == CB_USER_CUT
        cache_exception(model,
            MOI.InvalidCallbackUsage(MOI.UserCutCallback(), cb))
        Xpress.interrupt(model_cb, Xpress.Lib.XPRS_STOP_USER)
        return
    end
    ilength = length(variables)
    mipsolval = fill(NaN,ilength)
    mipsolcol = fill(NaN,ilength)
    count = 1
    for (var, value) in zip(variables, values)
        mipsolcol[count] = convert(Cint,_info(model, var).column - 1)
        mipsolval[count] = value
        count += 1
    end
    mipsolcol = Cint.(mipsolcol)
    mipsolval = Cfloat.(mipsolval)
    if ilength == MOI.get(model, MOI.NumberOfVariables())
        mipsolcol = C_NULL
    end
    addmipsol(model_cb, ilength, mipsolval, mipsolcol, C_NULL)
    return MOI.HEURISTIC_SOLUTION_UNKNOWN
end
MOI.supports(::Optimizer, ::MOI.HeuristicSolution{CallbackData}) = true

function cache_exception(model::Optimizer, e::Exception)
    model.cb_exception = e
    return
end


text:
using SuiteSparseGraphBLAS
using SparseArrays
using Test
using Random
using ChainRulesTestUtils
using ChainRulesCore
using FiniteDifferences
using SuiteSparseGraphBLAS
Random.seed!(1)

function include_test(path)
    println("Testing $path:")
    @time include(path)
end

function ChainRulesTestUtils.rand_tangent(
    rng::AbstractRNG,
    x::GBMatrix{T}
) where {T <: Union{AbstractFloat, Complex}}
    n = nnz(x)
    v = rand(rng, -9:0.01:9, n)
    I, J, _ = findnz(x)
    return GBMatrix(I, J, v; nrows = size(x, 1), ncols = size(x, 2))
end

function ChainRulesTestUtils.rand_tangent(
    rng::AbstractRNG,
    x::GBVector{T}
) where {T <: Union{AbstractFloat, Complex}}
    n = nnz(x)
    v = rand(rng, -9:0.01:9, n)
    I, _ = findnz(x)
    return GBVector(I, v; nrows = size(x, 1))
end

# Inefficient, but doesn't matter, only doing small matrices
function FiniteDifferences.to_vec(M::SparseMatrixCSC)
    x, back = FiniteDifferences.to_vec(Matrix(M))
    function backtomat(xvec)
        M2 = back(xvec)
        M_out = copy(M)
        nz = findnz(M_out)
        for j ∈ nz[1], i ∈ nz[2]
            M_out[i,j] = M2[i, j]
        end
        return M_out
    end
    return x, backtomat
end
function FiniteDifferences.to_vec(M::SparseVector)
    x, back = FiniteDifferences.to_vec(Vector(M))
    function backtovec(xvec)
        M2 = back(xvec)
        M_out = copy(M)
        nz = findnz(M_out)
        for i ∈ nz[1]
            M_out[i] = M2[i]
        end
        return M_out
    end
    return x, backtovec
end
ChainRulesTestUtils.rand_tangent(::AbstractRNG, ::SuiteSparseGraphBLAS.AbstractOp) = NoTangent()

println("Testing SuiteSparseGraphBLAS.jl")
@testset "SuiteSparseGraphBLAS" begin

    include_test("gbarray.jl")
    include_test("operations.jl")
    include_test("chainrules/chainrulesutils.jl")
    include_test("chainrules/mulrules.jl")
    include_test("chainrules/ewiserules.jl")
    include_test("chainrules/selectrules.jl")
    include_test("chainrules/constructorrules.jl")
    include_test("chainrules/maprules.jl")
    include_test("sparsemat.jl")
end


text:
Maybe(T)=Union{T,Nothing}
# geometric types
abstract type Geom end
struct Geom2D <: Geom end
struct Geom3D <: Geom end

# Smoother types
abstract type Smoother end

"""
    SwitchSmoother <: Smoother

switch smoother based on tanh function

# Fields
- 'steepness': steepness of the transition

"""
@kwdef struct SwitchSmoother <: Smoother
    x_one_percent::Float64 = 1e-3
end

"tanh smoother : goes from 0 to 1 when x goes from negative to positive, steepness is a field of the instanciated type"
function (ss::SwitchSmoother)(x)
    k = atanh(2*(0.99-0.5))/ss.x_one_percent
    0.5 + 0.5*tanh(k * x)
end

"tanh smoother, switches from v1 to v2 when x goes from negative to positive, steepness is a field of the instanciated type"
(ss::SwitchSmoother)(v1,v2,x) = (1 - ss(x))*v1 + ss(x)*v2

"tanh smoother, switches from v1 to v2 when x = (v2-v1)/v2 goes from negative to positive, steepness is a field of the instanciated type"
(ss::SwitchSmoother)(v1,v2) = (1 - ss(x))*v1 + ss(x)*v2

# Numerical setup types
abstract type DeformationControl end
@kwdef struct ConstantStrainRate{tE<:Real} <: DeformationControl
    ϵ̇::tE = 1e-5
end
@kwdef struct ConstantStress{tS<:Real} <: DeformationControl
    s::tS = 1e8
end

abstract type NumericalSetup end
@kwdef struct TriaxialSetup{tG<:Geom,tC<:DeformationControl,tP<:Real} <: NumericalSetup
    geom::tG = Geom3D() # geometric approximation of the problem
    control::tC = ConstantStrainRate()
    pc::tP = 1e5
end

# weakening types
abstract type Weakening end
@kwdef struct LinearWeakening{T<:Real} <: Weakening
    γ::T = 1.0 # max total weakening ∈ [0,1]
end
@kwdef struct AsymptoticWeakening{T<:Real} <: Weakening
    γ::T = 1.0
end
struct EnergyBasedWeakening <: Weakening end

# yield stress types
abstract type YieldStress end
@kwdef struct ConstantYieldStress{T<:Real} <: YieldStress
    val::T = 0.0
end
(σy::ConstantYieldStress)() = σy.val
(σy::ConstantYieldStress)(p) = σy()

@kwdef struct CoulombYieldStress{tμ<:Real,tC<:Real} <: YieldStress
    μ::tμ = 0.6
    C::tC = 0.0
end
(σy::CoulombYieldStress)(p) = (ϕ = atan(σy.μ) ; p*sin(ϕ) + σy.C*cos(ϕ))

# damage growth types
abstract type DamageGrowth end
@kwdef struct SimpleCharlesLaw{tTd<:Real,tS<:Real,tM<:Real,tY<:YieldStress} <: DamageGrowth
    Td::tTd = 4.5e6
    S::tS = 4.5e6
    m::tM = 4.0
    σy::tY = CoulombYieldStress() # instance of YieldStress subtype
end

abstract type MicroMechanicalCharlesLaw <: DamageGrowth end
"Damage mechanics where KI is formulated using stress invariants"
@kwdef struct InvariantsKICharlesLaw <: MicroMechanicalCharlesLaw
    r::Rheology = DSB.Rheology() # Type containing micromechanical parameters defined in DamagedShearBand.jl along with damage functions used to evaluate KI
end
"Damage mechanics where KI is formulated using principal stresses, only works in the 2D case"
@kwdef struct PrincipalKICharlesLaw <: MicroMechanicalCharlesLaw
    r::Rheology = DSB.Rheology() # Type containing micromechanical parameters defined in DamagedShearBand.jl along with damage functions used to evaluate KI
end

abstract type Elasticity end
@kwdef struct IncompressibleElasticity{tG<:Real} <: Elasticity
    G::tG = 4e9
end

# Plasticity related types
#TODO : !!!!!!!!!
abstract type PlasticityThreshold end
@kwdef struct MinViscosityThreshold{tS<:Maybe(SwitchSmoother)} <: PlasticityThreshold
    smoother::tS = nothing
end

@kwdef struct DamageThreshold{tS<:Maybe(SwitchSmoother),T<:Real} <: PlasticityThreshold
    smoother::tS = nothing
    value::T = 0.99
end

@kwdef struct Plasticity{tC<:PlasticityThreshold,tY<:YieldStress}
    threshold::tC = DamageThreshold(0.95)
    σy::tY = CoulombYieldStress() # instance of YieldStress subtype
end

# Constitutive model type
@kwdef struct ConstitutiveModel{tW<:Weakening,tD<:DamageGrowth,tE<:Elasticity,tP<:Maybe(Plasticity)}
    weakening::tW = LinearWeakening()# elastic modulus weakening type
    damage::tD = SimpleCharlesLaw()# Damage growth type
    elasticity::tE = IncompressibleElasticity() # Elasticity
    plasticity::tP = nothing
end

# Model type
@kwdef struct Model{tCM<:ConstitutiveModel,tNS<:NumericalSetup}
    cm::tCM = ConstitutiveModel()
    setup::tNS = TriaxialSetup()
end
#Model{tCM,tNS}(cm,setup) where {tCM,tNS} = Model(cm,setup)

# ALIASES
const M = Model
const NS = NumericalSetup
const TS = TriaxialSetup
const DC = DeformationControl
const CSR = ConstantStrainRate
const CS = ConstantStress
const CM = ConstitutiveModel
const W = Weakening
const LW = LinearWeakening
const AW = AsymptoticWeakening
const EBW = EnergyBasedWeakening
const ConstY = ConstantYieldStress
const CoulombY = CoulombYieldStress
const SD = SimpleCharlesLaw
const MD = MicroMechanicalCharlesLaw
const IKI = InvariantsKICharlesLaw
const PKI = PrincipalKICharlesLaw
const IE = IncompressibleElasticity
const P = Plasticity
const MVT = MinViscosityThreshold
const DT = DamageThreshold

max_stars_repo_name: Leooop/SimpleDamage

max_issues_repo_name: Leooop/SimpleDamage

max_forks_repo_name: Leooop/SimpleDamage


text:
module _NumberTheory

using Brainstorm._Math._NumberTheory
using Base.Test
using Brainstorm: dropwhile
using DataStructures: SortedDict
using IterTools: take

include("primes.jl")
include("factor.jl")
include("mod.jl")
include("decimal.jl")
include("fibonacci.jl")
include("hailstone.jl")
include("triangle.jl")
include("pentagon.jl")
include("hexagon.jl")
include("confrac.jl")
include("diophantine.jl")

function test_all()
    test_primes_all()
    test_factor_all()
    test_mod_all()
    test_decimal_all()
    test_fibonacci_all()
    test_hailstone_all()
    test_triangle_all()
    test_pentagon_all()
    test_hexagon_all()
    test_confrac_all()
    test_diophantine_all()
end

end


text:
##############################################################
"""
$(SIGNATURES)

Calculation of Bernoulli function via Horner scheme based on Taylor
coefficients around 0.
"""

function bernoulli_horner(x)
    y=x/47_900_160
    y=x*y
    y=x*(-1/1_209_600+y)
    y=x*y
    y=x*(1/30_240+y)
    y=x*y
    y=x*(-1/720+y)
    y=x*y
    y=x*(1/12+y)
    y=x*(-1/2+y)
    y=1+y
end

##############################################################
"""
$(SIGNATURES)

Bernoulli function ``B(x)=\\frac{x}{e^x-1}`` for exponentially
fitted upwinding.

The name `fbernoulli` has been chosen to avoid confusion
with Bernoulli from JuliaStats/Distributions.jl

Returns a real number containing the result.
"""
function fbernoulli(x)
    expx=exp(x)
    if expx<0.99999
        return x/(expx-1)
    elseif expx < 1.00001
        return bernoulli_horner(x)
    else
        return x/(expx-1)
    end
end

##############################################################

const etruncmax = 100.0
const etruncmin = -100.0

function trexp(x)
  if(x<etruncmin)
    return 1.0/(exp(etruncmin)*(-x+etruncmin+1.0));
  elseif (x<etruncmax)
    return exp(x);
  else
      return exp(etruncmax)*(x-etruncmax+1.0);
  end
end

"""
$(SIGNATURES)

Bernoulli function ``B(x)=\\frac{x}{e^x-1}`` for exponentially
fitted upwind, joint evaluation for positive and negative
argument

Usually, we need ``B(x), B(-x)`` togehter,
and it is cheaper to calculate them together.

Returns two real numbers containing the result for argument
`x` and argument `-x`.

"""
function fbernoulli_pm(x)
    expx=exp(x)
    if abs(expx-1)>0.00001
        bp=x/(expx-1)
        bm=x/(1-1/expx)
        return bp,bm
    else
        y=bernoulli_horner(x)
        return y,x+y
    end
end


text:
using Artifacts: @artifact_str

function hfun_bar(vname)
    val = Meta.parse(vname[1])
    return round(sqrt(val), digits=2)
end

function hfun_m1fill(vname)
    var = vname[1]
    return pagevar("index", var)
end

function lx_baz(com, _)
    # keep this first line
    brace_content = Franklin.content(com.braces[1]) # input string
    # do whatever you want here
    return uppercase(brace_content)
end

"""
    lx_readhtml(com, _)

Embed a Pluto notebook via:
https://github.com/rikhuijzer/PlutoStaticHTML.jl
"""
function lx_readhtml(com, _)
    file = string(Franklin.content(com.braces[1]))::String
    dir = joinpath("notebooks")
    html_path = joinpath(dir, "$file.html")
    jl_path = joinpath(dir, "$file.jl")

    return """
        ```julia:pluto
        # hideall

        using PlutoStaticHTML: notebook2html

        path = "$html_path"
        html = read(path, String)
        println("~~~\n\$html\n~~~\n")
        println("_To run this blog post locally, open [this notebook](/$jl_path) with Pluto.jl._")
        ```
        \\textoutput{pluto}
        """
end

"""
    hfun_artifact(params::Vector{String})::String

Return a (relative) URL to an artifact.
For example, for JuliaMono, use
```
{{artifact JuliaMono juliamono-0.042 webfonts JuliaMono-Regular.woff2}}
```
where JuliaMono is the name of the Artifact in Artifacts.toml.

This method copies the artifact, puts it into `_assets` and returns a relative URL.
"""
function hfun_artifact(params::Vector{String})::String
    name = params[1]
    dir = @artifact_str(name)
    from = joinpath(dir, params[2:end]...)
    @assert isfile(from)
    location = params[2:end]
    to = joinpath(@__DIR__, "__site", "assets", name, location...)
    mkpath(dirname(to))
    cp(from, to; force=true)
    parts = ["assets"; name; location]
    url = string('/', join(parts, '/'))
    return url
end

function hfun_menuitem(params::Vector{String})::String
    @assert length(params) == 2
    location, title = params

    rpath, _ = Franklin.LOCAL_VARS["fd_rpath"] # "tutorials/linear-model.md"
    current_location, _ = splitext(rpath)
    active = current_location == location ? "active" : ""

    pre = "
"
    link = "$title"
    post = "
"
    return string(pre, link, post)
end

max_stars_repo_name: VEZY/PlantBiophysics-paper

max_issues_repo_name: VEZY/PlantBiophysics-paper

max_forks_repo_name: rikhuijzer/JuliaTutorialsTemplate


text:
module Day5

using Advent: save_input

get_seatnum(line) = reduce((x, y) -> (x << 1) | (y == 'R') | (y == 'B'), line; init = 0)

solve_a(filename) = maximum(get_seatnum, eachline(filename))

function solve_b(filename)
    seats = Iterators.map(get_seatnum, eachline(filename)) |> BitSet
    low, high = extrema(seats)
    setdiff(BitSet(low:high), seats)
end

solve(filename = save_input(2020, 5)) = solve_a(filename), solve_b(filename)
solve_big() = solve("day5_big.in")

end

max_stars_repo_name: AnAverageHuman/competitive

max_issues_repo_name: AnAverageHuman/competitive

max_forks_repo_name: AnAverageHuman/competitive


text:
# SDP example to find the maximum eigenvalue of a symmetric matrix A

# from: https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15859-f11/www/notes/lecture12.pdf
# Suppose A has eigenvalues λ1 ≥ λ2 . . . ≥ λn. Then the matrix tI − A has
# eigenvalues t−λ1, t−λ2, . . . , t−λn. Note that tI −A is psd exactly when all these eigenvalues
# are non-negative, and this happens for values t ≥ λ1
# This immediately gives us that
# λ1 = min{t | s.t. tI − A ≥ 0}
using Test
using COSMO, SparseArrays, LinearAlgebra, Random

nn = 10
rng = MersenneTwister(7232)

@testset "Max Eigenvalue Problem with Random Matrices" begin

  for iii = 1:nn
    # generate symmetric test matrix A
    r = rand(rng, 2:30)
    A = Symmetric(randn(rng, r, r))

    # solve the dual problem
    c = -vec(A)
    A1 = -vec(sparse(1.0I, r, r))'
    A2 = sparse(1.0I, r^2, r^2)
    b1 = 1.
    b2 = zeros(r^2)

    constraint1 = COSMO.Constraint(A1, b1, COSMO.ZeroSet)
    constraint2 = COSMO.Constraint(A2, b2, COSMO.PsdCone)
    P = spzeros(r^2, r^2)

    settings = COSMO.Settings(check_termination=1, scaling = 0)

    model = COSMO.Model()
    assemble!(model, P, c,[constraint1; constraint2], settings = settings)
    res = COSMO.optimize!(model);

    println("$(iii)/$(nn) completed! Size of A: $(r), Number of Iterations $(res.iter).")

    # true solution
    λMaxTrue = maximum(eigen(A).values)
    @test abs(res.y[1] - λMaxTrue) < 1e-2
   end
end
nothing


text:
##################################################################################
# This file is part of StateSpaceEcon.jl
# BSD 3-Clause License
# Copyright (c) 2020, Bank of Canada
# All rights reserved.
##################################################################################

abstract type FinalCondition end
abstract type NoFinalCondition <: FinalCondition end
struct FCNone <: NoFinalCondition end
abstract type HasFinalCondition <: FinalCondition end
struct FCGiven <: HasFinalCondition end
struct FCMatchSSLevel <: HasFinalCondition end
struct FCMatchSSRate <: HasFinalCondition end
struct FCConstRate <: HasFinalCondition end

const fcnone = FCNone()
const fcgiven = FCGiven()
const fclevel = FCMatchSSLevel()
const fcslope = FCMatchSSRate()
const fcrate = FCMatchSSRate()
const fcnatural = FCConstRate()

export FinalCondition
export NoFinalCondition
export HasFinalCondition
export FCNone, fcnone
export FCGiven, fcgiven
export FCMatchSSLevel, fclevel
export FCMatchSSRate, fcslope, fcrate
export FCConstRate, fcnatural
export setfc

function setfc(m::Model, fc::FinalCondition)
    ret = similar(m.allvars, FinalCondition)
    for (vi, v) in enumerate(m.allvars)
        ret[vi] = isshock(v) || isexog(v) ? fcnone : fc
    end
    return ret
end

function setfc!(fc_vec::AbstractVector{FinalCondition}, m::Model, v::ModelVariable, new_fc::FinalCondition)
    @assert m.allvars[v.index] == v
    fc_vec[v.index] = new_fc
    return fc_vec
end

function setfc!(fc_vec::AbstractVector{FinalCondition}, m::Model, v::Symbol, new_fc::FinalCondition)
    vi = indexin([v], m.allvars)[1]
    if vi === nothing
        throw(ArgumentError("Unknown variable $(Symbol(v))."))
    end
    @assert vi == m.allvars[vi].index
    fc_vec[vi] = new_fc
    return fc_vec
end


text:
function newav(d::DataBase, tg, av, ms)
    @unpack T, Av, K, groups = d
    from_id = ms["message"]["from"]["id"]
    Av[from_id] = Dict("first_name" => ms["message"]["from"]["first_name"],
                      "token" => 4, "step" => "00", "id" => from_id)
    if haskey(ms["message"]["from"],"last_name")
        Av[from_id]["last_name"] = ms["message"]["from"]["last_name"]
    end
    av = Av[from_id]
    for pathkey in keys(T)
        push!(T[pathkey]["dav_id"],av["id"])
    end
    println(string("Registered new member: ", av["first_name"]))
    msg = string("Sveiki/Здравствуйте, ", kas2nkas(av["first_name"]), "! Esu robotas Talkon. Aš padedu kaip taksi išsikviesti (arba suteikti) pagalbą./Я робот Talkon. Я допомагаю як таксі викликати (або надати) допомогу./Я робот Талкон. Помогаю как такси вызвать (или оказать) помощь.")
    sendMessage(tg, chat_id = from_id, text = msg)
    sendMessage(tg, chat_id = from_id, text = welcometext())
    tbegin(tg, av)
    #keyboard = [["Taip","invitecodeyesno(1)","Ne","invitecodeyesno(0)"]]
    #sendMessage(chat_id = from_id,text = "Ar turite pakvietimo kodą?",reply_markup = tik(keyboard))
    return av
end

function tbegin(tg, av)
    av["step"] = "0"
    av["path"] = ["0"]
    msg = "Galite klausti ir prašyti pagalbos arba jei galite suteikti pagalbą žymėti sritis kuriose galite pagelbėti./Ви можете попросити і попросити про допомогу або, якщо ви можете надати допомогу, позначити місця, де ви можете допомогти."
    keyboard = [["Klausti/Спитати/Спросить", "trequest()", "Žymėti/Позначте/Отметить", "tenter()"]]
    sendMessage(tg, chat_id = av["id"], text = msg, reply_markup = tik(keyboard))

    return
end

function welcometext()
    txt="""Ši priemonė skirta padėti suvesti klausiantįjį su žinančiu. Svarbus aspektas šios priemonės surinkti ir suskirstyti mūsų žinias ir gebėjimus, todėl kai suformuluosite klausimą, tą klausimą reiks priskirti sričiai iš sričių medžio tam, kad klausimas nukeliautų pas išmanantį žmogų. Kai norėsite prisidėti sprendžiant kitų klausimus, taip pat reikės pasirinkti sritis, kur jūs turite išmanymą./
            Цей інструмент покликаний допомогти об’єднати запитувача та обізнаних. Важливим аспектом цього інструменту є збір і обмін нашими знаннями та навичками, тому, як тільки ви сформулюєте питання, це питання потрібно буде призначити до області з дерева областей, щоб питання було передано обізнаній людині. Якщо ви хочете внести свій внесок у вирішення проблем інших людей, вам також потрібно буде вибрати сфери, де ви маєте досвід./
            Этот инструмент предназначен для того, чтобы помочь исследователю объединиться со знающим. Важным аспектом этого инструмента является сбор и обмен нашими знаниями и навыками, поэтому, как только вы сформулируете вопрос, этот вопрос необходимо будет назначить области из дерева областей, чтобы вопрос попал к знающему человеку. Если вы хотите помоч решить проблемы других людей, вам также нужно будет выбрать области, в которых у вас есть опыт."""
end

# ***** functions below will not be used for a now *****
function registerinvitecode()
    id=tryparse(Int, av["txt"])
    if id !== nothing && any(keys(Av).==id)
        Av[id]["token"]+=2
        msg="Jūsų pakviestas dalyvis sėkmingai užsiregistravo! O jums prisidėjo du taškai. Bendras taškų skaičius $(Av[id]["token"])"
        sendMessage(chat_id = id,text = msg)
        #av["tonken"]+=2
        msg="Pakvietimo kodas priimtas"
        sendMessage(chat_id = av["id"],text = msg)
        tbegin()
    else
        msg="Kažkas negerai su kodu, bandykite dar kartą arba tęskite paspaudę komandą /namo."
        sendMessage(chat_id = av["id"],text = msg)
    end
end

function invite() # this is not used now
    msg="Nusiūskite žmogui nuorodą bei kodą (jei reikia, pirmiausia pakviestkite į Telegram platformą)."
    sendMessage(chat_id = av["id"],text = msg)
    msg="Prisijunkite į Talką @talkon_bot, pakvietimo kodas:."
    sendMessage(chat_id = av["id"],text = msg)
    sendMessage(chat_id = av["id"],text = "$(av["id"])")
end

function invitecodeyesno(t) # this is not needed now
    if t==0
        tbegin()
        return
    end
    sendMessage(chat_id = av["id"], text = "Įveskite kodą")
    av["step"]="wait_for_invite_code"
end


text:
NI(x...) = error("This function is not implemented.")

@deprecate readgraph load

const filemap = Dict{Symbol, Tuple{Function, Function, Function, Function}}()
        # :gml        => (loadgml, loadgml_mult, savegml, savegml_mult)
        # :graphml    => (loadgraphml, loadgraphml_mult, savegraphml, savegraphml_mult)
        # :md         => (loadmatrixdepot, NOTIMPLEMENTED, NOTIMPLEMENTED, NOTIMPLEMENTED)

# load a single graph by name
"""
    load(file, name, t=:lg)

Loads a graph with name `name` from `file` in format `t`.

Currently supported formats are `:lg, :gml, :graphml, :gexf, :dot, :net`.
"""
function load(io::IO, gname::AbstractString, t::Symbol=:lg)
    t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
    return filemap[t][1](io, gname)
end

"""
    load(file, t=:lg)

Loads multiple graphs from  `file` in the format `t`. Returns a dictionary
mapping graph name to graph.

For unnamed graphs the default names \"graph\" and \"digraph\" will be used.
"""

function load(io::IO, t::Symbol=:lg)
    t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
    return filemap[t][2](io)
end

# load from a file
function load(fn::AbstractString, x...)
    GZip.open(fn,"r") do io
        load(io, x...)
    end
end

"""
    save(file, g, t=:lg)
    save(file, g, name, t=:lg)
    save(file, dict, t=:lg)

Saves a graph `g` with name `name` to `file` in the format `t`. If `name` is not given
the default names \"graph\" and \"digraph\" will be used.

Currently supported formats are `:lg, :gml, :graphml, :gexf, :dot, :net`.

For some graph formats, multiple graphs in a  `dict` `"name"=>g` can be saved in the same file.

Returns the number of graphs written.
"""
function save(io::IO, g::SimpleGraph, gname::AbstractString, t::Symbol=:lg)
    t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
    return filemap[t][3](io, g, gname)
end

# save a single graph without name
save(io::IO, g::Graph, t::Symbol=:lg) = save(io, g, "graph", t)
save(io::IO, g::DiGraph, t::Symbol=:lg) = save(io, g, "digraph", t)

# save a dictionary of graphs {"name" => graph}
function save{T<:AbstractString}(io::IO, d::Dict{T, SimpleGraph}, t::Symbol=:lg)
    t in keys(filemap) || error("Please select a supported graph format: one of $(keys(filemap))")
    return filemap[t][4](io, d)
end

# save to a file
function save(fn::AbstractString, x...; compress::Bool=false)
    if compress
        io = GZip.open(fn,"w")
    else
        io = open(fn,"w")
    end
    retval = save(io, x...)
    close(io)
    return retval
end


text:
module Preprocessing

export Standard, MinMax, Robust, fit_transform!, inv_transform, dataloader, databuilder, DataSplitter, LabelEncoder, OneHotEncoder

using Statistics
using Random
using Downloads
using CSV
using DataFrames

include("../utils.jl")
include("utils.jl")
include("Data.jl")
include("Encoder.jl")
include("MM.jl")
include("RS.jl")
include("SS.jl")

end


text:
using Cxx
using Libdl

push!(DL_LOAD_PATH, "/usr/local/lib")
push!(DL_LOAD_PATH, "./")

function ransac_example()

    for header in ["/usr/include/eigen3/",
                   "/usr/local/include/theia/libraries/vlfeat",
                   "/usr/include/suitesparse",
                   "/usr/local/include/theia/libraries/",
                   "/usr/local/include/theia/libraries/statx",
                   "/usr/local/include/theia/libraries/optimo",
                   "/usr/local/include",
                   "/usr/local/include/theia",
                   "/usr/include", "./"]

        addHeaderDir(header, kind=C_User)

    end

    Libdl.dlopen("libvlfeat.so", Libdl.RTLD_GLOBAL)
    Libdl.dlopen("libflann_cpp.so", Libdl.RTLD_GLOBAL)
    Libdl.dlopen("libakaze.so", Libdl.RTLD_GLOBAL)
    Libdl.dlopen("libceres.so", Libdl.RTLD_GLOBAL)
    Libdl.dlopen("libtheia.so", Libdl.RTLD_GLOBAL)
    Libdl.dlopen("libransac.so", Libdl.RTLD_GLOBAL)

    cxx"""
run_ransac();

    """

end


text:
push!(LOAD_PATH, pwd())

module TestModule

using A
using B
using Test
using JLD2

x =  AType(1)

S = BType(x)

@testset "save and load" begin
	T = deepcopy(S)
	@test T == S
	fn = joinpath(mktempdir(), "test_out.jld")
	@save fn T
	T = nothing
	@load fn T
	@test T == S
end

@testset "name collisions" begin
    mods = collect(keys(Base.module_keys))
    # use whichever module would not be found first in a linear search
    M = findfirst(==(A), mods) < findfirst(==(B), mods) ? B : A
    x = M.SameNameType(42)
    file = joinpath(mktempdir(), "collision.jld")
    @save file x
    x = nothing
    @load file x
    @test x isa M.SameNameType
end

end


text:
# Some initial support for Healpix fields.
# The main functionality of broadcasting, indexing, and projection for
# a few field types is implemented, but not much beyond that.

@init global hp = lazy_pyimport("healpy")

struct ProjHealpix <: Proj
    Nside :: Int
end
make_field_aliases("Healpix", ProjHealpix)
typealias_def(::Type{<:ProjHealpix}) = "ProjHealpix"

## constructing from arrays
# spin-0
function HealpixMap(I::A) where {T, A<:AbstractArray{T}}
    HealpixMap(I, ProjHealpix(hp.npix2nside(length(I))))
end
# spin-2
function HealpixField{B}(X::A, Y::A) where {T, A<:AbstractArray{T}, B<:Basis2Prod{<:Union{𝐐𝐔,𝐄𝐁},Map}}
    HealpixField{B}(cat(X, Y, dims=Val(2)), ProjHealpix(hp.npix2nside(length(X))))
end
# spin-(0,2)
function HealpixField{B}(I::A, X::A, Y::A) where {T, A<:AbstractArray{T}, B<:Basis3Prod{𝐈,<:Union{𝐐𝐔,𝐄𝐁},Map}}
    HealpixField{B}(cat(I, X, Y, dims=Val(2)), ProjHealpix(hp.npix2nside(length(I))))
end

### pretty printing
typealias_def(::Type{F}) where {B,M<:ProjHealpix,T,A,F<:HealpixField{B,M,T,A}} = "Healpix$(typealias(B)){$(typealias(A))}"
function Base.summary(io::IO, f::HealpixField)
    @unpack Nside = f
    print(io, "$(length(f))-element Nside=$Nside ")
    Base.showarg(io, f, true)
end

getproperty(f::HealpixField, ::Val{:proj}) = getfield(f,:metadata)
pol_slice(::HealpixField, i) = (:, i)

### broadcasting

function promote_metadata_strict(metadata₁::ProjHealpix, metadata₂::ProjHealpix)
    if metadata₁ === metadata₂
        metadata₁
    else
        error("Can't broadcast Healpix maps with two different Nsides ($metadata₁.Nside, $metadata₂.Nside).")
    end
end

### Projection

# adding more flat projections in the future should be as easy as
# defining pairs of functions like the above two for other cases

## ProjEquiRect
function θϕ_to_ij(proj::ProjEquiRect, θ, ϕ)
    @unpack Ny, Nx, θspan, φspan = proj
    i =        (θ - θspan[1])             / abs(-(θspan...)) * Ny
    j = rem2pi((ϕ - φspan[1]), RoundDown) / abs(-(φspan...)) * Nx
    (i, j)
end

function ij_to_θϕ(proj::ProjEquiRect, i, j)
    @unpack Ny, Nx, θspan, φspan = proj
    θ = abs(-(θspan...)) / Ny * i + θspan[1]
    ϕ = abs(-(φspan...)) / Nx * j + φspan[1]
    (θ, ϕ)
end

## ProjLambert
#
# Notes:
# * choices of negative signs are such that the default projection is
#   centered on the center of a healpy.mollview plot and oriented the
#   same way
# * we have to define these at the "broadcasted" level so we can do
#   just a single call to Rotator(), otherwise it'd be really slow

function broadcasted(::typeof(ij_to_θϕ), proj::ProjLambert, is, js)
    @unpack Δx, Ny, Nx, rotator = proj
    θϕs = broadcast(is, js) do i, j
        x = Δx * (j - Nx÷2 - 0.5)
        y = Δx * (i - Ny÷2 - 0.5)
        r = sqrt(x^2 + y^2)
        θ = 2*acos(r/2)
        ϕ = atan(-x, -y)
        θ, ϕ
    end
    R = hp.Rotator(rotator)
    θϕs = reshape(R.get_inverse()(first.(θϕs)[:], last.(θϕs)[:]), 2, size(θϕs)...)
    tuple.(θϕs[1,:,:], θϕs[2,:,:])
end

function broadcasted(::typeof(θϕ_to_ij), proj::ProjLambert, θs, ϕs)
    @unpack Δx, Ny, Nx, rotator = proj
    R = hp.Rotator(rotator)
    (θs, ϕs) = eachrow(R(θs, ϕs))
    broadcast(θs, ϕs) do θ, ϕ
        r = 2cos(θ/2)
        x = -r*sin(ϕ)
        y = -r*cos(ϕ)
        i = y / Δx + Ny÷2 + 0.5
        j = x / Δx + Nx÷2 + 0.5
        (i, j)
    end
end

## Healpix => Cartesian

"""
    project(healpix_map::HealpixField => cart_proj::CartesianProj)

Project `healpix_map` to a cartisian projection specified by
`cart_proj`. E.g.:

    healpix_map = HealpixMap(rand(12*2048^2))
    flat_proj = ProjLambert(Ny=128, Nx=128, θpix=3, T=Float32)
    f = project(healpix_map => flat_proj; rotator=pyimport("healpy").Rotator((0,28,23)))

The use of `=>` is to help remember in which order the arguments are
specified. If `healpix_map` is a `HealpixQU`, Q/U polarization angles
are rotated to be aligned with the local coordinates (sometimes called
"polarization flattening").
"""
function project((hpx_map, cart_proj)::Pair{<:HealpixMap,<:CartesianProj})
    @unpack Ny, Nx = cart_proj
    _project(ij_to_θϕ.(cart_proj, 1:Ny, (1:Nx)'), hpx_map => cart_proj)
end

function project((hpx_map, cart_proj)::Pair{<:HealpixQUMap,<:ProjLambert{T}}) where {T}
    @unpack Ny, Nx, rotator = cart_proj
    θϕs = ij_to_θϕ.(cart_proj, 1:Ny, (1:Nx)')
    Q = _project(θϕs, hpx_map.Q => cart_proj)
    U = _project(θϕs, hpx_map.U => cart_proj)
    ψpol = reshape((hp.Rotator((0,-90,0)) * hp.Rotator(rotator)).angle_ref(first.(θϕs)[:], last.(θϕs)[:]), Ny, Nx)
    QU_flat = @. (Q.arr + im * U.arr) * exp(im * 2 * ψpol)
    FlatQUMap(real.(QU_flat), imag.(QU_flat), cart_proj)
end

function _project(θϕs, (hpx_map, cart_proj)::Pair{<:HealpixMap,<:CartesianProj})
    @unpack Ny, Nx = cart_proj
    BaseMap(reshape(hp.get_interp_val(collect(hpx_map), first.(θϕs)[:], last.(θϕs)[:]), Ny, Nx), cart_proj)
end

## Cartesian => Healpix

"""
    project(flat_map::FlatField => healpix_proj::ProjHealpix; [rotator])

Reproject a `flat_map` back onto the sphere in a Healpix projection
specified by `healpix_proj`. E.g.

    flat_map = FlatMap(rand(128,128))
    f = project(flat_map => ProjHealpix(2048); rotator=pyimport("healpy").Rotator((0,28,23)))

The use of `=>` is to help remember in which order the arguments are
specified. Optional keyword argument `rotator` is a `healpy.Rotator`
object specifying a rotation which rotates the north pole to the
center of the desired field.
"""
function project((cart_map, hpx_proj)::Pair{<:CartesianS0, <:ProjHealpix})
    @unpack Nside = hpx_proj
    (θs, ϕs) = hp.pix2ang(Nside, 0:(12*Nside^2-1))
    ijs = θϕ_to_ij.(cart_map.proj, θs, ϕs)
    is, js = first.(ijs), last.(ijs)
    HealpixMap(@ondemand(Images.bilinear_interpolation).(Ref(cpu(Map(cart_map).Ix)), is, js), hpx_proj)
end


text:
# change to absolute path
data_input_root = "data/input/dami-base-processed-2000"
data_output_root = "data/output"

JULIA_ENV = joinpath(@__DIR__, "..")

num_workers = 1

max_stars_repo_name: holtri/lama

max_issues_repo_name: holtri/lama

max_forks_repo_name: holtri/lama


text:
for unary_operator in unary_operators
    b_symbol = Meta.parse.(unary_operator[2]) #broadcast
    @eval import Base: $b_symbol
    @eval function $b_symbol(field1::FourierField)
        data = broadcast($b_symbol, field1.data)
        metadata  = field1.metadata
        symbname = string($b_symbol)
        name = symbname * "(" * field1.metadata.name * ")"
        fmd = FourierMetaData(name, metadata.grid, metadata.transform)
        FourierField(data, fmd )
    end
end

for binary_operator in [binary_operators..., ["Negative", "-"]]
    b_symbol = Meta.parse.(binary_operator[2])
    @eval import Base: $b_symbol
    @eval function $b_symbol(field1::FourierField, field2::𝒮) where {𝒮}
        data = broadcast($b_symbol, field1.data, field2)
        metadata  = field1.metadata
        symbname = string($b_symbol)
        name1 = field1.metadata.name
        name2 = string(field2)
        name = "(" * name1 * symbname * name2 * ")"
        fmd = FourierMetaData(name, metadata.grid, metadata.transform)
        return FourierField(data, fmd)
    end
    @eval function $b_symbol(field1::𝒯, field2::FourierField) where {𝒯}
        data = broadcast($b_symbol, field1, field2.data)
        metadata  = field2.metadata
        symbname = string($b_symbol)
        name1 = string(field1)
        name2 = field2.metadata.name
        name = "(" * name1 * symbname * name2 * ")"
        fmd = FourierMetaData(name, metadata.grid, metadata.transform)
        return FourierField(data, fmd)
    end
end

# exception for multiplication of fourier fields
for binary_operator in [binary_operators[1], ["Negative", "-"]]
    b_symbol = Meta.parse.(binary_operator[2])
    @eval function $b_symbol(field1::FourierField, field2::FourierField)
        data = broadcast($b_symbol, field1.data, field2.data)
        metadata  = field1.metadata
        symbname = string($b_symbol)
        name1 = field1.metadata.name
        name2 = field2.metadata.name
        name = "(" * name1 * symbname * name2 * ")"
        fmd = FourierMetaData(name, metadata.grid, metadata.transform)
        return FourierField(data, fmd)
    end
end

function *(f̂::FourierField, ĝ::FourierField)
    fwd = f̂.metadata.transform.forward
    bwd = f̂.metadata.transform.backward
    f = real.(bwd * f̂.data)
    g = real.(bwd * ĝ.data)
    fg = broadcast(*, f, g)
    metadata  = ĝ.metadata
    name1 = f̂.metadata.name
    name2 = ĝ.metadata.name
    name = "(" * name1 * "*" * name2 * ")"
    fmd = FourierMetaData(name, metadata.grid, metadata.transform)
    return FourierField(fwd * fg, fmd)
end
function ^(f̂::FourierField, n::Number)
    fwd = f̂.metadata.transform.forward
    bwd = f̂.metadata.transform.backward
    f = real.(bwd * f̂.data)
    ff = broadcast(^, f, n)
    metadata  = f̂.metadata
    name1 = f̂.metadata.name
    name = "(" * name1 * ")" * "^" * string(n)
    fmd = FourierMetaData(name, metadata.grid, metadata.transform)
    return FourierField(fwd * ff, fmd)
end

compute(a::FourierField) = a

## need the following hook
function compute(a::DerivativeMetaData{𝒮,𝒯}) where
    {𝒮 <: FourierOperator, 𝒯}
    return a.operation
end

max_stars_repo_name: upiterbarg/QuasiGeostrophy

max_issues_repo_name: upiterbarg/QuasiGeostrophy

max_forks_repo_name: upiterbarg/QuasiGeostrophy


text:
# TODO: Implement sparse methods when moving to large scale
struct SmallSignalOutput
    reduced_jacobian::Matrix{Float64}
    eigenvalues::Vector{Complex{Float64}}
    eigenvectors::Matrix{Complex{Float64}}
    index::Dict
    stable::Bool
    operating_point::Vector{Float64}
    damping::Dict{String, Dict{Symbol, Float64}}
    participation_factors::Dict{String, Dict{Symbol, Array{Float64}}}
end

function _determine_stability(vals::Vector{Complex{Float64}})
    for real_eig in real(vals)
        real_eig > 0.0 && return false
    end
    return true
end

function _calculate_forwardiff_jacobian(
    sim::Simulation{ImplicitModel},
    x_eval::Vector{Float64},
)
    var_count = get_variable_count(sim.simulation_inputs)
    dx0 = zeros(var_count) #Define a vector of zeros for the derivative
    sysf! = (out, x) -> system_implicit!(
        out,            #output of the function
        dx0,            #derivatives equal to zero
        x,              #states
        sim.simulation_inputs,     #Parameters
        0.0,            #time equals to zero.
    )
    out = zeros(var_count) #Define a vector of zeros for the output
    jacobian = ForwardDiff.jacobian(sysf!, out, x_eval)
    return jacobian
end

function _calculate_forwardiff_jacobian(
    sim::Simulation{MassMatrixModel},
    x_eval::Vector{Float64},
)
    var_count = get_variable_count(sim.simulation_inputs)
    sysf! = (dx, x) -> system_mass_matrix!(
        dx,            #derivatives equal to zero
        x,              #states
        sim.simulation_inputs,     #Parameters
        0.0,            #time equals to zero.
    )
    dx = zeros(var_count) #Define a vector of zeros for the output
    jacobian = ForwardDiff.jacobian(sysf!, dx, x_eval)
    return jacobian
end

"""
Finds the location of the differential states in the reduced Jacobian
"""
function _make_reduced_jacobian_index(global_index, diff_states)
    jac_index = Dict{String, Dict{Symbol, Int}}()
    for (device_name, device_index) in global_index
        jac_index[device_name] = Dict{Symbol, Int}()
        for (state, ix) in device_index
            state_is_differential = diff_states[ix]
            if state_is_differential
                jac_index[device_name][state] = sum(diff_states[1:ix])
            end
        end
    end
    return jac_index
end

function _reduce_jacobian(
    jacobian::Matrix{Float64},
    diff_states::Vector{Bool},
    mass_matrix::SparseArrays.SparseMatrixCSC{Float64, Int},
)
    alg_states = .!diff_states
    fx = @view jacobian[diff_states, diff_states]
    gy = jacobian[alg_states, alg_states]
    fy = @view jacobian[diff_states, alg_states]
    gx = @view jacobian[alg_states, diff_states]
    M = @view mass_matrix[diff_states, diff_states]
    inv_diag_M = Vector(1.0 ./ LinearAlgebra.diag(M))
    # TODO: Make operation using BLAS!
    reduced_jacobian = inv_diag_M .* (fx - fy * inv(gy) * gx)
    return reduced_jacobian
end

function _get_eigenvalues(reduced_jacobian::Matrix{Float64}, multimachine::Bool)
    eigen_vals, R_eigen_vect = LinearAlgebra.eigen(reduced_jacobian)
    if multimachine
        @warn(
            "No Infinite Bus found. Confirm stability directly checking eigenvalues.\nIf all eigenvalues are on the left-half plane and only one eigenvalue is zero, the system is small signal stable."
        )
        info_evals = "Eigenvalues are:\n"
        for i in eigen_vals
            info_evals = info_evals * string(i) * "\n"
        end
        @info(info_evals)
    end
    return eigen_vals, R_eigen_vect
end

function _get_damping(
    eigen_vals::Vector{Complex{Float64}},
    jac_index::Dict{String, Dict{Symbol, Int}},
)
    damping_results = Dict{String, Dict{Symbol, Float64}}()
    for (device_name, device_index) in jac_index
        damping_results[device_name] = Dict{Symbol, Float64}()
        for (state, ix) in device_index
            isnothing(ix) && continue
            eigen_val = eigen_vals[ix]
            damping_results[device_name][state] =
                -1 * real(eigen_val) / sqrt(real(eigen_val)^2 + imag(eigen_val)^2)
        end
    end
    return damping_results
end

function _get_participation_factors(
    R_eigen_vect::Matrix{Complex{Float64}},
    jac_index::Dict{String, Dict{Symbol, Int}},
)
    L_eigen_vect = inv(R_eigen_vect)
    participation_factors = Dict{String, Dict{Symbol, Array{Float64}}}()
    for (device_name, device_index) in jac_index
        participation_factors[device_name] = Dict{Symbol, Array{Float64}}()
        for (state, ix) in device_index
            den = sum(abs.(L_eigen_vect[:, ix]) .* abs.(R_eigen_vect[ix, :]))
            participation_factors[device_name][state] =
                abs.(L_eigen_vect[:, ix]) .* abs.(R_eigen_vect[ix, :]) ./ den
        end
    end
    return participation_factors
end

function small_signal_analysis(sim::Simulation; kwargs...)
    simulation_pre_step!(sim, get(kwargs, :reset_simulation, false), Real)
    sim.status = CONVERTED_FOR_SMALL_SIGNAL
    inputs = get_simulation_inputs(sim)
    mass_matrix = get_mass_matrix(inputs)
    x_eval = get(kwargs, :operating_point, sim.x0_init)
    jacobian = _calculate_forwardiff_jacobian(sim, x_eval)
    diff_states = get_DAE_vector(inputs)
    jac_index = _make_reduced_jacobian_index(get_global_index(inputs), diff_states)
    reduced_jacobian = _reduce_jacobian(jacobian, diff_states, mass_matrix)
    eigen_vals, R_eigen_vect = _get_eigenvalues(reduced_jacobian, sim.multimachine)
    damping = _get_damping(eigen_vals, jac_index)
    stable = _determine_stability(eigen_vals)
    participation_factors = _get_participation_factors(R_eigen_vect, jac_index)
    return SmallSignalOutput(
        reduced_jacobian,
        eigen_vals,
        R_eigen_vect,
        jac_index,
        stable,
        x_eval,
        damping,
        participation_factors,
    )
end


text:
module TestGaussNewton

using Test
using OptimizationAlgorithms
using OptimizationAlgorithms: GaussNewton, LevenbergMarquart, DecreasingStep, LevenbergMarquartSettings
using OptimizationAlgorithms: update!, optimize!

function test_problem(n)
    x = sort!(randn(n))
    g(a, b) = x -> sin(2π*a*x) + b*x^2
    a, b = randn(2)
    y = g(a, b).(x)
    return [a,b], x, y, g, function residual!(r, ab)
        @. r = y - g(ab...).(x)
    end
end

@testset "GaussNewton" begin
    n = 64
    ab0, x, y, g, r = test_problem(n)
    G = GaussNewton(r, ab0, y)
    σ = .1
    ab = ab0 + σ*randn(2)
    for i in 1:16
        update!(G, ab)
    end
    tol = 1e-8
    @test isapprox(ab, ab0, atol = tol)

    D = DecreasingStep(G, ab)
    ab = ab0 + σ*randn(2)
    for i in 1:16
        update!(D, ab)
    end
    tol = 1e-8
    @test isapprox(ab, ab0, atol = tol)
end

@testset "LevenbergMarquart" begin
    n = 64
    ab0, x, y, g, r = test_problem(n)
    LM = LevenbergMarquart(r, ab0, y)
    σ = .1
    ab = ab0 + σ*randn(2)
    tol = 1e-8
    # tesing out intitialization with very large lambda, min_decrease, and min_iter
    res = copy(y)
    stn = LevenbergMarquartSettings(max_iter = 16, min_decrease = 1e-10, min_resnorm = 1e-10, min_res = 0)
    optimize!(LM, ab, res, Val(false), stn, 1e-6, Val(true))
    @test isapprox(ab, ab0, atol = tol)
end

@testset "Geodesic LevenbergMarquart" begin
    n = 64
    ab0, x, y, g, r = test_problem(n)
    LM = LevenbergMarquart(r, ab0, y)
    σ = .1
    ab = ab0 + σ*randn(2)
    tol = 1e-8
    # tesing out intitialization with very large lambda, min_decrease, and min_iter
    res = copy(y)
    stn = LevenbergMarquartSettings(max_iter = 16, min_decrease = 1e-10, min_resnorm = 1e-10, min_res = 0)
    optimize!(LM, ab, res, Val(true), stn, 1e-6, 0.01, 0.75, Val(true))
    @test isapprox(ab, ab0, atol = tol)
end

end


text:
using Test, Pkg, LyceumDocs

function collect_scripts()
    scripts = String[]
    for (root, _, files) in walkdir(LyceumDocs.SRC_DIR), file in files
        abs_path = joinpath(root, file)
        if LyceumDocs.isliterate(abs_path, read(abs_path, String))
            push!(scripts, abs_path)
        end
    end
    scripts
end

function do_one(script)
    curdir = pwd()
    curproj = Base.active_project()
    tmpdir = mktempdir()
    try
        LyceumDocs.create_example_project(tmpdir)
        cd(tmpdir)
        Pkg.activate(".")
        run(`julia --check-bounds=yes --startup-file=no --project=$(tmpdir) $(script)`)
        return true
    catch e
        @error e
        return false
    finally
        cd(curdir)
        Pkg.activate(curproj)
        rm(tmpdir, force = true, recursive = true)
    end
end

@testset "LyceumDocs.jl" begin
    @testset "$(relpath(script, LyceumDocs.SRC_DIR))" for script in collect_scripts()
        @test do_one(script)
    end
end


text:
# Autogenerated wrapper script for SPRAL_jll for x86_64-apple-darwin-libgfortran5
export libspral, spral_ssids

using METIS_jll
using CompilerSupportLibraries_jll
using OpenBLAS32_jll
using Hwloc_jll
JLLWrappers.@generate_wrapper_header("SPRAL")
JLLWrappers.@declare_library_product(libspral, "@rpath/libspral.dylib")
JLLWrappers.@declare_executable_product(spral_ssids)
function __init__()
    JLLWrappers.@generate_init_header(METIS_jll, CompilerSupportLibraries_jll, OpenBLAS32_jll, Hwloc_jll)
    JLLWrappers.@init_library_product(
        libspral,
        "lib/libspral.dylib",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_executable_product(
        spral_ssids,
        "bin/spral_ssids",
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
using OptEnrichedSetCover
using Documenter

makedocs(
    format = Documenter.HTML(prettyurls=false),
    sitename = "OptEnrichedSetCover.jl",
    authors = "Alexey Stukalov",
    modules = [OptEnrichedSetCover],
    clean = true,
    pages = [
        "Introduction" => "index.md",
        "Method description" => "method.md",
        "Sets collection" => "mosaic.md",
        "Cover problem" => "cover_problem.md",
        "Internals" => [
            "Array pool" => "array_pool.md",
            "Sparse mask matrix" => "sparse_mask_matrix.md",
        ]
    ],
)

deploydocs(
    repo = "github.com/alyst/OptEnrichedSetCover.jl.git",
)