text:
import Base.zero

export
    AVIO_SEEKABLE_NORMAL,
    AVSEEK_SIZE,
    AVSEEK_FORCE,
    AVIO_FLAG_READ,
    AVIO_FLAG_WRITE,
    AVIO_FLAG_READ_WRITE,
    AVIO_FLAG_NONBLOCK,
    AVIO_FLAG_DIRECT,
    AVIOInterruptCB,
    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_RAWPICTURE,
    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,
    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_CAPTIONS,
    AV_DISPOSITION_DESCRIPTIONS,
    AV_DISPOSITION_METADATA,
    AV_PTS_WRAP_IGNORE,
    AV_PTS_WRAP_ADD_OFFSET,
    AV_PTS_WRAP_SUB_OFFSET,
    AVSTREAM_EVENT_FLAG_METADATA_UPDATED,
    MAX_STD_TIMEBASES,
    MAX_PROBE_PACKETS,
    MAX_REORDER_DELAY,
    AV_PROGRAM_RUNNING,
    AVFMTCTX_NOHEADER,
    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_EVENT_FLAG_METADATA_UPDATED,
    RAW_PACKET_BUFFER_SIZE,
    AVSEEK_FLAG_BACKWARD,
    AVSEEK_FLAG_BYTE,
    AVSEEK_FLAG_ANY,
    AVSEEK_FLAG_FRAME,
    AVCodecTag,
    AVInputFormat,
    AVOutputFormat,
    AVFrac,
    AVStreamParseType,
    AVSTREAM_PARSE_NONE,
    AVSTREAM_PARSE_FULL,
    AVSTREAM_PARSE_HEADERS,
    AVSTREAM_PARSE_TIMESTAMPS,
    AVSTREAM_PARSE_FULL_ONCE,
    AVSTREAM_PARSE_FULL_RAW,
    AVPacketList,
    AVProbeData,
    Array_17_Int64,
    AVIndexEntry,
    Array_17_Uint8,
    AVStream,
    Array_1024_Uint8,
    AVProgram,
    AVChapter,
    AVDurationEstimationMethod,
    AVFMT_DURATION_FROM_PTS,
    AVFMT_DURATION_FROM_STREAM,
    AVFMT_DURATION_FROM_BITRATE,
    AVFormatInternal,
    av_format_control_message,
    AVFormatContext,
    AVDeviceInfoList,
    AVDeviceCapabilitiesQuery

const AVIO_SEEKABLE_NORMAL  =  0x0001
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

immutable AVIOInterruptCB
    callback::Ptr{Void}
    opaque::Ptr{Void}
end

immutable AVIOContext
    av_class::Ptr{AVClass}
    buffer::Ptr{Cuchar}
    buffer_size::Cint
    buf_ptr::Ptr{Cuchar}
    buf_end::Ptr{Cuchar}
    opaque::Ptr{Void}
    read_packet::Ptr{Void}
    write_packet::Ptr{Void}
    seek::Ptr{Void}
    pos::Int64
    must_flush::Cint
    eof_reached::Cint
    write_flag::Cint
    max_packet_size::Cint
    checksum::Culong
    checksum_ptr::Ptr{Cuchar}
    update_checksum::Ptr{Void}
    error::Cint
    read_pause::Ptr{Void}
    read_seek::Ptr{Void}
    seekable::Cint
    maxsize::Int64
    direct::Cint
    bytes_read::Int64
    seek_count::Cint
    writeout_count::Cint
    orig_buffer_size::Cint
end

const AVBPrint = Void

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_RAWPICTURE  =  0x0020
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 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_CAPTIONS  =  0x00010000
const AV_DISPOSITION_DESCRIPTIONS  =  0x00020000
const AV_DISPOSITION_METADATA  =  0x00040000
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  =  60 * 12 + 6
const MAX_PROBE_PACKETS  =  2500
const MAX_REORDER_DELAY  =  16
const AV_PROGRAM_RUNNING  =  1
const AVFMTCTX_NOHEADER  =  0x0001
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 FF_FDEBUG_TS  =  0x0001
const AVFMT_EVENT_FLAG_METADATA_UPDATED  =  0x0001
const RAW_PACKET_BUFFER_SIZE  =  2500000
const AVSEEK_FLAG_BACKWARD  =  1
const AVSEEK_FLAG_BYTE  =  2
const AVSEEK_FLAG_ANY  =  4
const AVSEEK_FLAG_FRAME  =  8

const AVCodecTag = Void

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

immutable AVOutputFormat
    name::Ptr{UInt8}
    long_name::Ptr{UInt8}
    mime_type::Ptr{UInt8}
    extensions::Ptr{UInt8}
    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{Void}
    write_packet::Ptr{Void}
    write_trailer::Ptr{Void}
    interleave_packet::Ptr{Void}
    query_codec::Ptr{Void}
    get_output_timestamp::Ptr{Void}
    control_message::Ptr{Void}
    write_uncoded_frame::Ptr{Void}
    get_device_list::Ptr{Void}
    create_device_capabilities::Ptr{Void}
    free_device_capabilities::Ptr{Void}
end

immutable AVFrac
    val::Int64
    num::Int64
    den::Int64
end

# begin enum AVStreamParseType
const AVStreamParseType = UInt32
const AVSTREAM_PARSE_NONE  =  UInt32(0)
const AVSTREAM_PARSE_FULL  =  UInt32(1)
const AVSTREAM_PARSE_HEADERS  =  UInt32(2)
const AVSTREAM_PARSE_TIMESTAMPS  =  UInt32(3)
const AVSTREAM_PARSE_FULL_ONCE  =  UInt32(4)
const AVSTREAM_PARSE_FULL_RAW  =  UInt32(1463898624)
# end enum AVStreamParseType

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

immutable AVProbeData
    filename::Ptr{UInt8}
    buf::Ptr{Cuchar}
    buf_size::Cint
    mime_type::Ptr{UInt8}
end

immutable Array_17_Int64
    d1::Int64
    d2::Int64
    d3::Int64
    d4::Int64
    d5::Int64
    d6::Int64
    d7::Int64
    d8::Int64
    d9::Int64
    d10::Int64
    d11::Int64
    d12::Int64
    d13::Int64
    d14::Int64
    d15::Int64
    d16::Int64
    d17::Int64
end

zero(::Type{Array_17_Int64}) = Array_17_Int64(fill(zero(Int64),17)...)

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

immutable Array_17_Uint8
    d1::UInt8
    d2::UInt8
    d3::UInt8
    d4::UInt8
    d5::UInt8
    d6::UInt8
    d7::UInt8
    d8::UInt8
    d9::UInt8
    d10::UInt8
    d11::UInt8
    d12::UInt8
    d13::UInt8
    d14::UInt8
    d15::UInt8
    d16::UInt8
    d17::UInt8
end

zero(::Type{Array_17_Uint8}) = Array_17_Uint8(fill(zero(UInt8),17)...)

immutable AVStream
    index::Cint
    id::Cint
    codec::Ptr{AVCodecContext}
    priv_data::Ptr{Void}
    pts::AVFrac
    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
    info::Ptr{Void}
    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::Array_17_Int64
    index_entries::Ptr{AVIndexEntry}
    nb_index_entries::Cint
    index_entries_allocated_size::UInt32
    r_frame_rate::AVRational
    stream_identifier::Cint
    interleaver_chunk_size::Int64
    interleaver_chunk_duration::Int64
    request_probe::Cint
    skip_to_keyframe::Cint
    skip_samples::Cint
    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::Array_17_Int64
    pts_reorder_error_count::Array_17_Uint8
    last_dts_for_order_check::Int64
    dts_ordered::UInt8
    dts_misordered::UInt8
    inject_global_side_data::Cint
end

immutable Array_1024_Uint8
    d1::UInt8
    d2::UInt8
    d3::UInt8
    d4::UInt8
    d5::UInt8
    d6::UInt8
    d7::UInt8
    d8::UInt8
    d9::UInt8
    d10::UInt8
    d11::UInt8
    d12::UInt8
    d13::UInt8
    d14::UInt8
    d15::UInt8
    d16::UInt8
    d17::UInt8
    d18::UInt8
    d19::UInt8
    d20::UInt8
    d21::UInt8
    d22::UInt8
    d23::UInt8
    d24::UInt8
    d25::UInt8
    d26::UInt8
    d27::UInt8
    d28::UInt8
    d29::UInt8
    d30::UInt8
    d31::UInt8
    d32::UInt8
    d33::UInt8
    d34::UInt8
    d35::UInt8
    d36::UInt8
    d37::UInt8
    d38::UInt8
    d39::UInt8
    d40::UInt8
    d41::UInt8
    d42::UInt8
    d43::UInt8
    d44::UInt8
    d45::UInt8
    d46::UInt8
    d47::UInt8
    d48::UInt8
    d49::UInt8
    d50::UInt8
    d51::UInt8
    d52::UInt8
    d53::UInt8
    d54::UInt8
    d55::UInt8
    d56::UInt8
    d57::UInt8
    d58::UInt8
    d59::UInt8
    d60::UInt8
    d61::UInt8
    d62::UInt8
    d63::UInt8
    d64::UInt8
    d65::UInt8
    d66::UInt8
    d67::UInt8
    d68::UInt8
    d69::UInt8
    d70::UInt8
    d71::UInt8
    d72::UInt8
    d73::UInt8
    d74::UInt8
    d75::UInt8
    d76::UInt8
    d77::UInt8
    d78::UInt8
    d79::UInt8
    d80::UInt8
    d81::UInt8
    d82::UInt8
    d83::UInt8
    d84::UInt8
    d85::UInt8
    d86::UInt8
    d87::UInt8
    d88::UInt8
    d89::UInt8
    d90::UInt8
    d91::UInt8
    d92::UInt8
    d93::UInt8
    d94::UInt8
    d95::UInt8
    d96::UInt8
    d97::UInt8
    d98::UInt8
    d99::UInt8
    d100::UInt8
    d101::UInt8
    d102::UInt8
    d103::UInt8
    d104::UInt8
    d105::UInt8
    d106::UInt8
    d107::UInt8
    d108::UInt8
    d109::UInt8
    d110::UInt8
    d111::UInt8
    d112::UInt8
    d113::UInt8
    d114::UInt8
    d115::UInt8
    d116::UInt8
    d117::UInt8
    d118::UInt8
    d119::UInt8
    d120::UInt8
    d121::UInt8
    d122::UInt8
    d123::UInt8
    d124::UInt8
    d125::UInt8
    d126::UInt8
    d127::UInt8
    d128::UInt8
    d129::UInt8
    d130::UInt8
    d131::UInt8
    d132::UInt8
    d133::UInt8
    d134::UInt8
    d135::UInt8
    d136::UInt8
    d137::UInt8
    d138::UInt8
    d139::UInt8
    d140::UInt8
    d141::UInt8
    d142::UInt8
    d143::UInt8
    d144::UInt8
    d145::UInt8
    d146::UInt8
    d147::UInt8
    d148::UInt8
    d149::UInt8
    d150::UInt8
    d151::UInt8
    d152::UInt8
    d153::UInt8
    d154::UInt8
    d155::UInt8
    d156::UInt8
    d157::UInt8
    d158::UInt8
    d159::UInt8
    d160::UInt8
    d161::UInt8
    d162::UInt8
    d163::UInt8
    d164::UInt8
    d165::UInt8
    d166::UInt8
    d167::UInt8
    d168::UInt8
    d169::UInt8
    d170::UInt8
    d171::UInt8
    d172::UInt8
    d173::UInt8
    d174::UInt8
    d175::UInt8
    d176::UInt8
    d177::UInt8
    d178::UInt8
    d179::UInt8
    d180::UInt8
    d181::UInt8
    d182::UInt8
    d183::UInt8
    d184::UInt8
    d185::UInt8
    d186::UInt8
    d187::UInt8
    d188::UInt8
    d189::UInt8
    d190::UInt8
    d191::UInt8
    d192::UInt8
    d193::UInt8
    d194::UInt8
    d195::UInt8
    d196::UInt8
    d197::UInt8
    d198::UInt8
    d199::UInt8
    d200::UInt8
    d201::UInt8
    d202::UInt8
    d203::UInt8
    d204::UInt8
    d205::UInt8
    d206::UInt8
    d207::UInt8
    d208::UInt8
    d209::UInt8
    d210::UInt8
    d211::UInt8
    d212::UInt8
    d213::UInt8
    d214::UInt8
    d215::UInt8
    d216::UInt8
    d217::UInt8
    d218::UInt8
    d219::UInt8
    d220::UInt8
    d221::UInt8
    d222::UInt8
    d223::UInt8
    d224::UInt8
    d225::UInt8
    d226::UInt8
    d227::UInt8
    d228::UInt8
    d229::UInt8
    d230::UInt8
    d231::UInt8
    d232::UInt8
    d233::UInt8
    d234::UInt8
    d235::UInt8
    d236::UInt8
    d237::UInt8
    d238::UInt8
    d239::UInt8
    d240::UInt8
    d241::UInt8
    d242::UInt8
    d243::UInt8
    d244::UInt8
    d245::UInt8
    d246::UInt8
    d247::UInt8
    d248::UInt8
    d249::UInt8
    d250::UInt8
    d251::UInt8
    d252::UInt8
    d253::UInt8
    d254::UInt8
    d255::UInt8
    d256::UInt8
    d257::UInt8
    d258::UInt8
    d259::UInt8
    d260::UInt8
    d261::UInt8
    d262::UInt8
    d263::UInt8
    d264::UInt8
    d265::UInt8
    d266::UInt8
    d267::UInt8
    d268::UInt8
    d269::UInt8
    d270::UInt8
    d271::UInt8
    d272::UInt8
    d273::UInt8
    d274::UInt8
    d275::UInt8
    d276::UInt8
    d277::UInt8
    d278::UInt8
    d279::UInt8
    d280::UInt8
    d281::UInt8
    d282::UInt8
    d283::UInt8
    d284::UInt8
    d285::UInt8
    d286::UInt8
    d287::UInt8
    d288::UInt8
    d289::UInt8
    d290::UInt8
    d291::UInt8
    d292::UInt8
    d293::UInt8
    d294::UInt8
    d295::UInt8
    d296::UInt8
    d297::UInt8
    d298::UInt8
    d299::UInt8
    d300::UInt8
    d301::UInt8
    d302::UInt8
    d303::UInt8
    d304::UInt8
    d305::UInt8
    d306::UInt8
    d307::UInt8
    d308::UInt8
    d309::UInt8
    d310::UInt8
    d311::UInt8
    d312::UInt8
    d313::UInt8
    d314::UInt8
    d315::UInt8
    d316::UInt8
    d317::UInt8
    d318::UInt8
    d319::UInt8
    d320::UInt8
    d321::UInt8
    d322::UInt8
    d323::UInt8
    d324::UInt8
    d325::UInt8
    d326::UInt8
    d327::UInt8
    d328::UInt8
    d329::UInt8
    d330::UInt8
    d331::UInt8
    d332::UInt8
    d333::UInt8
    d334::UInt8
    d335::UInt8
    d336::UInt8
    d337::UInt8
    d338::UInt8
    d339::UInt8
    d340::UInt8
    d341::UInt8
    d342::UInt8
    d343::UInt8
    d344::UInt8
    d345::UInt8
    d346::UInt8
    d347::UInt8
    d348::UInt8
    d349::UInt8
    d350::UInt8
    d351::UInt8
    d352::UInt8
    d353::UInt8
    d354::UInt8
    d355::UInt8
    d356::UInt8
    d357::UInt8
    d358::UInt8
    d359::UInt8
    d360::UInt8
    d361::UInt8
    d362::UInt8
    d363::UInt8
    d364::UInt8
    d365::UInt8
    d366::UInt8
    d367::UInt8
    d368::UInt8
    d369::UInt8
    d370::UInt8
    d371::UInt8
    d372::UInt8
    d373::UInt8
    d374::UInt8
    d375::UInt8
    d376::UInt8
    d377::UInt8
    d378::UInt8
    d379::UInt8
    d380::UInt8
    d381::UInt8
    d382::UInt8
    d383::UInt8
    d384::UInt8
    d385::UInt8
    d386::UInt8
    d387::UInt8
    d388::UInt8
    d389::UInt8
    d390::UInt8
    d391::UInt8
    d392::UInt8
    d393::UInt8
    d394::UInt8
    d395::UInt8
    d396::UInt8
    d397::UInt8
    d398::UInt8
    d399::UInt8
    d400::UInt8
    d401::UInt8
    d402::UInt8
    d403::UInt8
    d404::UInt8
    d405::UInt8
    d406::UInt8
    d407::UInt8
    d408::UInt8
    d409::UInt8
    d410::UInt8
    d411::UInt8
    d412::UInt8
    d413::UInt8
    d414::UInt8
    d415::UInt8
    d416::UInt8
    d417::UInt8
    d418::UInt8
    d419::UInt8
    d420::UInt8
    d421::UInt8
    d422::UInt8
    d423::UInt8
    d424::UInt8
    d425::UInt8
    d426::UInt8
    d427::UInt8
    d428::UInt8
    d429::UInt8
    d430::UInt8
    d431::UInt8
    d432::UInt8
    d433::UInt8
    d434::UInt8
    d435::UInt8
    d436::UInt8
    d437::UInt8
    d438::UInt8
    d439::UInt8
    d440::UInt8
    d441::UInt8
    d442::UInt8
    d443::UInt8
    d444::UInt8
    d445::UInt8
    d446::UInt8
    d447::UInt8
    d448::UInt8
    d449::UInt8
    d450::UInt8
    d451::UInt8
    d452::UInt8
    d453::UInt8
    d454::UInt8
    d455::UInt8
    d456::UInt8
    d457::UInt8
    d458::UInt8
    d459::UInt8
    d460::UInt8
    d461::UInt8
    d462::UInt8
    d463::UInt8
    d464::UInt8
    d465::UInt8
    d466::UInt8
    d467::UInt8
    d468::UInt8
    d469::UInt8
    d470::UInt8
    d471::UInt8
    d472::UInt8
    d473::UInt8
    d474::UInt8
    d475::UInt8
    d476::UInt8
    d477::UInt8
    d478::UInt8
    d479::UInt8
    d480::UInt8
    d481::UInt8
    d482::UInt8
    d483::UInt8
    d484::UInt8
    d485::UInt8
    d486::UInt8
    d487::UInt8
    d488::UInt8
    d489::UInt8
    d490::UInt8
    d491::UInt8
    d492::UInt8
    d493::UInt8
    d494::UInt8
    d495::UInt8
    d496::UInt8
    d497::UInt8
    d498::UInt8
    d499::UInt8
    d500::UInt8
    d501::UInt8
    d502::UInt8
    d503::UInt8
    d504::UInt8
    d505::UInt8
    d506::UInt8
    d507::UInt8
    d508::UInt8
    d509::UInt8
    d510::UInt8
    d511::UInt8
    d512::UInt8
    d513::UInt8
    d514::UInt8
    d515::UInt8
    d516::UInt8
    d517::UInt8
    d518::UInt8
    d519::UInt8
    d520::UInt8
    d521::UInt8
    d522::UInt8
    d523::UInt8
    d524::UInt8
    d525::UInt8
    d526::UInt8
    d527::UInt8
    d528::UInt8
    d529::UInt8
    d530::UInt8
    d531::UInt8
    d532::UInt8
    d533::UInt8
    d534::UInt8
    d535::UInt8
    d536::UInt8
    d537::UInt8
    d538::UInt8
    d539::UInt8
    d540::UInt8
    d541::UInt8
    d542::UInt8
    d543::UInt8
    d544::UInt8
    d545::UInt8
    d546::UInt8
    d547::UInt8
    d548::UInt8
    d549::UInt8
    d550::UInt8
    d551::UInt8
    d552::UInt8
    d553::UInt8
    d554::UInt8
    d555::UInt8
    d556::UInt8
    d557::UInt8
    d558::UInt8
    d559::UInt8
    d560::UInt8
    d561::UInt8
    d562::UInt8
    d563::UInt8
    d564::UInt8
    d565::UInt8
    d566::UInt8
    d567::UInt8
    d568::UInt8
    d569::UInt8
    d570::UInt8
    d571::UInt8
    d572::UInt8
    d573::UInt8
    d574::UInt8
    d575::UInt8
    d576::UInt8
    d577::UInt8
    d578::UInt8
    d579::UInt8
    d580::UInt8
    d581::UInt8
    d582::UInt8
    d583::UInt8
    d584::UInt8
    d585::UInt8
    d586::UInt8
    d587::UInt8
    d588::UInt8
    d589::UInt8
    d590::UInt8
    d591::UInt8
    d592::UInt8
    d593::UInt8
    d594::UInt8
    d595::UInt8
    d596::UInt8
    d597::UInt8
    d598::UInt8
    d599::UInt8
    d600::UInt8
    d601::UInt8
    d602::UInt8
    d603::UInt8
    d604::UInt8
    d605::UInt8
    d606::UInt8
    d607::UInt8
    d608::UInt8
    d609::UInt8
    d610::UInt8
    d611::UInt8
    d612::UInt8
    d613::UInt8
    d614::UInt8
    d615::UInt8
    d616::UInt8
    d617::UInt8
    d618::UInt8
    d619::UInt8
    d620::UInt8
    d621::UInt8
    d622::UInt8
    d623::UInt8
    d624::UInt8
    d625::UInt8
    d626::UInt8
    d627::UInt8
    d628::UInt8
    d629::UInt8
    d630::UInt8
    d631::UInt8
    d632::UInt8
    d633::UInt8
    d634::UInt8
    d635::UInt8
    d636::UInt8
    d637::UInt8
    d638::UInt8
    d639::UInt8
    d640::UInt8
    d641::UInt8
    d642::UInt8
    d643::UInt8
    d644::UInt8
    d645::UInt8
    d646::UInt8
    d647::UInt8
    d648::UInt8
    d649::UInt8
    d650::UInt8
    d651::UInt8
    d652::UInt8
    d653::UInt8
    d654::UInt8
    d655::UInt8
    d656::UInt8
    d657::UInt8
    d658::UInt8
    d659::UInt8
    d660::UInt8
    d661::UInt8
    d662::UInt8
    d663::UInt8
    d664::UInt8
    d665::UInt8
    d666::UInt8
    d667::UInt8
    d668::UInt8
    d669::UInt8
    d670::UInt8
    d671::UInt8
    d672::UInt8
    d673::UInt8
    d674::UInt8
    d675::UInt8
    d676::UInt8
    d677::UInt8
    d678::UInt8
    d679::UInt8
    d680::UInt8
    d681::UInt8
    d682::UInt8
    d683::UInt8
    d684::UInt8
    d685::UInt8
    d686::UInt8
    d687::UInt8
    d688::UInt8
    d689::UInt8
    d690::UInt8
    d691::UInt8
    d692::UInt8
    d693::UInt8
    d694::UInt8
    d695::UInt8
    d696::UInt8
    d697::UInt8
    d698::UInt8
    d699::UInt8
    d700::UInt8
    d701::UInt8
    d702::UInt8
    d703::UInt8
    d704::UInt8
    d705::UInt8
    d706::UInt8
    d707::UInt8
    d708::UInt8
    d709::UInt8
    d710::UInt8
    d711::UInt8
    d712::UInt8
    d713::UInt8
    d714::UInt8
    d715::UInt8
    d716::UInt8
    d717::UInt8
    d718::UInt8
    d719::UInt8
    d720::UInt8
    d721::UInt8
    d722::UInt8
    d723::UInt8
    d724::UInt8
    d725::UInt8
    d726::UInt8
    d727::UInt8
    d728::UInt8
    d729::UInt8
    d730::UInt8
    d731::UInt8
    d732::UInt8
    d733::UInt8
    d734::UInt8
    d735::UInt8
    d736::UInt8
    d737::UInt8
    d738::UInt8
    d739::UInt8
    d740::UInt8
    d741::UInt8
    d742::UInt8
    d743::UInt8
    d744::UInt8
    d745::UInt8
    d746::UInt8
    d747::UInt8
    d748::UInt8
    d749::UInt8
    d750::UInt8
    d751::UInt8
    d752::UInt8
    d753::UInt8
    d754::UInt8
    d755::UInt8
    d756::UInt8
    d757::UInt8
    d758::UInt8
    d759::UInt8
    d760::UInt8
    d761::UInt8
    d762::UInt8
    d763::UInt8
    d764::UInt8
    d765::UInt8
    d766::UInt8
    d767::UInt8
    d768::UInt8
    d769::UInt8
    d770::UInt8
    d771::UInt8
    d772::UInt8
    d773::UInt8
    d774::UInt8
    d775::UInt8
    d776::UInt8
    d777::UInt8
    d778::UInt8
    d779::UInt8
    d780::UInt8
    d781::UInt8
    d782::UInt8
    d783::UInt8
    d784::UInt8
    d785::UInt8
    d786::UInt8
    d787::UInt8
    d788::UInt8
    d789::UInt8
    d790::UInt8
    d791::UInt8
    d792::UInt8
    d793::UInt8
    d794::UInt8
    d795::UInt8
    d796::UInt8
    d797::UInt8
    d798::UInt8
    d799::UInt8
    d800::UInt8
    d801::UInt8
    d802::UInt8
    d803::UInt8
    d804::UInt8
    d805::UInt8
    d806::UInt8
    d807::UInt8
    d808::UInt8
    d809::UInt8
    d810::UInt8
    d811::UInt8
    d812::UInt8
    d813::UInt8
    d814::UInt8
    d815::UInt8
    d816::UInt8
    d817::UInt8
    d818::UInt8
    d819::UInt8
    d820::UInt8
    d821::UInt8
    d822::UInt8
    d823::UInt8
    d824::UInt8
    d825::UInt8
    d826::UInt8
    d827::UInt8
    d828::UInt8
    d829::UInt8
    d830::UInt8
    d831::UInt8
    d832::UInt8
    d833::UInt8
    d834::UInt8
    d835::UInt8
    d836::UInt8
    d837::UInt8
    d838::UInt8
    d839::UInt8
    d840::UInt8
    d841::UInt8
    d842::UInt8
    d843::UInt8
    d844::UInt8
    d845::UInt8
    d846::UInt8
    d847::UInt8
    d848::UInt8
    d849::UInt8
    d850::UInt8
    d851::UInt8
    d852::UInt8
    d853::UInt8
    d854::UInt8
    d855::UInt8
    d856::UInt8
    d857::UInt8
    d858::UInt8
    d859::UInt8
    d860::UInt8
    d861::UInt8
    d862::UInt8
    d863::UInt8
    d864::UInt8
    d865::UInt8
    d866::UInt8
    d867::UInt8
    d868::UInt8
    d869::UInt8
    d870::UInt8
    d871::UInt8
    d872::UInt8
    d873::UInt8
    d874::UInt8
    d875::UInt8
    d876::UInt8
    d877::UInt8
    d878::UInt8
    d879::UInt8
    d880::UInt8
    d881::UInt8
    d882::UInt8
    d883::UInt8
    d884::UInt8
    d885::UInt8
    d886::UInt8
    d887::UInt8
    d888::UInt8
    d889::UInt8
    d890::UInt8
    d891::UInt8
    d892::UInt8
    d893::UInt8
    d894::UInt8
    d895::UInt8
    d896::UInt8
    d897::UInt8
    d898::UInt8
    d899::UInt8
    d900::UInt8
    d901::UInt8
    d902::UInt8
    d903::UInt8
    d904::UInt8
    d905::UInt8
    d906::UInt8
    d907::UInt8
    d908::UInt8
    d909::UInt8
    d910::UInt8
    d911::UInt8
    d912::UInt8
    d913::UInt8
    d914::UInt8
    d915::UInt8
    d916::UInt8
    d917::UInt8
    d918::UInt8
    d919::UInt8
    d920::UInt8
    d921::UInt8
    d922::UInt8
    d923::UInt8
    d924::UInt8
    d925::UInt8
    d926::UInt8
    d927::UInt8
    d928::UInt8
    d929::UInt8
    d930::UInt8
    d931::UInt8
    d932::UInt8
    d933::UInt8
    d934::UInt8
    d935::UInt8
    d936::UInt8
    d937::UInt8
    d938::UInt8
    d939::UInt8
    d940::UInt8
    d941::UInt8
    d942::UInt8
    d943::UInt8
    d944::UInt8
    d945::UInt8
    d946::UInt8
    d947::UInt8
    d948::UInt8
    d949::UInt8
    d950::UInt8
    d951::UInt8
    d952::UInt8
    d953::UInt8
    d954::UInt8
    d955::UInt8
    d956::UInt8
    d957::UInt8
    d958::UInt8
    d959::UInt8
    d960::UInt8
    d961::UInt8
    d962::UInt8
    d963::UInt8
    d964::UInt8
    d965::UInt8
    d966::UInt8
    d967::UInt8
    d968::UInt8
    d969::UInt8
    d970::UInt8
    d971::UInt8
    d972::UInt8
    d973::UInt8
    d974::UInt8
    d975::UInt8
    d976::UInt8
    d977::UInt8
    d978::UInt8
    d979::UInt8
    d980::UInt8
    d981::UInt8
    d982::UInt8
    d983::UInt8
    d984::UInt8
    d985::UInt8
    d986::UInt8
    d987::UInt8
    d988::UInt8
    d989::UInt8
    d990::UInt8
    d991::UInt8
    d992::UInt8
    d993::UInt8
    d994::UInt8
    d995::UInt8
    d996::UInt8
    d997::UInt8
    d998::UInt8
    d999::UInt8
    d1000::UInt8
    d1001::UInt8
    d1002::UInt8
    d1003::UInt8
    d1004::UInt8
    d1005::UInt8
    d1006::UInt8
    d1007::UInt8
    d1008::UInt8
    d1009::UInt8
    d1010::UInt8
    d1011::UInt8
    d1012::UInt8
    d1013::UInt8
    d1014::UInt8
    d1015::UInt8
    d1016::UInt8
    d1017::UInt8
    d1018::UInt8
    d1019::UInt8
    d1020::UInt8
    d1021::UInt8
    d1022::UInt8
    d1023::UInt8
    d1024::UInt8
end

zero(::Type{Array_1024_Uint8}) = Array_1024_Uint8(fill(zero(UInt8),1024)...)

immutable 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
    start_time::Int64
    end_time::Int64
    pts_wrap_reference::Int64
    pts_wrap_behavior::Cint
end

immutable 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  =  UInt32(0)
const AVFMT_DURATION_FROM_STREAM  =  UInt32(1)
const AVFMT_DURATION_FROM_BITRATE  =  UInt32(2)
# end enum AVDurationEstimationMethod

const AVFormatInternal = Void
const av_format_control_message = Ptr{Void}

immutable AVFormatContext
    av_class::Ptr{AVClass}
    iformat::Ptr{AVInputFormat}
    oformat::Ptr{AVOutputFormat}
    priv_data::Ptr{Void}
    pb::Ptr{AVIOContext}
    ctx_flags::Cint
    nb_streams::UInt32
    streams::Ptr{Ptr{AVStream}}
    filename::Array_1024_Uint8
    start_time::Int64
    duration::Int64
    bit_rate::Cint
    packet_size::UInt32
    max_delay::Cint
    flags::Cint
    probesize::UInt32
    max_analyze_duration::Cint
    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
    ts_id::Cint
    audio_preload::Cint
    max_chunk_duration::Cint
    max_chunk_size::Cint
    use_wallclock_as_timestamps::Cint
    avoid_negative_ts::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
    packet_buffer::Ptr{AVPacketList}
    packet_buffer_end::Ptr{AVPacketList}
    data_offset::Int64
    raw_packet_buffer::Ptr{AVPacketList}
    raw_packet_buffer_end::Ptr{AVPacketList}
    parse_queue::Ptr{AVPacketList}
    parse_queue_end::Ptr{AVPacketList}
    raw_packet_buffer_remaining_size::Cint
    offset::Int64
    offset_timebase::AVRational
    internal::Ptr{AVFormatInternal}
    io_repositioned::Cint
    video_codec::Ptr{AVCodec}
    audio_codec::Ptr{AVCodec}
    subtitle_codec::Ptr{AVCodec}
    metadata_header_padding::Cint
    opaque::Ptr{Void}
    control_message_cb::av_format_control_message
    output_ts_offset::Int64
    max_analyze_duration2::Int64
    probesize2::Int64
    dump_separator::Ptr{UInt8}
end

const AVDeviceInfoList = Void
const AVDeviceCapabilitiesQuery = Void

max_stars_repo_name: asafasban/AAVideoIO

max_issues_repo_name: asafasban/AAVideoIO

max_forks_repo_name: asafasban/AAVideoIO


text:
# # [Illustration of the Gradient of a Second Order Difference](@id secondOrderDifferenceGrad)
#
# This example explains how to compute the gradient of the second order
# difference mid point model using [`adjointJacobiField`](@ref)s.
#
# This example also illustrates the [`Power`](@ref) manifold as well
# as [`ArmijoLinesearch`](@ref).

# We first initialize the manifold
exportFolder = joinpath(@__DIR__,"..","..","docs","src","assets","images","tutorials") #src
using Manopt
# and we define some colors from [Paul Tol](https://personal.sron.nl/~pault/)
using Colors
black = RGBA{Float64}(colorant"#000000")
TolVibrantBlue = RGBA{Float64}(colorant"#0077BB") # points
TolVibrantOrange = RGBA{Float64}(colorant"#EE7733") # results
TolVibrantCyan = RGBA{Float64}(colorant"#33BBEE") # vectors
TolVibrantTeal = RGBA{Float64}(colorant"#009988") # geo
asyResolution = 2
nothing #hide
# Assume we have two [`SnPoint`](@ref)s $x,y$ on the equator of the
# [`Sphere`](@ref)`(2)` $\mathcal M = \mathbb S^2$
# and a point $y$ near the north pole
M = Sphere(2)
x = SnPoint([1., 0., 0.])
z = SnPoint([0., 1., 0.])
c = midPoint(M,x,z)
#src y is the north pole just bend a little bit towards
y = geodesic(M, SnPoint([0., 0., 1.]), c, 0.1)
[c,y]
# Now the second order absolute difference can be stated as (see [[Bačák, Bergmann, Steidl, Weinmann, 2016](#BacakBergmannSteidlWeinmann2016)])
#
# $d_2(x,y,z) := \min_{c\in\mathcal C_{x,z}} d_{\mathcal M}(c,y),\qquad x,y,z\in\mathcal M,$
#
# where $\mathcal C_{x,z}$ is the set of all mid points $g(\frac{1}{2};x,z)$, where $g$
# is a (not necessarily minimizing) geodesic connecting $x$ and $z$.
#
# For illustration we further define the point opposite of
c2 = opposite(M,c)
# and draw the geodesic connecting $y$ and the nearest mid point $c$, namely
T = [0:0.1:1.0...]
geoPts_yc = geodesic(M,y,c,T)
nothing #hide
# looks as follows using [`renderAsymptote`](@ref) with the [`asyExportS2Signals`](@ref) export
renderAsymptote(exportFolder*"/SecondOrderData.asy",asyExportS2Signals; #src
    render = asyResolution, #src
    curves = [ geoPts_yc ], #src
    points = [ [x,y,z], [c,c2] ], #src
    colors=Dict(:curves => [TolVibrantTeal], :points => [black, TolVibrantBlue]), #src
    dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5) #src
) #src
#md #
#md # ```julia
#md # renderAsymptote("secondOrderData.asy",asyExportS2Signals;
#md #     render = asyResolution,
#md #     curves = [ geoPts_yc ],
#md #     points = [ [x,y,z], [c,c2] ],
#md #     colors=Dict(:curves => [TolVibrantTeal], :points => [black, TolVibrantBlue]),
#md #     dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5)
#md # )
#md # ```
#
#md # ![Three points $x,y,z$ and the midpoint $c=c(x,z)$ (blue)](../assets/images/tutorials/SecondOrderData.png)
#
# Since we moved $y$ 10% along the geodesic from the north pole to $c$, the distance
# to $c$ is $\frac{9\pi}{20}\approx 1.4137$, and this is also what
costTV2(M, (x,y,z) )
# returns, see [`costTV2`](@ref) for reference. But also its gradient can be
# easily computed since it is just a distance with respect to $y$ and a
# concatenation of a geodesic, where the start or end point is the argument,
# respectively, with a distance.
# Hence the [adjoint differentials](@ref adjointDifferentialFunctions)
# [`AdjDxGeo`](@ref) and [`AdjDyGeo`](@ref) can be employed,
# see [`gradTV2`](@ref) for details.
# we obtain
(ξx, ξy, ξz) = gradTV2(M, (x,y,z) )
#
# When we aim to minimize this, we look at the negative gradient, i.e.
# we can draw this as
renderAsymptote(exportFolder*"/SecondOrderGradient.asy",asyExportS2Signals; #src
    render = asyResolution, #src
    points = [ [x,y,z], [c,c2] ], #src
    tVectors = [TVectorE.( [-ξx, -ξy, -ξz], [x, y, z] )], #src
    colors=Dict(:tvectors => [TolVibrantCyan], :points => [black, TolVibrantBlue]), #src
    dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5) #src
) #src
#md #
#md # ```julia
#md # renderAsymptote("SecondOrderGradient.asy",asyExportS2Signals;
#md #    render = asyResolution,
#md #    points = [ [x,y,z], [c,c2] ],
#md #    tVectors = [TVectorE.( [-ξx, -ξy, -ξz], [x, y, z] )],
#md #    colors=Dict(:tvectors => [TolVibrantCyan], :points => [black, TolVibrantBlue]),
#md #    dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5)
#md # )
#md # ```
#md #
#md # ![Three points $x,y,z$ and the negative gradient of the second order absolute difference](../assets/images/tutorials/SecondOrderGradient.png)
#
# If we now perform a gradient step, we obtain the three points
xn, yn, zn = exp.(Ref(M), [x,y,z], [-ξx,-ξy,-ξz])
# as well we the new mid point
cn = midPoint(M,xn,zn)
geoPts_yncn = geodesic(M,yn,cn,T)
nothing #hide
# and obtain the new situation
renderAsymptote(exportFolder*"/SecondOrderMin1.asy",asyExportS2Signals; #src
    render = asyResolution, #src
    points = [ [x,y,z], [c,c2,cn], [xn,yn,zn] ], #src
    curves = [ geoPts_yncn ], #src
    tVectors = [TVectorE.( [-ξx, -ξy, -ξz], [x, y, z] )], #src
    colors=Dict(:tvectors => [TolVibrantCyan], #src
                :points => [black, TolVibrantBlue, TolVibrantOrange], #src
                :curves => [TolVibrantTeal] #src
                ), #src
    dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5) #src
) #src
#md #
#md # ```julia
#md # renderAsymptote("SecondOrderMin1.asy",asyExportS2Signals;
#md #     render = asyResolution,
#md #     points = [ [x,y,z], [c,c2,cn], [xn,yn,zn] ],
#md #     curves = [ geoPts_yncn ] ,
#md #     tVectors = [TVectorE.( [-ξx, -ξy, -ξz], [x, y, z] )],
#md #     colors=Dict(:tvectors => [TolVibrantCyan],
#md #         :points => [black, TolVibrantBlue, TolVibrantOrange],
#md #         :curves => [TolVibrantTeal]
#md #     ),
#md #     dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5)
#md # )
#md # ```
#md
#md # ![A gradient Step](../assets/images/tutorials/SecondOrderMin1.png)
#
# One can see, that this step slightly “overshoots”, i.e. $y$ is now even below $c$.
# and the cost function is still at
costTV2(M, (xn, yn, zn) )
#
# But we can also search for the best step size using [`ArmijoLinesearch`](@ref)
# on the [`Power`](@ref) manifold $\mathcal N = \mathcal M^3 = (\mathbb S^2)^3$
p = PowPoint([x,y,z])
N = Power(M,3)
s = ArmijoLinesearch(1.0,exp,0.999,0.96)(N, p,
    x -> costTV2(M, Tuple(getValue(x))),
    PowTVector( [ gradTV2(M, (x,y,z))... ] ) # transform from tuple to PowTVector
)
# and for the new points
xm, ym, zm = exp.(Ref(M), [x,y,z], s*[-ξx,-ξy,-ξz])
cm = midPoint(M,xm,zm)
geoPts_xmzm = geodesic(M,xm,zm,T)
nothing #hide
# we obtain again with
renderAsymptote(exportFolder*"/SecondOrderMin2.asy",asyExportS2Signals; #src
    render = asyResolution, #src
    points = [ [x,y,z], [c,c2,cm], [xm,ym,zm] ], #src
    curves = [ geoPts_xmzm ], #src
    tVectors = [TVectorE.( [-ξx, -ξy, -ξz], [x, y, z] )], #src
    colors=Dict(:tvectors => [TolVibrantCyan], #src
                :points => [black, TolVibrantBlue, TolVibrantOrange], #src
                :curves => [TolVibrantTeal] #src
                ), #src
    dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5) #src
) #src
#md #
#md # ```julia
#md # renderAsymptote("SecondOrderMin2.asy",asyExportS2Signals;
#md #     render = asyResolution,
#md #     points = [ [x,y,z], [c,c2,cm], [xm,ym,zm] ],
#md #     curves = [ geoPts_xmzm ] ,
#md #     tVectors = [TVectorE.( [-ξx, -ξy, -ξz], [x, y, z] )],
#md #     colors=Dict(:tvectors => [TolVibrantCyan],
#md #                 :points => [black, TolVibrantBlue, TolVibrantOrange],
#md #                 :curves => [TolVibrantTeal]
#md #                 ),
#md #     dotSize = 3.5, lineWidth = 0.75, cameraPosition = (1.2,1.,.5)
#md # )
#md # ```
#md #
#md # ![A gradient Step](../assets/images/tutorials/SecondOrderMin2.png)
#
# Here, the cost function yields
costTV2( M, (xm, ym, zm) )
# which is nearly zero, as one can also see, since the new center $c$ and $y$
# are quite close.
#
# ## Literature
#
# ```@raw html
# <ul>
# <li id="BačákBergmannSteidlWeinmann2016">[<a>Bačák, Bergmann, Steidl, Weinmann, 2016</a>]
#   Bačák, M; Bergmann, R.; Steidl, G; Weinmann, A.: <emph>A second order nonsmooth
#   variational model for restoring manifold-valued images.</emph>,
#   SIAM Journal on Scientific Computations, Volume 38, Number 1, pp. A567–597,
#   doi: <a href="https://doi.org/10.1137/15M101988X">10.1137/15M101988X</a></li>
# </ul>
# ```

ext: jl


text:
using LinearAlgebra, Jets, JetPack, Test

n1,n2 = 33,44

@testset "JopAtan, correctness T=$(T)" for T in (Float64,Float32,Complex{Float64},Complex{Float32})
    F = JopAtan(JetSpace(T,n1,n2))
    x1 = rand(domain(F))
    @test F*x1 ≈ atan.(x1) .+ π/2
end

@testset "JopAtan, linearity test, T=$(T)" for T in (Float64,Float32,Complex{Float64},Complex{Float32})
    F = JopAtan(JetSpace(T,n1,n2))
    J = jacobian(F, rand(domain(F)))
    lhs,rhs = linearity_test(J)
    @test lhs ≈ rhs
end

@testset "JopAtan, dot product test, T=$(T)" for T in (Float64,Float32,Complex{Float64},Complex{Float32})
    F = JopAtan(JetSpace(T,n1,n2))
    J  = jacobian!(F, rand(domain(F)))
    lhs, rhs = dot_product_test(J, -1 .+ 2 .* rand(domain(J)), -1 .+ 2 .* rand(range(J)))
    @test lhs ≈ rhs
end

@testset "JopAtan, linearization test, T=$(T)" for T in (Float64,Float32,Complex{Float64},Complex{Float32})
    F = JopAtan(JetSpace(T,n1,n2))
    m0 = 0.5 .* (-1 .+ rand(domain(F)))
    μ  = sqrt.([1/1,1/2,1/4,1/8,1/16,1/32,1/64,1/128,1/256,1/512,1/1024,1/2048,1/4096,1/8192])
    δm = rand(domain(F))
    observed, expected = linearization_test(F, m0, μ = μ, δm = δm)
    δ = minimum(abs, observed - expected)
    @test δ < 0.1
end


text:
using SeisReconstruction
using Test

# test that FFTOp passes the dot product test

m_rand = rand(ComplexF64,(20,20,20,20));
d_rand = rand(ComplexF64,(20,20,20,20));

T = rand(20,20,20,20);

a = (LinearIndices(T))[findall(T.<=0.5)];
b = (LinearIndices(T))[findall(T.>0.5)];

T[a] .= 0.;
T[b] .= 1.;

operators = [WeightingOp,FFTOp,WeightingOp]
parameters = [Dict(:w=>T),Dict(:normalize=>true),Dict(:w=>fill(1,size(T)))]

a,b = DotTest(m_rand,d_rand,operators,parameters)
@test abs((a-b)/a) < 0.01


text:
using ElectronicStructure

function test_main()
  LatVecs = 10.0*diagm(ones(3))
  pw = PWGrid( 20.0, LatVecs)
  Ns = pw.Ns
  @printf("Sampling points: (%d,%d,%d)\n", Ns[1], Ns[2], Ns[3])
  actual = prod(pw.Ns)/pw.gvecw.Ngwx
  theor = 1/(4*pi*0.25^3/3)
  @printf("Actual, theor: %10.5f %10.5f\n", actual, theor)
end

test_main()


text:
using Documenter, Queryverse

makedocs(
	modules=[Queryverse],
	sitename="Queryverse.jl",
	analytics="UA-132838790-1",
	pages=[
        "Introduction" => "index.md"
    ]
)

deploydocs(
    repo="github.com/queryverse/Queryverse.jl.git"
)


text:
function DESPOTAlphaTree(p::DESPOTAlphaPlanner{S,A,O}, b0::RB) where {S,A,O,RB}
    sol = solver(p)
    b0, all_terminal = strip_terminals(b0, p.pomdp)
    if all_terminal
        error("All states in the current belief are terminal.")
    end
    resampled_P = resample(sol.K, b0, p.pomdp, p.rng)
    L = Vector{Float64}(undef, sol.K)
    U = Vector{Float64}(undef, sol.K)
    bounds!(L, U, p.bounds, p.pomdp, resampled_P, sol.max_depth)
    if sol.tree_in_info || p.tree === nothing
        p.tree = DESPOTAlphaTree([fill(1.0/sol.K, sol.K)],
                        [Float64[]],
                        [1:0],
                        [0],
                        [0],
                        [mean(U)],
                        [mean(L)],
                        [1.0],

                        UnitRange{Int64}[],
                        Int[],
                        Float64[],
                        Float64[],
                        A[],

                        Dict{Vector{A}, Int}(),
                        Vector{S}[],
                        Vector{O}[],
                        Vector{Float64}[],
                        Matrix{Float64}[],
                        Vector{Float64}[],
                        Vector{Float64}[],
                        Vector{Float64}[],

                        resampled_P,
                        1,
                        0,
                        0
                    )
        resize_b!(p.tree, sol.num_b, sol.K)
        resize_ba!(p.tree, sol.num_b)
    else
        reset!(p.tree, resampled_P, mean(U), mean(L))
    end
    return p.tree::DESPOTAlphaTree{S,A,O}
end

function reset!(tree::DESPOTAlphaTree{S}, P::Vector{S}, u::Float64, l::Float64) where S
    fill!(tree.children, 1:0)
    fill!(view(tree.obs_prob, 2:length(tree.obs_prob)), 0.0)
    empty!.(tree.obs)
    empty!(tree.as_map)
    tree.u[1] = u
    tree.l[1] = l
    tree.b = 1
    tree.ba = 0
    tree.as = 0
    tree.root_particles = P
    return nothing
end

Base.zero(::Type{AbstractVector{T}}) where T = T[]

function expand!(D::DESPOTAlphaTree{T,A,Z}, b::Int, as::Vector{A}, p::DESPOTAlphaPlanner{T,A,Z}) where {T,A,Z}
    if b == 1
        P = D.root_particles
    else
        P = D.particles[D.as_map[as]]
    end

    sol = solver(p)
    acts = actions(p.pomdp, WeightedParticleBelief(P, D.weights[b]))
    num_a = length(acts)
    K = sol.K
    C = sol.C
    resize_ba!(D, D.ba + num_a)
    resize_b!(D, D.b + (C + 1) * num_a, sol.K)
    D.children[b] = (D.ba + 1):(D.ba + num_a)

    # Initialize action sequences
    asa = push!(copy(as), acts[1])
    if !haskey(D.as_map, asa)
        resize_as!(D, D.as + num_a, K)
        for a in acts
            D.as += 1
            D.as_map[push!(copy(as), a)] = D.as
            S, O, R = propagate_particles(D, P, a, p)
            L = Matrix{Float64}(undef, (length(O)+1, K))
            η_max = 1e-10
            for spi in eachindex(S)
                η = 0.0
                for (oi, o) in enumerate(O)
                    η += L[oi, spi] = pdf(p.obs_dists[spi], o)
                end
                if η > η_max
                    η_max = η
                end
                L[end, spi] = η
            end
            for spi in eachindex(S)
                for (oi, o) in enumerate(O)
                    L[oi, spi] /= η_max
                end
                L[end, spi] = 1.0 - L[end, spi]/η_max
            end
            push!(O, zero(Z))
            D.L[D.as] = L
            bounds!(D.def_alpha[D.as], D.pp_alpha_upper[D.as], p.bounds, p.pomdp, S, sol.max_depth - D.Delta[b])
            D.def_alpha_upper[D.as] .= D.pp_alpha_upper[D.as]
        end
    end

    # Initialize action branches
    for a in acts
        asa[length(asa)] = a
        as_ba = D.as_map[asa]
        D.ba += 1 # increase ba count
        n_obs = length(D.obs[as_ba]) # number of new obs
        fbp = D.b + 1 # first bp
        lbp = D.b + n_obs # last bp
        D.b += n_obs

        # Calculate child beliefs
        W = view(D.weights, fbp:lbp)
        obs_w = view(D.obs_prob, fbp:lbp)
        for oi in 1:n_obs
            for spi in 1:sol.K
                obs_w[oi] += W[oi][spi] = D.L[as_ba][oi, spi] * D.weights[b][spi]
            end
        end
        for oi in 1:n_obs
            W[oi] ./= obs_w[oi] + 1e-10
        end

        # Initialize the new action branch
        D.ba_children[D.ba] = fbp:lbp
        D.ba_parent[D.ba] = b
        D.ba_action[D.ba] = a

        # Initialize new obs branches
        view(D.parent, fbp:lbp) .= D.ba
        view(D.Delta, fbp:lbp) .= D.Delta[b] + 1
        view(D.obs_prob, fbp:lbp) .= obs_w
        broadcast!(x->dot(x, D.def_alpha[as_ba]), view(D.l, fbp:lbp), W)
        broadcast!(x->dot(x, D.def_alpha_upper[as_ba]), view(D.u, fbp:lbp), W)
        for i in fbp:lbp
            D.alpha[i] = D.def_alpha[as_ba]
        end

        # update upper bounds for action selection
        D.ba_u[D.ba] = D.weights[b]' * D.r[as_ba] + discount(p.pomdp) * sum(D.u[bp] * D.obs_prob[bp] for bp in D.ba_children[D.ba])
        D.ba_l[D.ba] = D.weights[b]' * D.r[as_ba] + discount(p.pomdp) * sum(D.l[bp] * D.obs_prob[bp] for bp in D.ba_children[D.ba])
    end
    # With this update, we need not to check all action branches during backup.
    D.u[b] = maximum(D.ba_u[ba] for ba in D.children[b])
    D.l[b] = maximum(D.ba_l[ba] for ba in D.children[b])
    return nothing
end

POMDPs.pdf(dist::Nothing, o) = 0.0

function strip_terminals(b, m::POMDP)
    return b, false
end

function strip_terminals(b::AbstractParticleBelief, m::POMDP)
    w_sum = 0.0
    P = particles(b)
    W = weights(b)
    @inbounds for (i, s) in enumerate(P)
        if isterminal(m, s)
            W[i] = 0.0
        else
            w_sum += W[i]
        end
    end
    return WeightedParticleBelief(P, W / (w_sum + 1e-10), 1.0), w_sum == 0.0
end

function propagate_particles(D::DESPOTAlphaTree, particles::Vector, a, p::DESPOTAlphaPlanner)
    sol = solver(p)
    S = D.particles[D.as]
    O = D.obs[D.as]
    R = D.r[D.as]
    empty!(p.obs_ind_dict)

    for (i, s) in enumerate(particles)
        if isterminal(p.pomdp, s)
            S[i] = s
            R[i] = 0.0
            p.obs_dists[i] = nothing
        else
            sp, o, r = @gen(:sp, :o, :r)(p.pomdp, s, a, p.rng)
            S[i] = sp
            R[i] = r
            p.obs_dists[i] = observation(p.pomdp, a, sp)
            if !haskey(p.obs_ind_dict, o) && length(O) < sol.C
                push!(O, o)
                p.obs_ind_dict[o] = length(O)
            end
        end
    end
    return S, O, R
end

function resize_b!(D::DESPOTAlphaTree, n::Int, K::Int)
    if n > length(D.weights)
        resize!(D.weights, n)
        resize!(D.alpha, n)
        resize!(D.children, n)
        resize!(D.obs_prob, n)
        @inbounds for i in (length(D.parent)+1):n
            D.weights[i] = Vector{Float64}(undef, K)
            D.children[i] = 1:0
            D.obs_prob[i] = 0.0
        end
        resize!(D.parent, n)
        resize!(D.Delta, n)
        resize!(D.u, n)
        resize!(D.l, n)
    end
    return nothing
end

function resize_ba!(D::DESPOTAlphaTree{S}, n::Int) where S
    if n > length(D.ba_children)
        resize!(D.ba_children, n)
        resize!(D.ba_parent, n)
        resize!(D.ba_u, n)
        resize!(D.ba_l, n)
        resize!(D.ba_action, n)
    end
    return nothing
end

function resize_as!(D::DESPOTAlphaTree{S,A,O}, n::Int, K::Int) where {S,A,O}
    if n > length(D.particles)
        resize!(D.particles, n)
        resize!(D.obs, n)
        resize!(D.r, n)
        resize!(D.def_alpha, n)
        resize!(D.def_alpha_upper, n)
        resize!(D.pp_alpha_upper, n)
        @inbounds for i in (length(D.L)+1):n
            D.particles[i] = Vector{S}(undef, K)
            D.obs[i] = O[]
            D.r[i] = Vector{Float64}(undef, K)
            D.def_alpha[i] = Vector{Float64}(undef, K)
            D.def_alpha_upper[i] = Vector{Float64}(undef, K)
            D.pp_alpha_upper[i] = Vector{Float64}(undef, K)
        end
        resize!(D.L, n)
    end
    return nothing
end

function resample(m::Int, b::AbstractParticleBelief{S}, pomdp::POMDP{S}, rng::AbstractRNG) where S
    step = weight_sum(b)/m
    U = rand(rng)*step
    c = weight(b,1) # accumulate sum of weights
    i = 1
    P = particles(b)
    P_resampled = Vector{S}(undef, m)
    @inbounds for j in 1:m
        while U > c
            i += 1
            c += weight(b, i)
        end
        U += step
        P_resampled[j] = P[i]
    end
    return P_resampled
end

function resample(m::Int, b, pomdp::POMDP{S}, rng::AbstractRNG) where S
    i = 0
    P_resampled = Vector{S}(undef, m)
    @inbounds for i in 1:m
        s = rand(rng, b)
        while isterminal(pomdp, s)
            s = rand(rng, b)
        end
        P_resampled[i] = s
    end
    return P_resampled
end


text:
# Misc data type definitions used in the API.

# Definition for a min/max numeric range
struct SoapySDRRange
    minimum::Cdouble
    maximum::Cdouble
    step::Cdouble
end

#Definition for a key/value string map
struct SoapySDRKwargs
    size::Csize_t
    keys::Ptr{Cstring}
    vals::Ptr{Cstring}
end

"""
Convert a markup string to a key-value map.
The markup format is: "key0=value0, key1=value1"
"""
function SoapySDRKwargs_fromString(markup)
    ccall((:SoapySDRKwargs_fromString, lib), SoapySDRKwargs, (Cstring,), markup)
end

"""
Convert a key-value map to a markup string.
The markup format is: "key0=value0, key1=value1"
"""
function SoapySDRKwargs_toString(args)
    ccall((:SoapySDRKwargs_toString, lib), Cstring, (Ptr{SoapySDRKwargs},), args)
end

# Possible data types for argument info
@enum SoapySDRArgInfoType begin
    SOAPY_SDR_ARG_INFO_BOOL
    SOAPY_SDR_ARG_INFO_INT
    SOAPY_SDR_ARG_INFO_FLOAT
    SOAPY_SDR_ARG_INFO_STRING
end

# Definition for argument info
struct SoapySDRArgInfo
    # The key used to identify the argument (required)
    key::Cstring    # key::Ptr{Cchar}

    # The default value of the argument when not specified (required)
    # Numbers should use standard floating point and integer formats.
    # Boolean values should be represented as "true" and  "false".
    value::Cstring

    # The displayable name of the argument (optional, use key if empty)
    name::Cstring

    # A brief description about the argument (optional)
    description::Cstring

    # The units of the argument: dB, Hz, etc (optional)
    units::Cstring

    # The data type of the argument (required)
    type::SoapySDRArgInfoType

    # The range of possible numeric values (optional)
    # When specified, the argument should be restricted to this range.
    # The range is only applicable to numeric argument types.
    range::SoapySDRRange

    # The size of the options set, or 0 when not used.
    numOptions::Csize_t

    # A discrete list of possible values (optional)
    # When specified, the argument should be restricted to this options set.
    options::Ptr{Cstring}

    # A discrete list of displayable names for the enumerated options (optional)
    # When not specified, the option value itself can be used as a display name.
    optionNames::Ptr{Cstring}
end

# Clear the contents of a list of string
# Convenience call to deal with results that return a string list.
function SoapySDRStrings_clear(elems, length)
    ccall((:SoapySDRStrings_clear, lib), Cvoid, (Ptr{Ptr{Cstring}}, Cint), elems, length)
end

"""
Set a key/value pair in a kwargs structure.
If the key exists, the existing entry will be modified;
otherwise a new entry will be appended to args.
On error, the elements of args will not be modified,
and args is guaranteed to be in a good state.
return 0 for success, otherwise allocation error
"""
function SoapySDRKwargs_set(args, key, val)
    ccall((:SoapySDRKwargs_set, lib), Cint, (Ptr{SoapySDRKwargs}, Cstring, Cstring), args, key, val)
end

"""
Get a value given a key in a kwargs structure.
return the string or NULL if not found
"""
function SoapySDRKwargs_get(args, key)
    ccall((:SoapySDRKwargs_get, lib), Cstring, (Ptr{SoapySDRKwargs}, Cstring), args, key)
end

"""
Clear the contents of a kwargs structure.
This frees all the underlying memory and clears the members.
"""
function SoapySDRKwargs_clear(args)
    ccall((:SoapySDRKwargs_clear, lib), Cvoid, (Ptr{SoapySDRKwargs},), args)
end

"""Clear a list of kwargs structures.
This frees all the underlying memory and clears the members."""
function SoapySDRKwargsList_clear(args, length::Integer)
    ccall((:SoapySDRKwargsList_clear, lib), Cvoid, (Ptr{SoapySDRKwargs}, Csize_t), args, length)
end

"""Clear the contents of a argument info structure.
This frees all the underlying memory and clears the members."""
function SoapySDRArgInfo_clear(info)
    ccall((:SoapySDRArgInfo_clear, lib), Cvoid, (Ptr{SoapySDRArgInfo},), info)
end

"""
Clear a list of argument info structures.
This frees all the underlying memory and clears the members."""
function SoapySDRArgInfoList_clear(info, length::Cint)
    ccall((:SoapySDRArgInfoList_clear, lib), Cvoid, (Ptr{SoapySDRArgInfo}, Cint), info, length)
end

function SoapySDR_free(ptr::Ptr)
    ccall((:SoapySDR_free, lib), Cvoid, (Ptr{Cvoid},), ptr)
end


text:
using Documenter
using EllipticalSliceSampling

makedocs(;
    sitename="EllipticalSliceSampling",
    format=Documenter.HTML(),
    modules=[EllipticalSliceSampling],
    pages=["Home" => "index.md"],
    strict=true,
    checkdocs=:exports,
)

deploydocs(;
    repo="github.com/TuringLang/EllipticalSliceSampling.jl.git",
    devbranch="main",
    push_preview=true,
)


text:
# This file is a part of BAT.jl, licensed under the MIT License (MIT).

using BAT
using Compat.Test
using StatsBase

@testset "onlinestats" begin
    n = 10
    data1  = [(-1)^x*exp(x-n/2) for x in 1:n]
    data2 = flipdim(data1, 1)

    w = [exp(x-n/2) for x in 1:n]

    data = vcat(data1', data2')
    m = size(data, 1)

    @testset "BAT.kbn_add" begin
        bg = +1E5
        sm = +1e-4
        res = bg + sm

        bgT = (bg, 0.0)
        smT = (sm, 0.0)

        @test collect(BAT.kbn_add((0.0,0.0),0.0)) ≈ [0.0,0.0]
        @test sum(BAT.kbn_add((0.0,0.0),eps())) ≈ eps()
        @test sum(BAT.kbn_add((bg,0.0),sm)) ≈ res
        @test sum(BAT.kbn_add((sm,0.0),bg)) ≈ res

        @test sum(BAT.kbn_add(bgT,smT)) ≈ res

        @test typeof(@inferred BAT.kbn_add(bgT,sm)) == NTuple{2, Float64}
        @test typeof(@inferred BAT.kbn_add(bgT,smT)) == NTuple{2, Float64}
        @test typeof(@inferred BAT.kbn_add((0.0f0, 0.0f0), 0.0f0)) == NTuple{2, Float32}
        @test typeof(@inferred BAT.kbn_add((0.0f0, 0.0f0), (0.0f0, 0.0f0))) == NTuple{2, Float32}
    end

    @testset "BAT.OnlineMvMean" begin
        @test typeof(@inferred BAT.OnlineMvMean(n)) <: AbstractVector{Float64}
        @test typeof(@inferred BAT.OnlineMvMean{Float32}(n)) <: AbstractVector{Float32}

        mvmean = BAT.OnlineMvMean(m)
        @test size(mvmean, 1) == m

        countM = 3
        mvmeans = Array{BAT.OnlineMvMean{Float64}}(countM)

        for i in indices(mvmeans, 1)
            mvmeans[i] = BAT.OnlineMvMean(m)
        end

        for i in indices(data, 2)
            push!(mvmean, data[:, i], w[i]);
            push!(mvmeans[(i % countM) + 1], data[:, i], w[i]);
        end

        @test mvmean ≈ mean(data, Weights(w), 2)

        res = merge(mvmeans...)
        @test res ≈ mean(data, Weights(w), 2)

        mvmean = BAT.OnlineMvMean(m)
        res = append!(deepcopy(mvmean), data, 2)
        @test res ≈ mean(data, 2)
        res = append!(deepcopy(mvmean), data, w, 2)
        @test res ≈ mean(data, Weights(w), 2)
    end

    @testset "BAT.OnlineMvCov" begin
        @test typeof(@inferred BAT.OnlineMvCov(n)) <: AbstractMatrix{Float64}
        @test typeof(@inferred BAT.OnlineMvCov{Float32, ProbabilityWeights}(n)) <: AbstractMatrix{Float32}

        for wKind in [ProbabilityWeights, FrequencyWeights, AnalyticWeights, Weights]
            mvcov = BAT.OnlineMvCov{Float64, wKind}(m)
            for i in indices(data, 2)
                push!(mvcov, data[:, i], w[i]);
            end

            @test mvcov ≈ cov(data, wKind(w), 2; corrected = (wKind != Weights))
        end

        countMvCovs = 3
        mvcovs = Array{BAT.OnlineMvCov{Float64, ProbabilityWeights}}(countMvCovs)
        for i in indices(mvcovs,1)
            mvcovs[i] = BAT.OnlineMvCov(m)
        end
        mvcovc = BAT.OnlineMvCov(m)

        for i in indices(data, 2)
            push!(mvcovs[(i % countMvCovs) + 1], data[:, i], w[i]);
            push!(mvcovc, data[:, i], w[i]);
        end

        res = merge(mvcovs...)
        @test res ≈ cov(data, ProbabilityWeights(w), 2; corrected = true)
        @test res ≈ mvcovc
        @test res.sum_w ≈ mvcovc.sum_w
        @test res.sum_w2 ≈ mvcovc.sum_w2
        @test res.n ≈ mvcovc.n
        @test res.Mean_X ≈ mvcovc.Mean_X
        @test res.New_Mean_X ≈ mvcovc.New_Mean_X
        @test push!(res, data[:, 1], zero(Float64)) ≈ mvcovc

        mvcov = BAT.OnlineMvCov(m)
        res = append!(deepcopy(mvcov), data, 2)
        @test res ≈ cov(data, 2)
        res = append!(deepcopy(mvcov), data, w, 2)
        @test res ≈ cov(data, ProbabilityWeights(w), 2; corrected = true)

    end
    @testset "BAT.BasicMvStatistic" begin
        bmvstats = BasicMvStatistics{Float64, ProbabilityWeights}(m)

        countBMS = 3
        bmvs = Array{BAT.BasicMvStatistics{Float64, ProbabilityWeights}}(countBMS)
        for i in indices(bmvs,1)
            bmvs[i] = BasicMvStatistics{Float64, ProbabilityWeights}(m)
        end

        for i in indices(data, 2)
            BAT.push!(bmvstats, data[:, i], w[i]);
            BAT.push!(bmvs[(i % countBMS) + 1], data[:, i], w[i]);
        end

        merbmvstats = merge(bmvs...)

        maxData =  [maximum(data[i, :]) for i in indices(data, 1)]
        minData =  [minimum(data[i, :]) for i in indices(data, 1)]

        for bs in [bmvstats, merbmvstats]
            @test bs.mean ≈  mean(data, Weights(w), 2)
            @test bs.cov ≈ cov(data, ProbabilityWeights(w), 2; corrected = true)
            @test bs.maximum ≈ maxData
            @test bs.minimum ≈ minData
        end

        mvstat = BasicMvStatistics{Float64, ProbabilityWeights}(m)
        res = append!(deepcopy(mvstat), data, 2)
        @test res.mean ≈ mean(data, 2)
        @test res.cov ≈ cov(data, 2)
        @test res.maximum ≈ maxData
        @test res.minimum ≈ minData

        res = append!(deepcopy(mvstat), data, w, 2)
        @test res.mean ≈ mean(data, weights(w), 2)
        @test res.cov ≈ cov(data, ProbabilityWeights(w), 2; corrected = true)
        @test res.maximum ≈ maxData
        @test res.minimum ≈ minData

        @test_throws ArgumentError append!(mvstat, data, w, 1)
        @test_throws ArgumentError append!(mvstat, data, w, 3)
        @test_throws ArgumentError append!(mvstat, data, 1)
        @test_throws ArgumentError append!(mvstat, data, 3)
    end

end


text:
@ms include("solvers/descent.jl")

function main_descent(args)
    # Résolution de l'action
    println("="^70)
    println("Début de la méthode de descente")
    inst = Instance(args[:infile])
    sol = Solution(inst)

    initial_sort!(sol)

    sv = DescentSolver(inst)

    duration = 15*60 # secondes
    itermax = Args.get(:itermax)

    ms_start = ms()
    solve(sv, swap_close_planes!, durationmax=duration,
          startsol=sol)
    ms_stop = ms()

    bestsol = sv.bestsol
    write(bestsol)
    print_sol(bestsol)

    nb_calls = bestsol.solver.nb_calls
    nb_infeasable = bestsol.solver.nb_infeasable
    nb_sec = round(ms_stop - ms_start, digits=3)
    nb_call_per_sec = round(nb_calls/nb_sec, digits=3)
    println("Performance: ")
    println("  nb_calls=$nb_calls")
    println("  nb_infeasable=$nb_infeasable")
    println("  nb_sec=$nb_sec")
    println("  => nb_call_per_sec = $nb_call_per_sec call/sec")
end

main_descent(Args.args)


text:
function visualizeCells(phi::CellValue; vmin::Real =0.0, vmax::Real = 0.0, cmap="viridis", shading = "gouraud")
d=phi.domain.dimension
if d==1 || d==1.5
  x = [phi.domain.facecenters.x[1]; phi.domain.cellcenters.x; phi.domain.facecenters.x[end]]
  phi = [0.5*(phi.value[1]+phi.value[2]); phi.value[2:end-1]; 0.5*(phi.value[end-1]+phi.value[end])]
  plot(x, phi)
elseif d==2 || d==2.5
  x = [phi.domain.facecenters.x[1]; phi.domain.cellcenters.x; phi.domain.facecenters.x[end]]
  y = [phi.domain.facecenters.y[1]; phi.domain.cellcenters.y; phi.domain.facecenters.y[end]]
  phi0 = Base.copy(phi.value)
  phi0[:,1] = 0.5*(phi0[:,1]+phi0[:,2])
  phi0[1,:] = 0.5*(phi0[1,:]+phi0[2,:])
  phi0[:,end] = 0.5*(phi0[:,end]+phi0[:,end-1])
  phi0[end,:] = 0.5*(phi0[end,:]+phi0[end-1,:])
  phi0[1,1] = phi0[1,2]
  phi0[1,end] = phi0[1,end-1]
  phi0[end,1] = phi0[end,2]
  phi0[end,end] = phi0[end,end-1]
  if vmin == 0.0 && vmax == 0.0
      vmin = minimum(phi0)
      vmax = maximum(phi0)
  end
  pcolormesh(x, y, phi0', vmin = vmin, vmax = vmax, cmap = cmap, shading = shading)
elseif d==2.8
  x = [phi.domain.facecenters.x[1]; phi.domain.cellcenters.x; phi.domain.facecenters.x[end]]
  y = [phi.domain.facecenters.y[1]; phi.domain.cellcenters.y; phi.domain.facecenters.y[end]]
  phi0 = Base.copy(phi.value)
  phi0[:,1] = 0.5*(phi0[:,1]+phi0[:,2])
  phi0[1,:] = 0.5*(phi0[1,:]+phi0[2,:])
  phi0[:,end] = 0.5*(phi0[:,end]+phi0[:,end-1])
  phi0[end,:] = 0.5*(phi0[end,:]+phi0[end-1,:])
  phi0[1,1] = phi0[1,2]
  phi0[1,end] = phi0[1,end-1]
  phi0[end,1] = phi0[end,2]
  phi0[end,end] = phi0[end,end-1]
  subplot(111, polar="true")
  pcolor(y, x, phi0)
elseif d==3
    Nx = phi.domain.dims[1]
    Ny = phi.domain.dims[2]
    Nz = phi.domain.dims[3]
    x=[phi.domain.facecenters.x[1]; phi.domain.cellcenters.x; phi.domain.facecenters.x[end]]
    y=zeros(1,Ny+2)
    y[:]=[phi.domain.facecenters.y[1]; phi.domain.cellcenters.y; phi.domain.facecenters.y[end]]
    z=zeros(1,1,Nz+2)
    z[:]=[phi.domain.facecenters.z[1]; phi.domain.cellcenters.z; phi.domain.facecenters.z[end]]

    phi0 = Base.copy(phi.value)
    phi0[:,1,:]=0.5*(phi0[:,1,:]+phi0[:,2,:])
    phi0[:,end,:]=0.5*(phi0[:,end-1,:]+phi0[:,end,:])
    phi0[:,:,1]=0.5*(phi0[:,:,1]+phi0[:,:,1])
    phi0[:,:,end]=0.5*(phi0[:,:,end-1]+phi0[:,:,end])
    phi0[1,:,:]=0.5*(phi0[1,:,:]+phi0[2,:,:])
    phi0[end,:,:]=0.5*(phi0[end-1,:,:]+phi0[end,:,:])

    vmin = minimum(phi0)
    vmax = maximum(phi0)
    mynormalize = a -> (a .- vmin)./(vmax-vmin)

    a=ones(Nx+2,Ny+2,Nz+2)
    X = x.*a
    Y = y.*a
    Z = z.*a

    fig = figure()
    ax = fig[:add_subplot](111, projection = "3d")
    # r = linspace(1.25, 1.25, 50)
    # p = linspace(0, 2π, 50)
    # R = repmat(r, 1, 50)
    # P = repmat(p', 50, 1)
    # Zc = rand(50, 50) # (P.^2-1).^2
    # Z = repmat(linspace(0, 2, 50), 1, 50)
    # X, Y = R.*cos.(P), R.*sin.(P)
    ax[:plot_surface](X[1,:,:], Y[1,:,:], Z[1,:,:], facecolors=PyPlot.cm[:viridis](mynormalize(phi0[1,:,:])), alpha=0.8)
    ax[:plot_surface](X[end,:,:], Y[end,:,:], Z[end,:,:], facecolors=PyPlot.cm[:viridis](mynormalize(phi0[end,:,:])), alpha=0.8)
    ax[:plot_surface](X[:,1,:], Y[:,1,:], Z[:,1,:], facecolors=PyPlot.cm[:viridis](mynormalize(phi0[:,1,:])), alpha=0.8)
    ax[:plot_surface](X[:,end,:], Y[:,end,:], Z[:,end,:], facecolors=PyPlot.cm[:viridis](mynormalize(phi0[:,end,:])), alpha=0.8)
    ax[:plot_surface](X[:,:,1], Y[:,:,1], Z[:,:,1], facecolors=PyPlot.cm[:viridis](mynormalize(phi0[:,:,1])), alpha=0.8)
    ax[:plot_surface](X[:,:,end], Y[:,:,end], Z[:,:,end], facecolors=PyPlot.cm[:viridis](mynormalize(phi0[:,:,end])), alpha=0.8)
  # s=mayavis.pipeline[:scalar_field](X,Y,Z,phi0)
  #
  # mayavis.pipeline[:image_plane_widget](s, plane_orientation="x_axes", slice_index=0, vmin=vmin, vmax=vmax)
  # mayavis.pipeline[:image_plane_widget](s, plane_orientation="y_axes", slice_index=0, vmin=vmin, vmax=vmax)
  # mayavis.pipeline[:image_plane_widget](s, plane_orientation="z_axes", slice_index=0, vmin=vmin, vmax=vmax)
  # mayavis.pipeline[:image_plane_widget](s, plane_orientation="z_axes", slice_index=floor(Integer,Nz/2.0), vmin=vmin, vmax=vmax)
  # mayavis.outline()

#   # 6 surfaces
#   # surfaces 1,2 (x=x[1], x=x[end])
#   Y=repmat(y,1,Nz)
#   Z=repmat(z,1,Ny)
#   mayavis.mesh(x[1]*ones(Ny,Nz),Y,Z',scalars=squeeze(phi.value[2,2:end-1,2:end-1],1), vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.mesh(x[end]*ones(Ny,Nz),Y,Z',scalars=squeeze(phi.value[end-1,2:end-1,2:end-1],1), vmin=vmin, vmax=vmax, opacity=0.8)
#
#   # surfaces 3,4 (y=y[1], y=y[end]
#   X = repmat(x,1,Nz)
#   Z = repmat(z,1,Nx)
#   mayavis.mesh(X,y[1]*ones(Nx,Nz),Z',scalars=squeeze(phi.value[2:end-1,2,2:end-1],2), vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.mesh(X,y[end]*ones(Nx,Nz),Z',scalars=squeeze(phi.value[2:end-1,end-1,2:end-1],2), vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.axes()
#
#   # surfaces 5,6 (z=z[1], z=z[end]
#   X = repmat(x,1,Ny)
#   Y = repmat(y,1,Nx)
#   mayavis.mesh(X,Y',z[1]*ones(Nx,Ny),scalars=phi.value[2:end-1,2:end-1,2], vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.mesh(X,Y',z[end]*ones(Nx,Ny),scalars=phi.value[2:end-1,2:end-1,end-1], vmin=vmin, vmax=vmax, opacity=0.8)

  # mayavis.colorbar()
  # mayavis.axes()
  # mshot= mayavis.screenshot()
  # mayavis.show()
  # return mshot

elseif d==3.2
  Nx = phi.domain.dims[1]
  Ny = phi.domain.dims[2]
  Nz = phi.domain.dims[3]
  r=[phi.domain.facecenters.x[1]; phi.domain.cellcenters.x; phi.domain.facecenters.x[end]]
  theta = zeros(1,Ny+2)
  theta[:]=[phi.domain.facecenters.y[1]; phi.domain.cellcenters.y; phi.domain.facecenters.y[end]]
  z=zeros(1,1,Nz+2)
  z[:]=[phi.domain.facecenters.z[1]; phi.domain.cellcenters.z; phi.domain.facecenters.z[end]]
  a=ones(Nx+2,Ny+2,Nz+2)
  R=r.*a
  TH = theta.*a
  Z = z.*a

  X=R.*cos(TH)
  Y=R.*sin(TH)

  phi0 = Base.copy(phi.value)
  phi0[:,1,:]=0.5*(phi0[:,1,:]+phi0[:,2,:])
  phi0[:,end,:]=0.5*(phi0[:,end-1,:]+phi0[:,end,:])
  phi0[:,:,1]=0.5*(phi0[:,:,1]+phi0[:,:,1])
  phi0[:,:,end]=0.5*(phi0[:,:,end-1]+phi0[:,:,end])
  phi0[1,:,:]=0.5*(phi0[1,:,:]+phi0[2,:,:])
  phi0[end,:,:]=0.5*(phi0[end-1,:,:]+phi0[end,:,:])

  vmin = minimum(phi0)
  vmax = maximum(phi0)
  # 6 surfaces
  # surfaces 1,2 (x=x[1], x=x[end])
  mayavis.mesh(squeeze(X[floor(Integer,Nx/2.0),:,:],1),squeeze(Y[floor(Integer,Nx/2.0),:,:],1),squeeze(Z[floor(Integer,Nx/2.0),:,:],1),
    scalars=squeeze(phi0[floor(Integer,Nx/2.0)+1,:,:],1), vmin=vmin, vmax=vmax, opacity=0.8)
  mayavis.mesh(squeeze(X[Nx,:,:],1),squeeze(Y[Nx,:,:],1),squeeze(Z[Nx,:,:],1),
    scalars=squeeze(phi0[Nx+2,:,:],1), vmin=vmin, vmax=vmax, opacity=0.8)

  # surfaces 3,4 (y=y[1], y=y[end]
  mayavis.mesh(squeeze(X[:,floor(Integer,Ny/2.0),:],2),squeeze(Y[:,floor(Integer,Ny/2.0),:],2),squeeze(Z[:,floor(Integer,Ny/2.0),:],2),
    scalars=squeeze(phi0[:,floor(Integer,Ny/2.0)+1,:],2), vmin=vmin, vmax=vmax, opacity=0.8)
  mayavis.mesh(squeeze(X[:,Ny,:],2),squeeze(Y[:,Ny,:],2),squeeze(Z[:,Ny,:],2),
    scalars=squeeze(phi0[:,Ny+2,:],2), vmin=vmin, vmax=vmax, opacity=0.8)

  # surfaces 5,6 (z=z[1], z=z[end]
  mayavis.mesh(X[:,:,floor(Integer,Nz/2.0)],Y[:,:,floor(Integer,Nz/2.0)],Z[:,:,floor(Integer,Nz/2.0)],
    scalars=phi0[:,:,floor(Integer,Nz/2.0)+1], vmin=vmin, vmax=vmax, opacity=0.8)
  mayavis.mesh(X[:,:,Nz],Y[:,:,Nz],Z[:,:,Nz],
    scalars=phi0[:,:,Nz+1], vmin=vmin, vmax=vmax, opacity=0.8)
  mayavis.colorbar()
  mayavis.axes()
  mshot=mayavis.screenshot()
  mayavis.show()
  return mshot
end
end

########################## Visualize Vectors #####################
function visualizeCellVectors(phi::CellVector)
d=phi.domain.dimension
if d==1 || d==1.5
  println("Vector visualization works only in 2D and 3D")
elseif d==2 || d==2.5
  x = phi.domain.cellcenters.x
  y = phi.domain.cellcenters.y
  quiver(repeat(x, 1, length(y)), repeat(y', length(x), 1), phi.xvalue, phi.yvalue)
elseif d==2.8
  x = phi.domain.cellcenters.x
  y = phi.domain.cellcenters.y'
  subplot(111, polar="true")
  quiver(repeat(y, length(x), 1), repeat(x, 1, length(y)),
  phi.xvalue.*cos(y)-phi.yvalue.*sin(y), phi.xvalue.*sin(y)+phi.yvalue.*cos(y))
elseif d==3
  Nx = phi.domain.dims[1]
  Ny = phi.domain.dims[2]
  Nz = phi.domain.dims[3]
  x=phi.domain.cellcenters.x
  y=zeros(1,Ny)
  y[:]=phi.domain.cellcenters.y
  z=zeros(1,1,Nz)
  z[:]=phi.domain.cellcenters.z

  #vmin = minimum(phi.xvalue)
  #vmax = maximum(phi0)

  a=ones(Nx,Ny,Nz)
  X = x.*a
  Y = y.*a
  Z = z.*a

  mayavis.quiver3d(X,Y,Z, phi.xvalue, phi.yvalue, phi.zvalue)
  mayavis.outline()

#   # 6 surfaces
#   # surfaces 1,2 (x=x[1], x=x[end])
#   Y=repmat(y,1,Nz)
#   Z=repmat(z,1,Ny)
#   mayavis.mesh(x[1]*ones(Ny,Nz),Y,Z',scalars=squeeze(phi.value[2,2:end-1,2:end-1],1), vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.mesh(x[end]*ones(Ny,Nz),Y,Z',scalars=squeeze(phi.value[end-1,2:end-1,2:end-1],1), vmin=vmin, vmax=vmax, opacity=0.8)
#
#   # surfaces 3,4 (y=y[1], y=y[end]
#   X = repmat(x,1,Nz)
#   Z = repmat(z,1,Nx)
#   mayavis.mesh(X,y[1]*ones(Nx,Nz),Z',scalars=squeeze(phi.value[2:end-1,2,2:end-1],2), vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.mesh(X,y[end]*ones(Nx,Nz),Z',scalars=squeeze(phi.value[2:end-1,end-1,2:end-1],2), vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.axes()
#
#   # surfaces 5,6 (z=z[1], z=z[end]
#   X = repmat(x,1,Ny)
#   Y = repmat(y,1,Nx)
#   mayavis.mesh(X,Y',z[1]*ones(Nx,Ny),scalars=phi.value[2:end-1,2:end-1,2], vmin=vmin, vmax=vmax, opacity=0.8)
#   mayavis.mesh(X,Y',z[end]*ones(Nx,Ny),scalars=phi.value[2:end-1,2:end-1,end-1], vmin=vmin, vmax=vmax, opacity=0.8)

  mayavis.colorbar()
  mayavis.axes()
  mshot= mayavis.screenshot()
  mayavis.show()
  return mshot

elseif d==3.2
  Nx = phi.domain.dims[1]
  Ny = phi.domain.dims[2]
  Nz = phi.domain.dims[3]
  r=phi.domain.cellcenters.x
  theta = zeros(1,Ny)
  theta[:]=phi.domain.cellcenters.y
  z=zeros(1,1,Nz)
  z[:]=phi.domain.cellcenters.z
  a=ones(Nx,Ny,Nz)
  R=r.*a
  TH = theta.*a
  Z = z.*a

  X=R.*cos(TH)
  Y=R.*sin(TH)

  #vmin = minimum(phi0)
  #vmax = maximum(phi0)
  # 6 surfaces
  # surfaces 1,2 (x=x[1], x=x[end])
  mayavis.quiver3d(X,Y,Z, phi.xvalue.*cos(TH)-phi.yvalue.*sin(TH),
  phi.xvalue.*sin(TH)+phi.yvalue.*cos(TH), phi.zvalue)
  mayavis.colorbar()
  mayavis.axes()
  mshot=mayavis.screenshot()
  mayavis.show()
  return mshot
end
end


text:
## wrappers for JuMP

function register_forward_model!(n_t_segs,model;
    diffusion_func=rdaam_forward_diffusion,ancillary_func=fill_u_term)
  n_T_segs = n_t_segs-1
  forward_model = Symbol(diffusion_func)
  helper_func = Symbol(ancillary_func)
  register(model,forward_model,22+n_T_segs+n_t_segs,diffusion_func,autodiff=true)
  register(model,helper_func,10,ancillary_func,autodiff=true)

  return true
end

function register_objective_function!(n_T_segs,model;model_constraints=mod_constraints,autodiff=true)
  model_constraints_sym = Symbol(model_constraints)
  register(model,model_constraints_sym,n_T_segs,model_constraints,autodiff=autodiff)

  return nothing
end

function set_objective_function!(model,T)

@NLobjective(model,Min,mod_constraints(T...))
return nothing

end


text:
using Documenter, Lasso, MLBase

makedocs(
    modules = [Lasso],
    format = Documenter.HTML(
        # Use clean URLs, unless built as a "local" build
        prettyurls = !("local" in ARGS),
        canonical = "https://juliastats.github.io/Lasso.jl/stable/",
    ),
    clean = false,
    sitename = "Lasso.jl",
    authors = "Simon Kornblith, Asaf Manela, and contributors.",
    linkcheck = !("skiplinks" in ARGS),
    pages = [
        "Home" => "index.md",
        "Lasso paths" => "lasso.md",
        "Fused Lasso and trend filtering" => "smoothing.md",
        "Index" => "api.md",
    ],
    )

deploydocs(
    repo = "github.com/JuliaStats/Lasso.jl.git",
    target = "build",
)


text:
Δ(x) = x[2]-x[1]

function find_where(A)
    I = findall(!iszero,A)
    v = A[I]
    ix = [I[i][1] for i in eachindex(I)]
    iy = [I[i][2] for i in eachindex(I)]
    return ix,iy,v
end

function found_near(n)
    near = true
    for j in 1:n
        psi,vort = rand_vortexfield(1)
        vortfound = findvortices(psi)
        vfdata = vortex_array(vortfound)
        vdata = vortex_array(vort)
        dx = Δ(psi.x)
        near *= isapprox(vdata,vfdata,rtol = dx/4)
    end
    return near
end

"""
    vortices = remove_vortices_edge(vort::Array{PointVortex,1},x,y,edge=1)

Strip artifact edgevortices arising from periodic phase differencing.
"""
function remove_vortices_edge(vort::Array{PointVortex,1},psi::Field,edge=1)
    @unpack x,y = psi; dx,dy=Δ(x),Δ(y)
    keep = []
    for j = 1:length(vort)
        xi,yi,qi = vortex_array(vort[j])
        xedge = isapprox(xi,x[1],atol=edge*dx) || isapprox(xi,x[end],atol=edge*dx)
        yedge = isapprox(yi,y[1],atol=edge*dy) || isapprox(yi,y[end],atol=edge*dy)
        not_edge = !(xedge || yedge)
        not_edge && push!(keep,j)
    end
    return vort[keep]
end

## phase jumps, unwrap

"""
    jumps = phase_jumps(ϕ,dim)

Count phase jumps greater than `π` in phase `ϕ` along dimension `dim`.
See also: [`unwrap`](@ref), [`unwrap`](@ref), [`unwrap!`](@ref)
"""
function phase_jumps(phase,dim=1)
    @assert (dim==1 || dim==2)
    s1,s2 = size(phase)
    pdiff = zero(phase)

    if dim == 1
    for j in 1:s2
        @inbounds dϕ = phase[1,j] - phase[s1,j]
        @inbounds abs(dϕ) > π && (pdiff[1,j] += sign(dϕ))
        for i in 2:s1
            @inbounds dϕ = phase[i,j] - phase[i-1,j]
            @inbounds abs(dϕ) > π && (pdiff[i,j] += sign(dϕ))
        end

    end

    elseif dim == 2
    for j in 2:s2
        for i in 1:s1
            j==2 && (@inbounds dϕ = phase[i,1] - phase[i,s2];
            @inbounds abs(dϕ) > π && (pdiff[i,1] += sign(dϕ)))
            @inbounds dϕ = phase[i,j] - phase[i,j-1]
            @inbounds abs(dϕ) > π && (pdiff[i,j] += sign(dϕ))
        end
    end
    end
  return pdiff
end

function phase_jumps!(pdiff,phase,dim=1)
    @assert (dim==1 || dim==2)
    s1,s2 = size(phase)

    if dim == 1
    for j in 1:s2
        @inbounds dϕ = phase[1,j] - phase[s1,j]
        @inbounds abs(dϕ) > π && (pdiff[1,j] += sign(dϕ))
        for i in 2:s1
            @inbounds dϕ = phase[i,j] - phase[i-1,j]
            @inbounds abs(dϕ) > π && (pdiff[i,j] += sign(dϕ))
        end

    end

    elseif dim == 2
    for j in 2:s2
        for i in 1:s1
            j==2 && (@inbounds dϕ = phase[i,1] - phase[i,s2];
            @inbounds abs(dϕ) > π && (pdiff[i,1] += sign(dϕ)))
            @inbounds dϕ = phase[i,j] - phase[i,j-1]
            @inbounds abs(dϕ) > π && (pdiff[i,j] += sign(dϕ))
        end
    end
    end
end

"""
    ϕu = unwrap(ϕ,dim=1)

Unwraps 2d array `ϕ` along dimension `dim`, acting periodically to give back array of same size as `ϕ`.
See also: [`unwrap!`](@ref)
"""
function unwrap(phase::Array{Float64,2},dim=1)
    @assert (dim==1 || dim==2)
    s1,s2 = size(phase)
    uphase = copy(phase)

    if dim == 1
    for j in 1:s2
        @inbounds (k=uphase[1,j] - uphase[s1,j];k > π) && (uphase[1,j] -= 2π*div(k,2pi,RoundNearest))
        @inbounds (k=uphase[1,j] - uphase[s1,j];k < -π) && (uphase[1,j] += 2π*div(-k,2pi,RoundNearest))
        for i in 2:s1
        @inbounds (k=uphase[i,j] - uphase[i-1,j];k > π) && (uphase[i,j] -= 2π*div(k,2pi,RoundNearest))
        @inbounds (k=uphase[i,j] - uphase[i-1,j];k < -π) && (uphase[i,j] += 2π*div(-k,2pi,RoundNearest))
        end
    end

    elseif dim == 2
        for j in 2:s2
        for i in 1:s1
            j==2 && (@inbounds (k= uphase[i,1] - uphase[i,s2]; k > π) && (uphase[i,1] -= 2π*div(k,2pi,RoundNearest));
            @inbounds (k=uphase[i,1] - uphase[i,s2];k < -π) && (uphase[i,1] += 2π*div(-k,2pi,RoundNearest)))
            @inbounds (k=uphase[i,j] - uphase[i,j-1];k > π) && (uphase[i,j] -= 2π*div(k,2pi,RoundNearest))
            @inbounds (k=uphase[i,j] - uphase[i,j-1];k < -π) && (uphase[i,j] += 2π*div(-k,2pi,RoundNearest))
        end
    end
end

    return uphase
end

"""
    unwrap!(ϕu,ϕ,dim)

Unwraps 2d phase array `ϕ` along dimension `dim`,
acting periodically and writing the unwrapped array `ϕ`
in place.
See also: [`unwrap`](@ref)
"""
function unwrap!(uphase::Array{Float64,2},phase::Array{Float64,2},dim=1)
    @assert (dim==1 || dim==2)
    s1,s2 = size(phase)
    uphase .= phase

    if dim == 1
        for j in 1:s2
            @inbounds (k=uphase[1,j] - uphase[s1,j];k > π) && (uphase[1,j] -= 2π*div(k,2pi,RoundNearest))
            @inbounds (k=uphase[1,j] - uphase[s1,j];k < -π) && (uphase[1,j] += 2π*div(-k,2pi,RoundNearest))
            for i in 2:s1
            @inbounds (k=uphase[i,j] - uphase[i-1,j];k > π) && (uphase[i,j] -= 2π*div(k,2pi,RoundNearest))
            @inbounds (k=uphase[i,j] - uphase[i-1,j];k < -π) && (uphase[i,j] += 2π*div(-k,2pi,RoundNearest))
            end
        end

        elseif dim == 2

        for j in 2:s2
            for i in 1:s1
                j==2 && (@inbounds (k= uphase[i,1] - uphase[i,s2]; k > π) && (uphase[i,1] -= 2π*div(k,2pi,RoundNearest));
                @inbounds (k=uphase[i,1] - uphase[i,s2];k < -π) && (uphase[i,1] += 2π*div(-k,2pi,RoundNearest)))
                @inbounds (k=uphase[i,j] - uphase[i,j-1];k > π) && (uphase[i,j] -= 2π*div(k,2pi,RoundNearest))
                @inbounds (k=uphase[i,j] - uphase[i,j-1];k < -π) && (uphase[i,j] += 2π*div(-k,2pi,RoundNearest))
            end
        end
    end
end

function unwrap(phase::Array{Float64,1})
    uphase = copy(phase)
    s1 = length(phase)
        @inbounds (k=uphase[1] - uphase[s1];k > π) && (uphase[1] -= 2π*div(k,2pi,RoundNearest))
        @inbounds (k=uphase[1] - uphase[s1];k < -π) && (uphase[1] += 2π*div(-k,2pi,RoundNearest))
        for i in 2:s1
        @inbounds (k=uphase[i] - uphase[i-1];k > π) && (uphase[i] -= 2π*div(k,2pi,RoundNearest))
        @inbounds (k=uphase[i] - uphase[i-1];k < -π) && (uphase[i] += 2π*div(-k,2pi,RoundNearest))
        end

        return uphase
end

function unwrap!(uphase::Array{Float64,1},phase::Array{Float64,1})
    uphase .= phase
    s1 = length(phase)
    @inbounds (k=uphase[1] - uphase[s1];k > π) && (uphase[1] -= 2π*div(k,2pi,RoundNearest))
    @inbounds (k=uphase[1] - uphase[s1];k < -π) && (uphase[1] += 2π*div(-k,2pi,RoundNearest))
    for i in 2:s1
    @inbounds (k=uphase[i] - uphase[i-1];k > π) && (uphase[i] -= 2π*div(k,2pi,RoundNearest))
    @inbounds (k=uphase[i] - uphase[i-1];k < -π) && (uphase[i] += 2π*div(-k,2pi,RoundNearest))
    end
end

function distances(x,y)
    xij = @. x - x'
    yij = @. y - y'
    return xij,yij
end

function periodic_distances!(x,y,Lx,Ly)
    make_periodic!(x,Lx)
    make_periodic!(y,Ly)
end

function make_periodic!(x,L)
    @. x[x>L/2]  -= L
    @. x[x<-L/2] += L
end

"""
    rij = sparse_distances(x,y)

Sparse form of unique lower triangular distance matrix for vectors `x`, `y` specifying points on the plane.
"""
function sparse_distances(x,y)
    xij = @. x - x'
    yij = @. y - y'
    rij = hypot.(xij,yij) |> tril |> sparse
end

"""
    tree = spanning_tree(x,y)

Minimal spanning tree for points specified by vectors `x`, `y`.
"""
function spanning_tree(x,y)
    rij = sparse_distances(x,y)
    # graph representation
    g = SimpleWeightedGraph(length(rij))
    for edge in eachindex(rij)
        n1,n2 = edge[1],edge[2]
        add_edge!(g,n1,n2,rij[n1,n2])
    end
    # get the spanning tree
    tree = prim_mst(g)
end

"""
    vortex_marker(c)

Define vortex marker using sign.
"""
function vortex_marker(c)
    if c==1.0
        return (4,0.6,:green, stroke(1.3, 1.0, :white))
    elseif c==-1.0
        return (4,0.6,:blue, stroke(1.3, 1.0, :white))
    else
    end
end

# """
#     plot_vortices!(p,vdata)

# Plot vortices defined in `vdata` on figure `p`.
# """
# function plot_vortices!(p,vdata)
#     for j in 1:size(vdata)[1]
#         vx,vy = vdata[j,1],vdata[j,2]
#         scatter!(p1,[vx],[vy],marker=vortex_marker(vdata[j,3]),label=false)
#     end
#     return p1
# end

# """
#     plot_cluster_vortices!(p,cluster::Cluster)

# Plot cluster in figure `p` using `vortex_marker`.
# """
# function plot_cluster_vortices!(p,cluster::Cluster)
#     vdata = vortex_array(cluster.vortices)
#     for j in 1:size(vdata)[1]
#         vx,vy = vdata[j,1],vdata[j,2]
#         scatter!(p,[vx],[vy],marker=vortex_marker(vdata[j,3]),label=false)
#     end
#     return p
# end

# """
#     plot_cluster_tree!(p,cluster::Cluster)

# Plot minimal spanning tree on figure `p` for `cluster`.
# """
# function plot_cluster_tree!(p,cluster::Cluster)
#     vortices = cluster.vortices
#     tree = cluster.tree
#     va = vortex_array(vortices)
#     xi = @view va[:,1]
#     yi = @view va[:,2]
#     ci = @view va[:,3]

#     for i in 1:length(tree)
#         edge = tree[i]
#         src,dst = edge.src,edge.dst
#         x1,y1 = xi[src],yi[src]
#         x2,y2 = xi[dst],yi[dst]
#         csign = vortices[1].qv
#         col = csign == 1.0 ? :green : :blue
#         plot!(p,[x1,x2],[y1,y2],label=false,c=col,alpha=0.4)
#     end
#     return p
# end

# """
#     plot_custer!(p,c)

# Plot the vortices and minimal spanning tree.
# """
# function plot_cluster!(p,c)
#     plot_cluster_vortices!(p,c)
#     plot_cluster_tree!(p,c)
#     return p
# end


text:
module Bibliographies

using Dates: Month, Year

using BibTeXFormat: Person, Bibliography
using DataFrames: DataFrame
using Parameters: @with_kw

import BibTeXFormat

export BibliographyEntry, Article
export all_fields, ignored_fields, expand, make_table

abstract type BibliographyEntry end

@with_kw struct Article <: BibliographyEntry
    author::Person
    journal::String
    title::String
    year::Year
    month::Month = Month(-1)
    note::String = ""
    number::Int = -1
    pages::NTuple{2,Int} = (-1, -1)
    volume::Int = -1
end
Article(author, journal, title, year) =
    Article(author = author, journal = journal, title = title, year = year)

@with_kw struct Book <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct Booklet <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct Conference <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct InBook <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct InCollection <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct InProceedings <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct Manual <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct MastersThesis <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct Misc <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct PhdThesis <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct Proceedings <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct TechReport <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

@with_kw struct Unpublished <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

struct GeneralBibliographyEntry <: BibliographyEntry
    address::String
    annote::String
    author::Person
    booktitle::String
    chapter::Int
    crossref::Int
    doi::String
    edition::VersionNumber
    editor::Person
    howpublished::Symbol
    institution::String
    journal::String
    key::String
    month::Month
    note::String
    number::Int
    organization::String
    pages::NTuple{2,Int}
    publisher::String
    school::String
    series::Int
    title::String
    type::Symbol
    volume::Int
    year::Year
end

function all_fields()
    return fieldnames(GeneralBibliographyEntry)
end # function all_fields

function ignored_fields(T::Type{<:BibliographyEntry})
    return setdiff(all_fields(), fieldnames(T))
end # function ignored_fields

function expand(d::AbstractDict{Symbol})
    default = Dict{Symbol,String}(zip(all_fields(), ["" for _ in 1:length(all_fields())]))
    for k in keys(default)
        default[k] = get(d, k, "")
    end
    return default
end # function expand
expand(d::AbstractDict{<:AbstractString}) = expand(Dict(Symbol(k) => v for (k, v) in d))

function make_table(str::String)
    bib = Bibliography(str)
    citations = map(values, values(bib.citations))
    df = DataFrame()
    for citation in citations
        append!(df, expand(citation.data) |> DataFrame)
    end
    return df
end # function make_table

end # module


text:
## Implementation of MathProgBase interface for non-linear optimisation
## ====================================================================

import MathProgBase.SolverInterface: AbstractMathProgSolver, AbstractMathProgModel,
  getsense, numvar, numconstr, getobjval, getobjbound, getsolution, getsolvetime,
  setwarmstart!, loadproblem!, optimize!, AbstractNLPEvaluator, status,
  obj_expr

## Solver Objects
## =============
export DRealSolver

immutable DRealSolver <: AbstractMathProgSolver
  precision::Float64
end

DRealSolver(;precision::Float64 = DEFAULT_PRECISION) = DRealSolver(precision)

type DRealMathProgModel <: AbstractMathProgModel
  ctx::Context
  status::Symbol
  numvar::Int
  vars::Vector{Ex}
  cost_var::Ex{Float64}
  constraint::Ex{Bool}
  sense::Symbol
  objbound::Interval
  solution::Vector{Interval}
  DRealMathProgModel(ctx::Context) = new(ctx, :Unsolved)
  DRealMathProgModel(ctx, numvar, vars, cost_var, constraint) =
    new(ctx, numvar, vars, cost_var, constraint)
end

function DRealMathProgModel(precision::Float64)
  warn("FIXME: using Global Context")
  # ctx = Context(qf_nra)
  ctx = global_context()
  set_precision!(ctx, precision)
  DRealMathProgModel(ctx)
end

MathProgBase.SolverInterface.NonlinearModel(s::DRealSolver) = DRealMathProgModel(s.precision)

## Interface Implementation
## ========================

getsense(m::DRealSolver) = m.sense
numvar(m::DRealSolver) = m.numvar
# numconstr(m::DRealSolver) = m.numconstr

# @doc "Best value" ->
getobjval(m::AbstractMathProgModel) = getobjbound(m).u

# @doc "Returns the best known bound on the optimal objective value" ->
function getobjbound(m::AbstractMathProgModel)
  m.status != :Optimal && error("Cannot get optimal value when status is $(m.status)")
  m.objbound
end

# @doc "Returns the solution vector found by the solver" ->
function getsolution(m::AbstractMathProgModel)
  m.status != :Optimal && error("Cannot get solution when status is $(m.status)")
  [mid(v) for v in m.solution]
end

# @doc "Returns the total elapsed solution time as reported by the solver." ->
# function getsolvetime(m::AbstractMathProgModel) end

# @doc "Provide an initial solution v to the solver, as supported." ->
function setwarmstart!(m::AbstractMathProgModel, v) end

# @doc "Loads the nonlinear programming problem into the model `m`." ->
function loadproblem!(m::DRealMathProgModel,
                      numVar::Integer,
                      numConstr::Integer,
                      x_l::Vector{Float64},      # variable lower bounds
                      x_u::Vector{Float64},      # variable upper bounds
                      g_lb,     # constraint lower bounds
                      g_ub,     # constraint upper bounds
                      sense::Symbol, # :Max or :Min
                      d::AbstractNLPEvaluator)

  (sense == :Min || sense == :Max) || error("Unrecognized sense $sense")
  @assert length(x_l) == length(x_u) == numVar

  cost_var = Var(m.ctx, Float64, -100.00, 100.00)
  @show x_l
  @show x_u
  vars = [Var(m.ctx, Float64, x_l[i], x_u[i]) for i = 1:numVar]

  m.vars = vars
  @show obj_expr(d)
  # push_ctx!(m.ctx)
  add!(m.ctx, cost_var == eval(Expr(:let, obj_expr(d), :(x=$vars))))
  m.cost_var = cost_var
  m.sense = sense
  m.numvar = length(vars)
end

# @doc "Solves the optimization problem" ->
function optimize!(m::DRealMathProgModel)
  local cost
  local optimal_model
  try
    @show cost, optimal_model = minimize(m.ctx, m.cost_var, m.vars...; lb = -100.0, ub = 100.0)
  catch e
    reset_global_ctx!()
    rethrow(e)
  end
  m.status = :Optimal
  m.objbound = cost
  opt_sols_vec = Interval[optimal_model...]
  m.solution = opt_sols_vec
end

# @doc "Status after solving. Possible values include :Optimal, :Infeasible, :Unbounded, :UserLimit"
function status(m::DRealMathProgModel) m.status end


text:
module ResultTests

using DiffBase
using Compat
using Base.Test

using DiffBase: DiffResult, GradientResult, JacobianResult, HessianResult,
                value, value!, derivative, derivative!, gradient, gradient!,
                jacobian, jacobian!, hessian, hessian!

const k = 3
const n0, n1, n2 = rand(), rand(), rand()
const x0, x1, x2 = rand(k), rand(k, k), rand(k, k, k)
const rn, rx = DiffResult(n0, n1, n2), DiffResult(x0, x1, x2)

issimilar(x, y) = typeof(x) == typeof(y) && size(x) == size(y)
issimilar(x::DiffResult, y::DiffResult) = issimilar(value(x), value(y)) && all(issimilar, zip(x.derivs, y.derivs))
issimilar(t::Tuple) = issimilar(t...)

##############
# DiffResult #
##############

@test rn == DiffResult(n0, n1, n2)
@test rx == DiffResult(x0, x1, x2)

@test issimilar(GradientResult(x0), DiffResult(first(x0), x0))
@test issimilar(JacobianResult(x0), DiffResult(x0, similar(x0, k, k)))
@test issimilar(JacobianResult(similar(x0, k + 1), x0), DiffResult(similar(x0, k + 1), similar(x0, k + 1, k)))
@test issimilar(HessianResult(x0), DiffResult(first(x0), x0, similar(x0, k, k)))

@test eltype(rn) === typeof(n0)
@test eltype(rx) === eltype(x0)

rn_copy = copy(rn)
@test rn == rn_copy
@test rn !== rn_copy

rx_copy = copy(rx)
@test rx == rx_copy
@test rx !== rx_copy

# value/value! #
#--------------#

@test value(rn) === n0
@test value(rx) === x0

value!(rn, n1)
@test value(rn) === n1
value!(rn, n0)

x0_new, x0_copy = rand(k), copy(x0)
value!(rx, x0_new)
@test value(rx) === x0 == x0_new
value!(rx, x0_copy)

value!(exp, rn, n1)
@test value(rn) === exp(n1)
value!(rn, n0)

x0_new, x0_copy = rand(k), copy(x0)
value!(exp, rx, x0_new)
@test value(rx) === x0 == @compat(exp.(x0_new))
value!(rx, x0_copy)

# derivative/derivative! #
#------------------------#

@test derivative(rn) === n1
@test derivative(rn, Val{2}) === n2

@test derivative(rx) === x1
@test derivative(rx, Val{2}) === x2

derivative!(rn, n0)
@test derivative(rn) === n0
derivative!(rn, n1)

x1_new, x1_copy = rand(k, k), copy(x1)
derivative!(rx, x1_new)
@test derivative(rx) === x1 == x1_new
derivative!(rx, x1_copy)

derivative!(rn, n1, Val{2})
@test derivative(rn, Val{2}) === n1
derivative!(rn, n2, Val{2})

x2_new, x2_copy = rand(k, k, k), copy(x2)
derivative!(rx, x2_new, Val{2})
@test derivative(rx, Val{2}) === x2 == x2_new
derivative!(rx, x2_copy, Val{2})

derivative!(exp, rn, n0)
@test derivative(rn) === exp(n0)
derivative!(rn, n1)

x1_new, x1_copy = rand(k, k), copy(x1)
derivative!(exp, rx, x1_new)
@test derivative(rx) === x1 == @compat(exp.(x1_new))
derivative!(exp, rx, x1_copy)

derivative!(exp, rn, n1, Val{2})
@test derivative(rn, Val{2}) === exp(n1)
derivative!(rn, n2, Val{2})

x2_new, x2_copy = rand(k, k, k), copy(x2)
derivative!(exp, rx, x2_new, Val{2})
@test derivative(rx, Val{2}) === x2 == @compat(exp.(x2_new))
derivative!(exp, rx, x2_copy, Val{2})

# gradient/gradient! #
#--------------------#

x1_new, x1_copy = rand(k, k), copy(x1)
gradient!(rx, x1_new)
@test gradient(rx) === x1 == x1_new
gradient!(rx, x1_copy)

x1_new, x1_copy = rand(k, k), copy(x1)
gradient!(exp, rx, x1_new)
@test gradient(rx) === x1 == @compat(exp.(x1_new))
gradient!(exp, rx, x1_copy)

# jacobian/jacobian! #
#--------------------#

x1_new, x1_copy = rand(k, k), copy(x1)
jacobian!(rx, x1_new)
@test jacobian(rx) === x1 == x1_new
jacobian!(rx, x1_copy)

x1_new, x1_copy = rand(k, k), copy(x1)
jacobian!(exp, rx, x1_new)
@test jacobian(rx) === x1 == @compat(exp.(x1_new))
jacobian!(exp, rx, x1_copy)

# hessian/hessian! #
#------------------#

x2_new, x2_copy = rand(k, k, k), copy(x2)
hessian!(rx, x2_new)
@test hessian(rx) === x2 == x2_new
hessian!(rx, x2_copy)

x2_new, x2_copy = rand(k, k, k), copy(x2)
hessian!(exp, rx, x2_new)
@test hessian(rx) === x2 == @compat(exp.(x2_new))
hessian!(exp, rx, x2_copy)

end # module