text:
return_one_if_zero(val::T) where {T <: Real} = (val == zero(T)) ? one(T) : val

function get_norm_rc_CSC!(v, A_colptr, A_rowval, A_nzval, n, ax)
  T = eltype(v)
  v .= zero(T)
  for j = 1:n
    @inbounds for i = A_colptr[j]:(A_colptr[j + 1] - 1)
      k = ax == :row ? A_rowval[i] : j
      if abs(A_nzval[i]) > v[k]
        v[k] = abs(A_nzval[i])
      end
    end
  end

  v .= sqrt.(v)
  @inbounds @simd for i = 1:length(v)
    if v[i] == zero(T)
      v[i] = one(T)
    end
  end
end
get_norm_rc!(v, A::SparseMatrixCSC, ax) =
  get_norm_rc_CSC!(v, A.colptr, A.rowval, A.nzval, size(A, 2), ax)

function get_norm_rc!(v, A, ax)
  T = eltype(v)
  v .= zero(T)
  if ax == :row
    maximum!(abs, v, A)
  elseif ax == :col
    maximum!(abs, v', A)
  end
  v .= return_one_if_zero.(sqrt.(v))
end

function mul_D1_A_D2_CSC!(A_colptr, A_rowval, A_nzval, d1, d2, r, c, uplo)
  for j = 1:length(c)
    @inbounds @simd for i = A_colptr[j]:(A_colptr[j + 1] - 1)
      A_nzval[i] /= r[A_rowval[i]] * c[j]
    end
  end

  if uplo == :U
    d1 ./= c
    d2 ./= r
  else
    d1 ./= r
    d2 ./= c
  end
end
mul_D1_A_D2(A::SparseMatrixCSC, d1, d2, R, C, uplo) =
  mul_D1_A_D2_CSC!(A.colptr, A.rowval, A.nzval, d1, d2, R.diag, C.diag, uplo)

function mul_D1_A_D2(A, d1, d2, R, C, uplo)
  ldiv!(R, A)
  rdiv!(A, C)
  if uplo == :U
    d1 ./= C.diag
    d2 ./= R.diag
  else
    d1 ./= R.diag
    d2 ./= C.diag
  end
end

function mul_Q_D_CSC!(Q_colptr, Q_rowval, Q_nzval, d, c)
  for j = 1:length(d)
    @inbounds @simd for i = Q_colptr[j]:(Q_colptr[j + 1] - 1)
      Q_nzval[i] /= c[Q_rowval[i]] * c[j]
    end
  end
  d ./= c
end
mul_Q_D!(Q::SparseMatrixCSC, d, C) = mul_Q_D_CSC!(Q.colptr, Q.rowval, Q.nzval, d, C.diag)

function mul_Q_D!(Q, d, C)
  ldiv!(C, Q)
  rdiv!(Q, C)
  d ./= C.diag
end

function mul_Q_D2_CSC!(Q_colptr, Q_rowval, Q_nzval, d2)
  for j = 1:length(d2)
    @inbounds @simd for i = Q_colptr[j]:(Q_colptr[j + 1] - 1)
      Q_nzval[i] *= d2[Q_rowval[i]] * d2[j]
    end
  end
end
mul_Q_D2!(Q::SparseMatrixCSC, D2) = mul_Q_D2_CSC!(Q.colptr, Q.rowval, Q.nzval, D2.diag)

function mul_Q_D2!(Q, D2)
  lmul!(D2, Q)
  rmul!(Q, D2)
end

# equilibration scaling (transform A so that its rows and cols have an infinite norm close to 1):
# A ← D2 * A * D1 (uplo = :L), R_k, C_k are storage Diagonal Arrays that have the same size as D1, D2
# or A ← D2 * Aᵀ * D1 (uplo = :U), R_k, C_k are storage Diagonal Arrays that have the same size as D2, D1
# ϵ is the norm tolerance on the row and cols infinite norm of A
# max_iter is the maximum number of iterations
function equilibrate!(
  A::AbstractMatrix{T},
  D1::Diagonal{T, S},
  D2::Diagonal{T, S},
  R_k::Diagonal{T, S},
  C_k::Diagonal{T, S};
  ϵ::T = T(1.0e-2),
  max_iter::Int = 100,
  uplo::Symbol = :L,
) where {T <: Real, S <: AbstractVector{T}}
  min(size(A)...) == 0 && return
  get_norm_rc!(R_k.diag, A, :row)
  get_norm_rc!(C_k.diag, A, :col)
  convergence = maximum(abs.(one(T) .- R_k.diag)) <= ϵ && maximum(abs.(one(T) .- C_k.diag)) <= ϵ
  mul_D1_A_D2(A, D1.diag, D2.diag, R_k, C_k, uplo)
  k = 1
  while !convergence && k < max_iter
    get_norm_rc!(R_k.diag, A, :row)
    get_norm_rc!(C_k.diag, A, :col)
    convergence = maximum(abs.(one(T) .- R_k.diag)) <= ϵ && maximum(abs.(one(T) .- C_k.diag)) <= ϵ
    mul_D1_A_D2(A, D1.diag, D2.diag, R_k, C_k, uplo)
    k += 1
  end
end

# Symmetric equilibration scaling (transform Q so that its rows and cols have an infinite norm close to 1):
# Q ← D3 * Q * D3, C_k is a storage Diagonal Array that has the same size as D3
# ϵ is the norm tolerance on the row and cols infinite norm of A
# max_iter is the maximum number of iterations
function equilibrate!(
  Q::Symmetric{T},
  D3::Diagonal{T, S},
  C_k::Diagonal{T, S};
  ϵ::T = T(1.0e-2),
  max_iter::Int = 100,
) where {T <: Real, S <: AbstractVector{T}}
  size(Q, 1) == 0 && return
  get_norm_rc!(C_k.diag, Q.data, :col)
  convergence = maximum(abs.(one(T) .- C_k.diag)) <= ϵ
  mul_Q_D!(Q.data, D3.diag, C_k)
  k = 1
  while !convergence && k < max_iter
    get_norm_rc!(C_k.diag, Q, :col)
    convergence = maximum(abs.(one(T) .- C_k.diag)) <= ϵ
    mul_Q_D!(Q.data, D3.diag, C_k)
    k += 1
  end
end

function scaling!(
  fd_T0::QM_FloatData{T},
  id::QM_IntData,
  sd::ScaleDataLP{T},
  ϵ::T;
  max_iter::Int = 100,
) where {T <: Real}
  d1, d2, r_k, c_k = sd.d1, sd.d2, sd.r_k, sd.c_k
  d1 .= one(T)
  d2 .= one(T)
  D1 = Diagonal(d1)
  D2 = Diagonal(d2)
  R_k = Diagonal(r_k)
  C_k = Diagonal(c_k)

  # r (resp. c) norm of rows of AT (resp. cols)
  # scaling: D2 * AT * D1
  equilibrate!(fd_T0.A, D2, D1, C_k, R_k; ϵ = ϵ, max_iter = max_iter, uplo = fd_T0.uplo)

  fd_T0.b .*= d2
  fd_T0.c .*= d1
  fd_T0.lvar ./= d1
  fd_T0.uvar ./= d1
end

function div_D_Q_D_CSC!(Q_colptr, Q_rowval, Q_nzval, d, n)
  for j = 1:n
    @inbounds @simd for i = Q_colptr[j]:(Q_colptr[j + 1] - 1)
      Q_nzval[i] /= d[Q_rowval[i]] * d[j]
    end
  end
end
div_D_Q_D!(Q::SparseMatrixCSC, D) = div_D_Q_D_CSC!(Q.colptr, Q.rowval, Q.nzval, D.diag, size(Q, 1))

function div_D_Q_D!(Q, D)
  ldiv!(D, Q)
  rdiv!(Q, D)
end

function div_D1_A_D2_CSC!(A_colptr, A_rowval, A_nzval, d1, d2, n, uplo)
  for j = 1:n
    @inbounds @simd for i = A_colptr[j]:(A_colptr[j + 1] - 1)
      A_nzval[i] /= (uplo == :U) ? d1[j] * d2[A_rowval[i]] : d1[A_rowval[i]] * d2[j]
    end
  end
end
div_D1_A_D2!(A::SparseMatrixCSC, D1, D2, uplo) =
  div_D1_A_D2_CSC!(A.colptr, A.rowval, A.nzval, D1.diag, D2.diag, size(A, 2), uplo)

function div_D1_A_D2!(A, D1, D2, uplo)
  if uplo == :U
    rdiv!(A, D1)
    ldiv!(D2, A)
  else
    ldiv!(D1, A)
    rdiv!(A, D2)
  end
end

function post_scale!(
  sd::ScaleData{T},
  pt::Point{T},
  res::AbstractResiduals{T},
  fd_T0::QM_FloatData{T},
  id::QM_IntData,
  itd::IterData{T},
) where {T <: Real}
  if typeof(sd) <: ScaleDataLP
    d1 = sd.d1
    d2 = sd.d2
  elseif typeof(sd) <: ScaleDataQP
    d1 = view(sd.deq, 1:(id.nvar))
    d2 = view(sd.deq, (id.nvar + 1):(id.nvar + id.ncon))
  end
  D1, D2 = Diagonal(d1), Diagonal(d2)

  # unscale problem data
  nnz(fd_T0.Q.data) > 0 && div_D_Q_D!(fd_T0.Q.data, D1)
  div_D1_A_D2!(fd_T0.A, D2, D1, fd_T0.uplo)
  fd_T0.b ./= d2
  fd_T0.c ./= d1
  fd_T0.lvar .*= d1
  fd_T0.uvar .*= d1

  # update final point
  pt.x .*= d1
  pt.y .*= d2
  pt.s_l ./= @views d1[id.ilow]
  pt.s_u ./= @views d1[id.iupp]

  # update iter data
  mul!(itd.Qx, fd_T0.Q, pt.x)
  itd.xTQx_2 = dot(pt.x, itd.Qx) / 2
  fd_T0.uplo == :U ? mul!(itd.ATy, fd_T0.A, pt.y) : mul!(itd.ATy, fd_T0.A', pt.y)
  fd_T0.uplo == :U ? mul!(itd.Ax, fd_T0.A', pt.x) : mul!(itd.Ax, fd_T0.A, pt.x)
  itd.cTx = dot(fd_T0.c, pt.x)
  itd.pri_obj = itd.xTQx_2 + itd.cTx + fd_T0.c0
  itd.dual_obj =
    dot(fd_T0.b, pt.y) - itd.xTQx_2 + dot(pt.s_l, view(fd_T0.lvar, id.ilow)) -
    dot(pt.s_u, view(fd_T0.uvar, id.iupp)) + fd_T0.c0

  # update residuals
  res.rb .= itd.Ax .- fd_T0.b
  res.rc .= itd.ATy .- itd.Qx .- fd_T0.c
  res.rc[id.ilow] .+= pt.s_l
  res.rc[id.iupp] .-= pt.s_u
  #         rcNorm, rbNorm = norm(rc), norm(rb)
  res.rcNorm, res.rbNorm = norm(res.rc, Inf), norm(res.rb, Inf)
end

# equilibrate K2
function get_norm_rc_K2_CSC!(
  v,
  Q_colptr,
  Q_rowval,
  Q_nzval,
  A_colptr,
  A_rowval,
  A_nzval,
  D,
  deq,
  δ,
  nvar,
  ncon,
  uplo,
)
  T = eltype(v)
  v .= zero(T)
  ignore_D = length(D) == 0 # ignore D if it is empty (in case we want to scale [Q Aᵀ; A δI])
  for j = 1:nvar
    passed_diagj = false
    @inbounds for k = Q_colptr[j]:(Q_colptr[j + 1] - 1)
      i = Q_rowval[k]
      if i == j
        nzvalij = ignore_D ? -deq[i]^2 * Q_nzval[k] : deq[i]^2 * (-Q_nzval[k] + D[j])
        passed_diagj = true
      else
        nzvalij = -deq[i] * Q_nzval[k] * deq[j]
      end
      if abs(nzvalij) > v[i]
        v[i] = abs(nzvalij)
      end
      if abs(nzvalij) > v[j]
        v[j] = abs(nzvalij)
      end
    end
    if !passed_diagj
      nzvalij = ignore_D ? zero(T) : deq[j]^2 * D[j]
      if abs(nzvalij) > v[j]
        v[j] = abs(nzvalij)
      end
    end
  end

  ncolA = (uplo == :L) ? nvar : ncon
  for j = 1:ncolA
    @inbounds for k = A_colptr[j]:(A_colptr[j + 1] - 1)
      if uplo == :L
        iup = A_rowval[k] + nvar
        jup = j
      else
        iup = A_rowval[k]
        jup = j + nvar
      end
      nzvalij = deq[iup] * A_nzval[k] * deq[jup]
      if abs(nzvalij) > v[iup]
        v[iup] = abs(nzvalij)
      end
      if abs(nzvalij) > v[jup]
        v[jup] = abs(nzvalij)
      end
    end
  end

  if δ > 0
    @inbounds for j = (nvar + 1):(nvar + ncon)
      rdij = δ * deq[j]^2
      if abs(rdij) > v[j]
        v[j] = abs(rdij)
      end
    end
  end

  v .= sqrt.(v)
  @inbounds @simd for i = 1:length(v)
    if v[i] == zero(T)
      v[i] = one(T)
    end
  end
end

get_norm_rc_K2!(v, Q::SparseMatrixCSC, A::SparseMatrixCSC, D, deq, δ, nvar, ncon, uplo) =
  get_norm_rc_K2_CSC!(
    v,
    Q.colptr,
    Q.rowval,
    Q.nzval,
    A.colptr,
    A.rowval,
    A.nzval,
    D,
    deq,
    δ,
    nvar,
    ncon,
    uplo,
  )

get_norm_rc_K2!(
  v,
  Q::Symmetric{T, SparseMatrixCSC{T, Int}},
  A::SparseMatrixCSC,
  D,
  deq,
  δ,
  nvar,
  ncon,
  uplo,
) where {T} = get_norm_rc_K2!(v, Q.data, A, D, deq, δ, nvar, ncon, uplo)

# not efficient but can be improved:
function get_norm_rc_K2!(v, Q::Symmetric, A, D, deq, δ, nvar, ncon, uplo)
  # D as storage vec
  @assert δ == 0
  T = eltype(v)
  v .= zero(T)
  v1 = view(v, 1:nvar)
  v2 = view(v, (nvar + 1):(nvar + ncon))
  Deq1 = Diagonal(view(deq, 1:nvar))
  Deq2 = Diagonal(view(deq, (nvar + 1):(nvar + ncon)))
  rmul!(Q.data, Deq1)
  lmul!(Deq1, Q.data)
  maximum!(abs, v1, Q)
  rdiv!(Q.data, Deq1)
  ldiv!(Deq1, Q.data)
  if uplo == :U
    lmul!(Deq1, A)
    rmul!(A, Deq2)
    maximum!(abs, D, A)
    maximum!(abs, v2', A)
    ldiv!(Deq1, A)
    rdiv!(A, Deq2)
  else
    lmul!(Deq2, A)
    rmul!(A, Deq1)
    maximum!(abs, v2, A)
    maximum!(abs, D', A)
    ldiv!(Deq2, A)
    rdiv!(A, Deq1)
  end
  v1 .= max.(v1, D)
  v .= return_one_if_zero.(sqrt.(v))
end

function equilibrate_K2!(
  Q::SparseMatrixCSC{T},
  A::SparseMatrixCSC{T},
  D::Vector{T},
  δ::T,
  nvar::Int,
  ncon::Int,
  Deq::Diagonal{T, S},
  C_k::Diagonal{T, S},
  uplo::Symbol;
  ϵ::T = T(1.0e-2),
  max_iter::Int = 100,
) where {T <: Real, S <: AbstractVector{T}}
  Deq.diag .= one(T)
  # get_norm_rc!(C_k.diag, Q.data, :col)
  get_norm_rc_K2!(C_k.diag, Q, A, D, Deq.diag, δ, nvar, ncon, uplo)
  convergence = maximum(abs.(one(T) .- C_k.diag)) <= ϵ
  Deq.diag ./= C_k.diag
  k = 1
  while !convergence && k < max_iter
    # get_norm_rc!(C_k.diag, Q, :col)
    get_norm_rc_K2!(C_k.diag, Q, A, D, Deq.diag, δ, nvar, ncon, uplo)
    convergence = maximum(abs.(one(T) .- C_k.diag)) <= ϵ
    Deq.diag ./= C_k.diag
    k += 1
  end
end

function scaling!(
  fd_T0::QM_FloatData{T},
  id::QM_IntData,
  sd::ScaleDataQP{T},
  ϵ::T;
  max_iter::Int = 100,
) where {T <: Real}
  size(fd_T0.Q) == 0 && min(size(fd_T0.A)...) == 0 && return
  deq, c_k = sd.deq, sd.c_k
  deq .= one(T)
  Deq = Diagonal(deq)
  C_k = Diagonal(c_k)
  # empty vector to use ignore_D in get_norm_rc_K2 or storage vector if not csc
  Dtmp = typeof(fd_T0.A) <: SparseMatrixCSC ? similar(deq, 0) : similar(deq, id.nvar)
  δ = zero(T)
  # scaling Q (symmetric)
  get_norm_rc_K2!(C_k.diag, fd_T0.Q, fd_T0.A, Dtmp, Deq.diag, δ, id.nvar, id.ncon, fd_T0.uplo)
  convergence = maximum(abs.(one(T) .- C_k.diag)) <= ϵ
  Deq.diag ./= C_k.diag
  k = 1
  while !convergence && k < max_iter
    get_norm_rc_K2!(C_k.diag, fd_T0.Q, fd_T0.A, Dtmp, Deq.diag, δ, id.nvar, id.ncon, fd_T0.uplo)
    convergence = maximum(abs.(one(T) .- C_k.diag)) <= ϵ
    Deq.diag ./= C_k.diag
    k += 1
  end

  D1 = Diagonal(view(deq, 1:(id.nvar)))
  D2 = Diagonal(view(deq, (id.nvar + 1):(id.nvar + id.ncon)))
  if fd_T0.uplo == :U
    lmul!(D1, fd_T0.A)
    rmul!(fd_T0.A, D2)
  else
    lmul!(D2, fd_T0.A)
    rmul!(fd_T0.A, D1)
  end
  mul_Q_D2!(fd_T0.Q.data, D1)
  fd_T0.c .*= D1.diag
  fd_T0.lvar ./= D1.diag
  fd_T0.uvar ./= D1.diag
  fd_T0.b .*= D2.diag
end


text:
# No info
struct Flat <: ContinuousUnivariateDistribution
end

Distributions.rand(d::Flat) = rand()
Distributions.logpdf(d::Flat, x::T) where T<:Real= zero(x)
Distributions.minimum(d::Flat) = -Inf
Distributions.maximum(d::Flat) = +Inf

# For vec support
Distributions.rand(d::Flat, n::Int) = Vector([rand() for _ = 1:n])
Distributions.logpdf(d::Flat, x::Vector{T}) where T<:Real= zero(x)

# Pos
struct FlatPos{T<:Real} <: ContinuousUnivariateDistribution
    l::T
    FlatPos{T}(l::T) where T = new{T}(l)
end

FlatPos(l::T) where T<:Real = FlatPos{T}(l)

Distributions.rand(d::FlatPos) = rand() + d.l
Distributions.logpdf(d::FlatPos, x::T) where T<:Real = if x <= d.l -Inf else zero(x) end
Distributions.minimum(d::FlatPos) = d.l
Distributions.maximum(d::FlatPos) = +Inf

# For vec support
Distributions.rand(d::FlatPos, n::Int) = Vector([rand() for _ = 1:n] .+ d.l)
Distributions.logpdf(d::FlatPos, x::Vector{T}) where T<:Real = if any(x .<= d.l) -Inf else zero(x) end

ext: jl


text:
function isdiff(a, b) :: Bool
    if typeof(a) !== typeof(b) return true end
    if a === b return false end
    if isempty(fieldnames(typeof(a)))
        return a != b
    end
    for prop in fieldnames(typeof(a))
        try
            if isdiff(getfield(a, prop), getfield(b, prop))
                return true
            end
        catch;
            if getfield(a, prop) != getfield(b, prop)
                return true
            end
        end
    end
    return false
end


text:
export Stream, openStream, closeStream, writeStream, readStream

const TypeToSampleFormat = {Float32 => 0x1, Int32 => 0x2, Int16 => 0x8,
                            Int8 => 0x10, Uint8 => 0x20}

type Stream
    pastream::PaStream
    channels::Int32
    sampleRate::Float64
    framesPerBuffer::Uint
    dtype::DataType
end

function InputStreamParameters(device::Integer, numChannels::Integer,
                               dtype::DataType)
    devinfo = DeviceInfo(device)
    return StreamParameters(convert(Int32, device), convert(Int32, numChannels),
                            convert(Uint, TypeToSampleFormat[dtype]),
                            devinfo.defaultHighInputLatency,
                            convert(Ptr{None}, C_NULL))
end

function OutputStreamParameters(device::Integer, numChannels::Integer,
                                   dtype::DataType)
    devinfo = DeviceInfo(device)
    return StreamParameters(convert(Int32, device),
                            convert(Int32, numChannels),
                            convert(Uint, TypeToSampleFormat[dtype]),
                            devinfo.defaultHighOutputLatency,
                            convert(Ptr{None}, C_NULL))
end

function openStream(inputId::Integer, outputId::Integer,
                       sampleRate::Integer, numChannels::Integer,
                       framesPerBuffer::Integer, dtype::DataType)
    pastream = Array(PaStream, 1)
    inputParams = InputStreamParameters(inputId, numChannels, dtype)
    outputParams = OutputStreamParameters(outputId, numChannels, dtype)

    err = ccall((:Pa_OpenStream, portaudio), Int32,
                (Ptr{PaStream}, Ptr{StreamParameters}, Ptr{StreamParameters},
                 Float64, Uint, Uint, Ptr{Void}, Ptr{Void}),
                pastream, &inputParams, &outputParams,
                sampleRate, framesPerBuffer, 0, C_NULL, C_NULL)
    check_pa_error(err)
    return Stream(pastream[],
                  convert(Int32, numChannels),
                  convert(Float64, sampleRate),
                  convert(Uint, framesPerBuffer),
                  dtype)
end

function openStream(sampleRate::Integer, numChannels::Integer, dtype::DataType)
    openStream(defaultInputDevice(), defaultOutputDevice(),
               sampleRate, numChannels, 1024, dtype)
end

function openStream(f::Function, args...)
    stream = openStream(args...)
    f(stream)
    closeStream(stream)
end

function closeStream(stream::Stream)
    err = ccall((:Pa_CloseStream, portaudio), Int32, (PaStream,), stream.pastream)
    check_pa_error(err)
end

function startStream(f::Function, stream::Stream)
    err = ccall((:Pa_StartStream, portaudio), Int32, (PaStream,), stream.pastream)
    check_pa_error(err)
    f()
    err = ccall((:Pa_StopStream, portaudio), Int32, (PaStream,), stream.pastream)
    check_pa_error(err)
end

function writeStream{T}(stream::Stream, data::Array{T})
    if stream.dtype != T
        error("Type mismatch: expected $(stream.dtype), got $T")
    end
    startStream(stream) do
        err = ccall((:Pa_WriteStream, portaudio), Int32,
                    (PaStream, Ptr{Void}, Uint),
                    stream.pastream, data, length(data) / stream.channels)
        check_pa_error(err)
    end
end

function readStream(stream::Stream, nframes::Integer)
    println("Now recording. Speak clearly into the microphone.")
    arr = (stream.channels == 1) ?
            Array(stream.dtype, nframes) :
            Array(stream.dtype, stream.channels, nframes)
    startStream(stream) do
        err = ccall((:Pa_ReadStream, portaudio), Int32, (PaStream, Ptr{Void}, Uint),
                    stream.pastream, arr, nframes)
        check_pa_error(err)
    end
    println("Finished recording")
    return arr
end

function readStream(stream::Stream, duration::FloatingPoint)
    nframes = int(duration * stream.sampleRate)
    return readStream(stream, nframes)
end


text:
## PARAMETER RANGES

#     Scale = SCALE()

# Object for dispatching on scales and functions when generating
# parameter ranges. We require different behaviour for scales and
# functions:

#      transform(Scale, scale(:log10), 100) = 2
#      inverse_transform(Scale, scale(:log10), 2) = 100

# but
#     transform(Scale, scale(log10), 100) = 100       # identity
#     inverse_transform(Scale, scale(log10), 100) = 2

# See also: strange

struct SCALE end
Scale = SCALE()
scale(s::Symbol) = Val(s)
scale(f::Function) = f
MLJ.transform(::SCALE, ::Val{:linear}, x) = x
MLJ.inverse_transform(::SCALE, ::Val{:linear}, x) = x
MLJ.transform(::SCALE, ::Val{:log}, x) = log(x)
MLJ.inverse_transform(::SCALE, ::Val{:log}, x) = exp(x)
MLJ.transform(::SCALE, ::Val{:log10}, x) = log10(x)
MLJ.inverse_transform(::SCALE, ::Val{:log10}, x) = 10^x
MLJ.transform(::SCALE, ::Val{:log2}, x) = log2(x)
MLJ.inverse_transform(::SCALE, ::Val{:log2}, x) = 2^x
MLJ.transform(::SCALE, f::Function, x) = x            # not a typo!
MLJ.inverse_transform(::SCALE, f::Function, x) = f(x) # not a typo!

abstract type ParamRange <: MLJType end

Base.isempty(::ParamRange) = false

struct NominalRange{T} <: ParamRange
    field::Union{Symbol,Expr}
    values::Tuple{Vararg{T}}
end

struct NumericRange{T,D} <: ParamRange
    field::Union{Symbol,Expr}
    lower::T
    upper::T
    scale::D
end

# function Base.show(stream::IO, object::ParamRange)
#     id = objectid(object)
#     T = typeof(object).parameters[1]
#     description = string(typeof(object).name.name, "{$T}")
#     str = "$description @ $(MLJBase.handle(object))"
#     printstyled(IOContext(stream, :color=> MLJBase.SHOW_COLOR),
#                 str, color=:blue)
#     print(stream, " for $(object.field)")

MLJBase.show_as_constructed(::Type{<:ParamRange}) = true

"""
    r = range(model, :hyper; values=nothing)

Defines a `NominalRange` object for a field `hyper` of `model`,
assuming the field is a not a subtype of `Real`. Note that `r` is not
directly iterable but `iterator(r)` iterates over `values`.

A nested hyperparameter is specified using dot notation. For example,
`:(atom.max_depth)` specifies the `:max_depth` hyperparameter of the hyperparameter `:atom` of `model`.

    r = range(model, :hyper; upper=nothing, lower=nothing, scale=:linear)

Defines a `NumericRange` object for a `Real` field `hyper` of `model`.
Note that `r` is not directly iteratable but `iterator(r, n)` iterates
over `n` values between `lower` and `upper` values, according to the
specified `scale`. The supported scales are `:linear, :log, :log10,
:log2`. Values for `Integer` types are rounded (with duplicate values
removed, resulting in possibly less than `n` values).

Alternatively, if a function `f` is provided as `scale`, then
`iterator(r, n)` iterates over the values `[f(x1), f(x2), ... ,
f(xn)]`, where `x1, x2, ..., xn` are linearly spaced between `lower`
and `upper`.

"""
function Base.range(model, field::Union{Symbol,Expr}; values=nothing,
                    lower=nothing, upper=nothing, scale::D=:linear) where D
    value = recursive_getproperty(model, field)
    T = typeof(value)
    if T <: Real
        (lower === nothing || upper === nothing) &&
            error("You must specify lower=... and upper=... .")
        return NumericRange{T,D}(field, lower, upper, scale)
    else
        values === nothing && error("You must specify values=... .")
        return NominalRange{T}(field, Tuple(values))
    end
end

"""
    MLJ.scale(r::ParamRange)

Return the scale associated with the `ParamRange` object `r`. The
possible return values are: `:none` (for a `NominalRange`), `:linear`,
`:log`, `:log10`, `:log2`, or `:custom` (if `r.scale` is function).

"""
scale(r::NominalRange) = :none
scale(r::NumericRange) = :custom
scale(r::NumericRange{T,Symbol}) where T =
    r.scale

## ITERATORS FROM A PARAMETER RANGE

iterator(param_range::NominalRange) = collect(param_range.values)

function iterator(param_range::NumericRange{T}, n::Int) where {T<:Real}
    s = scale(param_range.scale)
    transformed = range(transform(Scale, s, param_range.lower),
                stop=transform(Scale, s, param_range.upper),
                length=n)
    inverse_transformed = map(transformed) do value
        inverse_transform(Scale, s, value)
    end
    return unique(inverse_transformed)
end

# in special case of integers, round to nearest integer:
function iterator(param_range::NumericRange{I}, n::Int) where {I<:Integer}
    s = scale(param_range.scale)
    transformed = range(transform(Scale, s, param_range.lower),
                stop=transform(Scale, s, param_range.upper),
                length=n)
    inverse_transformed =  map(transformed) do value
        round(I, inverse_transform(Scale, s, value))
    end
    return unique(inverse_transformed)
end

## GRID GENERATION

"""
    unwind(iterators...)

Represent all possible combinations of values generated by `iterators`
as rows of a matrix `A`. In more detail, `A` has one column for each
iterator in `iterators` and one row for each distinct possible
combination of values taken on by the iterators. Elements in the first
column cycle fastest, those in the last clolumn slowest.

### Example

````julia
julia> iterators = ([1, 2], ["a","b"], ["x", "y", "z"]);
julia> MLJ.unwind(iterators...)
12×3 Array{Any,2}:
 1  "a"  "x"
 2  "a"  "x"
 1  "b"  "x"
 2  "b"  "x"
 1  "a"  "y"
 2  "a"  "y"
 1  "b"  "y"
 2  "b"  "y"
 1  "a"  "z"
 2  "a"  "z"
 1  "b"  "z"
 2  "b"  "z"
````

"""
function unwind(iterators...)
    n_iterators = length(iterators)
    iterator_lengths = map(length, iterators)

    # product of iterator lengths:
    L = reduce(*, iterator_lengths)
    L != 0 || error("Parameter iterator of length zero encountered.")

    A = Array{Any}(undef, L, n_iterators)
    n_iterators != 0 || return A

    inner = 1
    outer = L
    for j in 1:n_iterators
        outer = outer ÷ iterator_lengths[j]
        A[:,j] = repeat(iterators[j], inner=inner, outer=outer)
        inner *= iterator_lengths[j]
    end
    return A
end


text:
#   macro long(sa1::Array{SeriesPair,1}, ind::Function, op::Function, val::Union(Int, Float64), foo, sa2::Array{SeriesPair,1})
#   #macro long(sa, ind, op, val, foo, sa2)
#
#     vec     = :($ind($sa))
#     sigdays = :($tradesignal($vec, $val, $op))
#     oprets  = :($lag($percentchange($sa2), 2))
#     trades  = :($oprets[$sigdays])
#     :($exp($sum($value($trades))) ^ (252/$length($sa2)) - 1)
#   end
#
#   # what about a bid price generated from a model?
#
#
#   # proposed api
#   # @bid Goog TLTrsi AR(1) tradedays(3) targetexit([.005, .008, .01], [.4, .4, .2], signaltrue=true) stopout(.01, trailing=false)
#   macro bid(stock::Stock, sign::TradeSignal, bidprice::Function, duration::Date{ISOCalendar}, profit::Function, stopout::Function)
#
#   # stock is called to generate price
#   # sig may or may not be dependent on stock, but in any case is a type that includes truedates element
#   # bidprice is generated from a model
#   # duration is how long the bid is out before expiring
#   # profit is the scaling of profit taking
#   # stopout is a risk management variable
#
#   end


text:
function make_pr_for_new_version(api::GitHub.GitHubAPI,
                                 clone_hostname::HostnameForClones,
                                 repo::GitHub.Repo,
                                 dep_to_current_compat_entry::Dict{Package, Union{Pkg.Types.VersionSpec, Nothing}},
                                 dep_to_current_compat_entry_verbatim::Dict{Package, Union{String, Nothing}},
                                 dep_to_latest_version::Dict{Package, Union{VersionNumber, Nothing}},
                                 deps_with_missing_compat_entry::Set{Package},
                                 pr_list::Vector{GitHub.PullRequest},
                                 pr_titles::Vector{String},
                                 ci_cfg::CIService;
                                 auth::GitHub.Authorization,
                                 env,
                                 keep_existing_compat::Bool,
                                 drop_existing_compat::Bool,
                                 bump_compat_containing_equality_specifier::Bool,
                                 master_branch::Union{DefaultBranch, AbstractString},
                                 subdir::AbstractString,
                                 pr_title_prefix::String,
                                 registries::Vector{Pkg.RegistrySpec})
    original_directory = pwd()
    always_assert(keep_existing_compat || drop_existing_compat)
    for dep in keys(dep_to_current_compat_entry)
        make_pr_for_new_version(api,
                                clone_hostname,
                                repo,
                                dep,
                                dep_to_current_compat_entry,
                                dep_to_current_compat_entry_verbatim,
                                dep_to_latest_version,
                                pr_list,
                                pr_titles,
                                ci_cfg;
                                auth = auth,
                                env = env,
                                master_branch = master_branch,
                                subdir = subdir,
                                keep_existing_compat = keep_existing_compat,
                                drop_existing_compat = drop_existing_compat,
                                bump_compat_containing_equality_specifier = bump_compat_containing_equality_specifier,
                                pr_title_prefix = pr_title_prefix,
                                registries = registries)
    end
    cd(original_directory)
    return nothing
end

function make_pr_for_new_version(api::GitHub.GitHubAPI,
                                 clone_hostname::HostnameForClones,
                                 repo::GitHub.Repo,
                                 dep::Package,
                                 dep_to_current_compat_entry::Dict{Package, Union{Pkg.Types.VersionSpec, Nothing}},
                                 dep_to_current_compat_entry_verbatim::Dict{Package, Union{String, Nothing}},
                                 dep_to_latest_version::Dict{Package, Union{VersionNumber, Nothing}},
                                 pr_list::Vector{GitHub.PullRequest},
                                 pr_titles::Vector{String},
                                 ci_cfg::CIService;
                                 auth::GitHub.Authorization,
                                 env,
                                 keep_existing_compat::Bool,
                                 drop_existing_compat::Bool,
                                 bump_compat_containing_equality_specifier::Bool,
                                 master_branch::Union{DefaultBranch, AbstractString},
                                 subdir::AbstractString,
                                 pr_title_prefix::String,
                                 registries::Vector{Pkg.RegistrySpec})
    original_directory = pwd()
    always_assert(keep_existing_compat || drop_existing_compat)
    parenthetical_in_pr_title = keep_existing_compat && drop_existing_compat
    name = dep.name
    current_compat_entry = dep_to_current_compat_entry[dep]
    current_compat_entry_verbatim = dep_to_current_compat_entry_verbatim[dep]
    latest_version = dep_to_latest_version[dep]
    if !isnothing(latest_version) && !isnothing(current_compat_entry) && latest_version in current_compat_entry
        @info("latest_version in current_compat_entry",
              current_compat_entry,
              latest_version,
              name,
              dep)
    elseif !bump_compat_containing_equality_specifier &&
            !isnothing(current_compat_entry_verbatim) &&
            contains(current_compat_entry_verbatim, '=') &&
            !contains(current_compat_entry_verbatim, '>') &&
            !contains(current_compat_entry_verbatim, '<')
        # To check for an equality specifier (but not an inequality specifier) we look for an equals sign without any
        # symbols used for an inequality specifier that would also include an equals sign. Namely, greater than and
        # less than. Other specifiers containing symbols like ≥ shouldn't parse as containing an equals sign.
        @info("skipping compat entry because it contains an equality specifier",
            current_compat_entry_verbatim,
            name,
            dep)
    else
        if isnothing(latest_version)
            @error("The dependency was not found in any of the registries", name, dep)
            cd(original_directory)
            return nothing
        end
        compat_entry_for_latest_version = generate_compat_entry(latest_version)
        if isnothing(current_compat_entry)
            brand_new_compat = old_compat_to_new_compat(nothing,
                                                        compat_entry_for_latest_version,
                                                        :brandnewentry)
            make_pr_for_new_version(api,
                                    clone_hostname,
                                    compat_entry_for_latest_version,
                                    brand_new_compat,
                                    repo,
                                    dep,
                                    dep_to_current_compat_entry,
                                    dep_to_current_compat_entry_verbatim,
                                    dep_to_latest_version,
                                    pr_list,
                                    pr_titles,
                                    ci_cfg;
                                    auth = auth,
                                    env = env,
                                    keep_or_drop = :brandnewentry,
                                    parenthetical_in_pr_title = false,
                                    master_branch = master_branch,
                                    subdir = subdir,
                                    pr_title_prefix = pr_title_prefix,
                                    registries = registries)
        else
            if drop_existing_compat
                drop_compat = old_compat_to_new_compat(current_compat_entry_verbatim,
                                                       compat_entry_for_latest_version,
                                                       :drop)
                make_pr_for_new_version(api,
                                        clone_hostname,
                                        compat_entry_for_latest_version,
                                        drop_compat,
                                        repo,
                                        dep,
                                        dep_to_current_compat_entry,
                                        dep_to_current_compat_entry_verbatim,
                                        dep_to_latest_version,
                                        pr_list,
                                        pr_titles,
                                        ci_cfg;
                                        auth = auth,
                                        env = env,
                                        keep_or_drop = :drop,
                                        parenthetical_in_pr_title = parenthetical_in_pr_title,
                                        master_branch = master_branch,
                                        subdir = subdir,
                                        pr_title_prefix = pr_title_prefix,
                                        registries = registries)
            end
            if keep_existing_compat
                keep_compat = old_compat_to_new_compat(current_compat_entry_verbatim,
                                                       compat_entry_for_latest_version,
                                                       :keep)
                make_pr_for_new_version(api,
                                        clone_hostname,
                                        compat_entry_for_latest_version,
                                        keep_compat,
                                        repo,
                                        dep,
                                        dep_to_current_compat_entry,
                                        dep_to_current_compat_entry_verbatim,
                                        dep_to_latest_version,
                                        pr_list,
                                        pr_titles,
                                        ci_cfg;
                                        auth = auth,
                                        env = env,
                                        keep_or_drop = :keep,
                                        parenthetical_in_pr_title = parenthetical_in_pr_title,
                                        master_branch = master_branch,
                                        subdir = subdir,
                                        pr_title_prefix = pr_title_prefix,
                                        registries = registries)
            end
        end
    end
    cd(original_directory)
    return nothing
end

@inline function old_compat_to_new_compat(old_compat::String,
                                          new_compat::String,
                                          keep_or_drop::Symbol)::String
    if keep_or_drop == :keep
        return "$(strip(old_compat)), $(strip(new_compat))"
    elseif keep_or_drop == :drop
        return "$(strip(new_compat))"
    else
        throw(ArgumentError("keep_or_drop must be either :keep or :drop"))
    end
end

@inline function old_compat_to_new_compat(old_compat::Nothing,
                                          new_compat::String,
                                          keep_or_drop::Symbol)::String
    return "$(strip(new_compat))"
end

function make_pr_for_new_version(api::GitHub.GitHubAPI,
                                 clone_hostname::HostnameForClones,
                                 compat_entry_for_latest_version::String,
                                 new_compat_entry::String,
                                 repo::GitHub.Repo,
                                 dep::Package,
                                 dep_to_current_compat_entry::Dict{Package, Union{Pkg.Types.VersionSpec, Nothing}},
                                 dep_to_current_compat_entry_verbatim::Dict{Package, Union{String, Nothing}},
                                 dep_to_latest_version::Dict{Package, Union{VersionNumber, Nothing}},
                                 pr_list::Vector{GitHub.PullRequest},
                                 pr_titles::Vector{String},
                                 ci_cfg::CIService;
                                 auth::GitHub.Authorization,
                                 env,
                                 keep_or_drop::Symbol,
                                 parenthetical_in_pr_title::Bool,
                                 master_branch::Union{DefaultBranch, AbstractString},
                                 subdir::AbstractString,
                                 pr_title_prefix::String,
                                 registries::Vector{Pkg.RegistrySpec})
    original_directory = pwd()
    name = dep.name
    if subdir != ""
        subdir_string = " for package $(splitpath(subdir)[end])"
    else
        subdir_string = ""
    end
    always_assert(keep_or_drop == :keep || keep_or_drop == :drop || keep_or_drop == :brandnewentry)
    if keep_or_drop == :keep
        pr_body_keep_or_drop = string("This keeps the compat entries for ",
                                      "earlier versions.\n\n")
    end
    if keep_or_drop == :drop
        pr_body_keep_or_drop = string("This drops the compat entries for ",
                                      "earlier versions.\n\n")
    end
    if keep_or_drop == :brandnewentry
        pr_body_keep_or_drop = string("This is a brand new compat entry. ",
                                      "Previously, you did not have a ",
                                      "compat entry for the ",
                                      "`$(name)` package.\n\n")
    end
    pr_title_parenthetical = generate_pr_title_parenthetical(keep_or_drop,
                                                             parenthetical_in_pr_title)
    if dep_to_current_compat_entry_verbatim[dep] isa Nothing
        new_pr_title = string("$(pr_title_prefix)",
                              "CompatHelper: add new compat entry for ",
                              "\"$(name)\" at version ",
                              "\"$(compat_entry_for_latest_version)\"",
                              "$subdir_string")
        new_pr_body = string("This pull request sets the compat ",
                             "entry for the `$(name)` package ",
                             "to `$(new_compat_entry)`",
                             "$subdir_string.\n\n",
                             "$(pr_body_keep_or_drop)",
                             "Note: I have not tested your package ",
                             "with this new compat entry. ",
                             "It is your responsibility to make sure that ",
                             "your package tests pass before you merge this ",
                             "pull request.\n\n",
                             "Note: Consider registering a new release of your package immediately after ",
                             "merging this PR, as downstream packages ",
                             "may depend on this for tests to pass.")
    else
        new_pr_title = string("$(pr_title_prefix)",
                              "CompatHelper: bump compat for ",
                              "\"$(name)\" to ",
                              "\"$(compat_entry_for_latest_version)\"",
                              "$subdir_string",
                              "$(pr_title_parenthetical)")
        old_compat_entry_verbatim = convert(String, strip(dep_to_current_compat_entry_verbatim[dep]))
        new_pr_body = string("This pull request changes the compat ",
                             "entry for the `$(name)` package ",
                             "from `$(old_compat_entry_verbatim)` ",
                             "to `$(new_compat_entry)`",
                             "$subdir_string.\n\n",
                             "$(pr_body_keep_or_drop)",
                             "Note: I have not tested your package ",
                             "with this new compat entry. ",
                             "It is your responsibility to make sure that ",
                             "your package tests pass before you merge this ",
                             "pull request.")
    end
    if new_pr_title in pr_titles
        @info("An open PR with the title already exists", new_pr_title)
    else
        url_with_auth = "https://x-access-token:$(auth.token)@$(clone_hostname.hostname)/$(repo.full_name).git"
        url_for_ssh = "git@$(clone_hostname.hostname):$(repo.full_name).git"

        tmp_dir = mktempdir(; cleanup = true)
        cd(tmp_dir)

        ssh_private_key_directory = mktempdir(; cleanup = true)
        run(`chmod 700 $(ssh_private_key_directory)`)
        ssh_private_key_filename = joinpath(ssh_private_key_directory, "privatekey")

        my_retry(() -> run(`git clone $(url_with_auth) REPO`))
        cd(joinpath(tmp_dir, "REPO"))
        default_branch = git_get_current_branch()
        master_branch_name = git_decide_master_branch(master_branch,
                                                      default_branch)
        run(`git checkout $(master_branch_name)`)
        new_branch_name = "compathelper/new_version/$(get_random_string())"
        run(`git branch $(new_branch_name)`)
        run(`git checkout $(new_branch_name)`)
        project_file = joinpath(tmp_dir, "REPO", subdir, "Project.toml")
        project = TOML.parsefile(project_file)
        add_compat_section!(project)
        project["compat"][name] = new_compat_entry
        rm(project_file; force = true, recursive = true)
        open(project_file, "w") do io
            TOML.print(io,
                       project;
                       sorted = true,
                       by = key -> (Pkg.Types.project_key_order(key), key))
        end
        set_git_identity(ci_cfg)
        my_retry(() -> run(`git add -A`))
        @info("Attempting to commit...")
        commit_was_success = git_make_commit(; commit_message = new_pr_title)
        if commit_was_success
            @info("Commit was a success")
            my_retry(() -> run(`git push -f origin $(new_branch_name)`) )
            create_new_pull_request(api, repo;
                base_branch = master_branch_name,
                head_branch = new_branch_name,
                title = new_pr_title,
                body = new_pr_body,
                auth,
            )

            COMPATHELPER_PRIV_is_defined = compathelper_priv_is_defined(env)
            @info("Environment variable `COMPATHELPER_PRIV` is defined, is nonempty, and is not the string `false`: $(COMPATHELPER_PRIV_is_defined)")
            if COMPATHELPER_PRIV_is_defined
                COMPATHELPER_PRIV_contents = env["COMPATHELPER_PRIV"]
                COMPATHELPER_PRIV = _decode_ssh_private_key(COMPATHELPER_PRIV_contents)

                rm(ssh_private_key_filename; force = true, recursive = true)
                open(ssh_private_key_filename, "w") do io
                    println(io, COMPATHELPER_PRIV)
                end
                run(`chmod 700 $(ssh_private_key_directory)`)
                run(`chmod 600 $(ssh_private_key_filename)`)

                GIT_SSH_COMMAND = "ssh -i $(ssh_private_key_filename)"

                run(`git remote remove origin`)
                run(`git remote add origin $(url_for_ssh)`)
                run(`git reset --soft "HEAD~1"`)
                git_make_commit(; commit_message = new_pr_title)
                withenv("GIT_SSH_COMMAND" => GIT_SSH_COMMAND) do
                    my_retry(() -> run(`git push -f origin $(new_branch_name)`))
                end
            end
        end
        cd(original_directory)
        rm(ssh_private_key_filename; force = true, recursive = true)
        rm(ssh_private_key_directory; force = true, recursive = true)
        rm(tmp_dir; force = true, recursive = true)
    end
    cd(original_directory)
    return nothing
end


text:
function getdepth(str)
  str = string(str)
  depth = match(r"(UInt\d+)", str)
  if depth == nothing
    println("Error: failed to determine depth from ", str)
    exit(-1)
  end
  if depth[1] == "UInt8"
    rslt = UInt8
  elseif depth[1] == "UInt16"
    rslt = UInt16
  else
    println("Can't handle color depth ", depth[1])
    exit(-1)
  end
  return rslt
end

using Images, ImageCore
args = ARGS
if length(args) < 2
  println("Need at least one input file and one output file.")
  exit(-1)
end

prepped = false
final = nothing
what = nothing
sums = nothing
counter = 0

while length(args) > 1
    filen = shift!(args)
    img = load(filen)
    if img == nothing
      println("Image failed to load.")
      exit(-1)
    end
    println("Loaded ", filen)
    if ~ prepped
        what = getdepth(typeof(img))
        sums = similar(img[1:3, : , : ], Int32)
        sums = view(reinterpret(what, img), 1:3, :, :)
        prepped = true
        print("Set base image\n")
    else
        sums = broadcast(+, sums, view(reinterpret(what, img), 1:3, :, :))
    end
    counter += 1
end

if what == UInt8
    multiplier = 255.0 / counter
else
    multiplier = 1.0 / counter
end
println("Converting for save")
saveit = broadcast(*, sums, multiplier)
saveint = similar(saveit, UInt16)
for I in eachindex(saveit)
#    println(saveit[I])
#    println(floor(saveit[I]))
#    println("---------")
    saveint[I] = convert(UInt16, floor(saveit[I]))
end

#saveint = broadcast(convert(UInt16), saveit)
saveint = colorview(RGB{N0f16}, saveint)

filen = shift!(args)
save(filen, saveint)

max_stars_repo_name: FatherGeoffHorton/AstroTools

max_issues_repo_name: FatherGeoffHorton/AstroTools

max_forks_repo_name: FatherGeoffHorton/AstroTools


text:
# Tutorial de Julia

# 1. Criar variáveis

x = 10
# x

y = -10.5
# y

# 2. Função println
println(x)

println("o valor de x é ", x)

# 2.1 Interpolação de string
println("o valor de x é $(x)")
println("o valor de y é $(y)")

# 3. Coleção de valores
## 3.1 Array
### 3.1.1 Unidimensional Array{Any, 1}
x = [1, 2, 3]
x

### 3.1.2 Bidimensional Array{Any, 2}
X = [1 2 3;
     4 5 6;
     7 8 9]

## 3.2 Fatiamento
### 3.2.1 Unidimensional

x[1] # primeiro valor
x[2] # segundo valor
x[end] # último valor
x[1:2] # do primeiro ao segundo valor
x[2:end] # do segundo ao último valor

### 3.2.2 Bidimensional

X[1,1] # primeira linha, primeira coluna
X[2,1] # segunda linha, primeira coluna
X[:,1] # todas as linhas, primeira coluna
X[1,:] # primeira linha, todas as colunas
X[1:2, 1:2] # primeira e segunda linha e coluna
X[2:end, 1] # da segunda a última linha, primeira coluna
X[2, 2:end] # segunda linha, da segunda a terceira coluna

## 3.3 Operações entre Arrays

#### Criando as arrays unidimensionais
a = [1, 2, 3];
b = [-1, 10, 8];

### Operação com escalares
c = 2

a .+ c
a .- c
a .* c
a ./ c
ggplot(df, aes(x=seq_along(Today), y=Today)) +
geom_line()s unidimensionais

a - b

### 3.3.3 Multiplicação elemento por elemento

a .* b

### 3.3.4 Divisão elemento por elemento

a ./ b

### 3.3.5 Produto interno de dois vetores

### usar o "'" para transpor o vetor
a' * b

### 3.3.6 Produto externo de dois vetores
a * b'

# 4. Importação/Exportação de dados
using CSV

# 5. Manipulação de dados
using DataFrames

# 6. Visualizações
using Gadfly
using VegaLite

### Importar a base de dados
df = CSV.read("data/Smarket.csv", DataFrame)

#### Visualizar as primeiras linhas
first(df, 6)

#### salvar base de dados em .csv
# CSV.write("data/Smarket.csv", df)

### Gráfico de linha
# linha
plot(df, y=:Today, Geom.line)

### Gráfico de dispersão
# Gadfly
plot(df, x=:Year, y=:Today, Geom.point)

### Gráfico de dispersão com grupos
plot(df, color=:Direction, x=:Year, y=:Today, Geom.point)
df |> @vlplot(:point, x={"Year:t", axis={format="%Y"}}, y=:Today, color=:Direction)

### Com Grid
plot(df, color=:Direction, xgroup=:Direction, x=:Year, y=:Today,
     Geom.subplot_grid(Geom.point))

## Com x sendo contínuo
x = 1:nrow(df)
plot(df, color=:Direction, x=x, y=:Today, Geom.point)

### Testando aqui umas paradas

@select(df, :Today)
@where(df, :Year .> 2004)

x_thread = @linq df |>
    transform(y = 100 * :Today) |>
    where(:Year .> 2003) |>
    by(:Direction, meanLag1 = mean(:Lag1), meanLag2 = mean(:Lag2), meanToday = mean(:y)) |>
    orderby(:meanLag1) |>
    select(:meanLag1, :meanLag2, :meanToday, var =:Direction)


text:
using Random: randn

@testset "self-coherence" begin
    N, M = 1024, 128
    t = 1:N
    X = zeros(Float64, N, M)
    for i in 1:M
        X[:,i] = sin.(2pi*t/50) + randn(N)
    end
    wt = ContinuousWaveletTransform(CauchyWavelet(10), [50])
    C = coherence(wt, X; nsurrogate=1)
    @test sum(abs.(C)[:,1])/N ≈ 1.0 atol=1e-1
end

@testset "cross-coherence" begin
    N, M = 1024, 128
    t = 1:N
    X = zeros(Float64, N, M)
    Y = zeros(Float64, N, M)
    for i in 1:M
        X[:,i] = sin.(2pi*t/50) + randn(N)
        Y[:,i] = cos.(2pi*t/50) + randn(N)
    end
    wt = ContinuousWaveletTransform(CauchyWavelet(10), [50])
    C = coherence(wt, X, Y, nsurrogate=1)
    @test sum(abs.(C)[:,1])/N ≈ 1.0 atol=1e-1
end


text:
# Code from @devmotion
# https://github.com/devmotion/\
# CalibrationErrorsDistributions.jl/blob/main/src/distances/bures.jl

"""
    tr_sqrt(A::AbstractMatrix)

Compute ``\\operatorname{tr}\\big(A^{1/2}\\big)``.
"""
tr_sqrt(A::AbstractMatrix) = LinearAlgebra.tr(sqrt(A))
tr_sqrt(A::PDMats.PDMat) = tr_sqrt(A.mat)
tr_sqrt(A::PDMats.PDiagMat) = sum(sqrt, A.diag)
tr_sqrt(A::PDMats.ScalMat) = A.dim * sqrt(A.value)

"""
    _gaussian_ot_A(A::AbstractMatrix, B::AbstractMatrix)

Compute
```math
A^{1/2} B A^{1/2}.
```
"""
function _gaussian_ot_A(A::AbstractMatrix, B::AbstractMatrix)
    sqrt_A = sqrt(A)
    return sqrt_A * B * sqrt_A
end
function _gaussian_ot_A(A::PDMats.PDiagMat, B::AbstractMatrix)
    return sqrt.(A.diag) .* B .* sqrt.(A.diag')
end
function _gaussian_ot_A(A::StridedMatrix, B::PDMats.PDMat)
    return PDMats.X_A_Xt(B, sqrt(A))
end
_gaussian_ot_A(A::PDMats.PDMat, B::PDMats.PDMat) = _gaussian_ot_A(A.mat, B)
_gaussian_ot_A(A::AbstractMatrix, B::PDMats.PDiagMat) = _gaussian_ot_A(B, A)
_gaussian_ot_A(A::PDMats.PDMat, B::StridedMatrix) = _gaussian_ot_A(B, A)

"""
    sqbures(A::AbstractMatrix, B::AbstractMatrix)

Compute the squared Bures metric
```math
\\operatorname{tr}(A) + \\operatorname{tr}(B)
- \\operatorname{tr}\\Big({\\big(A^{1/2} B A^{1/2}\\big)}^{1/2}\\Big).
```
"""
function sqbures(A::AbstractMatrix, B::AbstractMatrix)
    return LinearAlgebra.tr(A) + LinearAlgebra.tr(B) - 2 * tr_sqrt(_gaussian_ot_A(A, B))
end

# diagonal matrix
function sqbures(A::PDMats.PDiagMat, B::PDMats.PDiagMat)
    if !(A.dim == B.dim)
        throw(ArgumentError("matrices must have the same dimensions."))
    end
    return sum(zip(A.diag, B.diag)) do (x, y)
        abs2(sqrt(x) - sqrt(y))
    end
end

# scaled identity matrix
function sqbures(A::PDMats.ScalMat, B::AbstractMatrix)
    return LinearAlgebra.tr(A) + LinearAlgebra.tr(B) - 2 * sqrt(A.value) * tr_sqrt(B)
end
sqbures(A::AbstractMatrix, B::PDMats.ScalMat) = sqbures(B, A)
sqbures(A::PDMats.ScalMat, B::PDMats.ScalMat) = A.dim * abs2(sqrt(A.value) - sqrt(B.value))

# combinations
function sqbures(A::PDMats.PDiagMat, B::PDMats.ScalMat)
    sqrt_B = sqrt(B.value)
    return sum(A.diag) do x
        abs2(sqrt(x) - sqrt_B)
    end
end
sqbures(A::PDMats.ScalMat, B::PDMats.PDiagMat) = sqbures(B, A)


text:
function _precompile_()
    ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Float16})   # time: 0.122194625
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Int8}})   # time: 0.08191741
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{UInt64}})   # time: 0.0809642
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Float32})   # time: 0.07822956
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Int32}})   # time: 0.077332
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Float64}})   # time: 0.077093035
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{UInt16}})   # time: 0.07661847
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Float16}})   # time: 0.07633699
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Char}})   # time: 0.076307364
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{String}})   # time: 0.075568676
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Int64}})   # time: 0.071211986
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{UInt8}})   # time: 0.066093676
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{UInt32}})   # time: 0.06573274
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Int16}})   # time: 0.06534618
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Float32}})   # time: 0.065121405
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Matrix{Bool}})   # time: 0.06482868
    Base.precompile(Tuple{Core.kwftype(typeof(pretty_table)),NamedTuple{(:alignment, :crop), Tuple{Symbol, Symbol}},typeof(pretty_table),Vector{Any}})   # time: 0.06120646
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Float64})   # time: 0.051268853
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{UInt64}})   # time: 0.035136133
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Float64}})   # time: 0.0336968
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{UInt8}})   # time: 0.032657966
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Tuple{Int64, Int64}})   # time: 0.028840367
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{UInt16}})   # time: 0.024657313
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{UInt32}})   # time: 0.023751128
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Float32}})   # time: 0.023440607
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Float16}})   # time: 0.0233361
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Int16}})   # time: 0.023233492
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Int8}})   # time: 0.023119511
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Bool}})   # time: 0.022458337
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Int32}})   # time: 0.022436554
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Int64}})   # time: 0.019929262
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{String}})   # time: 0.012381854
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Vector{Char}})   # time: 0.012368943
    Base.precompile(Tuple{typeof(_print_table_data),IOContext{IOBuffer},Display,Any,Matrix{Vector{String}},Vector{Int64},Vector{Int64},Int64,Vector{Int64},Vector{Int64},Vector{NTuple{4, Int64}},Vector{Int64},Vector{Symbol},NTuple{4, Char},Dict{Tuple{Int64, Int64}, Symbol},Symbol,Int64,Ref{Any},Bool,Bool,Bool,TextFormat,Crayon,Crayon,Crayon})   # time: 0.012022515
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Int64})   # time: 0.010344721
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Int16})   # time: 0.009935756
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Symbol})   # time: 0.009475924
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Int8})   # time: 0.009024752
    Base.precompile(Tuple{typeof(compact_type_str),DataType})   # time: 0.008718151
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),String})   # time: 0.008309719
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Bool})   # time: 0.008068463
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),UInt16})   # time: 0.00798423
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),UInt64})   # time: 0.00773642
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),UInt32})   # time: 0.007675963
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Char})   # time: 0.007666415
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),UInt8})   # time: 0.007640698
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Int32})   # time: 0.00760978
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_first_line_only, :column_width, :compact_printing, :linebreaks, :renderer), Tuple{Bool, Bool, Int64, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),String})   # time: 0.006261887
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),Symbol})   # time: 0.0035132
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),String})   # time: 0.003314562
    Base.precompile(Tuple{Core.kwftype(typeof(_parse_cell_text)),NamedTuple{(:autowrap, :cell_data_type, :cell_first_line_only, :column_width, :compact_printing, :has_color, :limit_printing, :linebreaks, :renderer), Tuple{Bool, DataType, Bool, Int64, Bool, Bool, Bool, Bool, Val{:print}}},typeof(_parse_cell_text),URLTextCell})   # time: 0.00290511
    Base.precompile(Tuple{typeof(_compute_cell_alignment_override),Matrix{Any},Vector{Int64},Vector{Int64},Int64,Int64,Int64,Base.RefValue{Any}})   # time: 0.00274682
    Base.precompile(Tuple{typeof(_compute_cell_alignment_override),ColumnTable,Vector{Int64},Vector{Int64},Int64,Int64,Int64,Base.RefValue{Any}})   # time: 0.00266063
    Base.precompile(Tuple{typeof(_compute_cell_alignment_override),Vector{Any},Vector{Int64},Vector{Int64},Int64,Int64,Int64,Base.RefValue{Any}})   # time: 0.002646816
end


text:
using Test
using ReinforcementLearning

@testset "ReinforcementLearning" begin end


text:
"""
    diff(t::Tuple)

For a tuple of length N, return a tuple of length N-1
where element i is t[i+1] - t[i].
"""
function Base.diff(t::NTuple{N}) where N
  return ntuple(i -> t[i+1] - t[i], Val(N-1))
end


text: eye(args...)

max_stars_repo_name: Alfheim/node-julia

max_issues_repo_name: Alfheim/node-julia

max_forks_repo_name: Alfheim/node-julia


text:
# HW9 Econ 136 Spring 2018
# Monte-Carlo simulator
# /Applications/Julia-0.6.app/Contents/Resources/julia/bin/julia ~/Documents/projects/ECON136/monte_carlo_stu/monte_carlo_stu.jl

using PyPlot
using Distributions

# This below shows how to use numpy's random sampler that draws from a
# standard normal distribution (mean 0, SD 1).
# Checking here to see if this numpy random sampler is any good.
sam_size = 252
rsample = zeros(sam_size)

for i in range(1, sam_size)
    rsample[i] = randn()
end

center = mean(rsample)
spread = std(rsample)

println("The mean should be close to zero, the spread close to one: ")
println("Mean : ", center)
println("Spread :", spread)

# Now build the simulator. Start with drift and volatility assumptions.
drift = 0.00356
sigma = 0.037874
start_price = 12.0
sims = 10
days = 252
#span = 3
#alpha = 2/(1+span)
#days_after = [0.0 for i in 0:span+1]
#days_after[1] = 4.0
#days_after[4] = 1.0
#for i in range(2, span)
#    days_after[i] = days_after[i-1]*exp(-0.34657359*i)
#end
# println(days_after)

# The monte-carlo estimator
out_su = range(0, (sims+1)*days)
out_su = reshape(out_su, (sims+1,days)) # for col domination, order='F' ?C
price = zeros(Float64, size(out_su))
#
for i in range(1, sims+1)
    price[i,1] = start_price
end
# println(price)

for j in range(2, days-1)
    price[1,j] = price[1, j-1]*exp(drift) # Computes the drift only portion
end

for i in range(2, sims+1)  # rows (each a different simulation)
    for j in range(2, days-1)    # cols (each a new day!)
        # And below is where you replace the placeholder with the Monte Carlo equation.
        price[i,j] = price[i,j-1]*exp(drift + sigma*randn())
    end
end
# sns.set_style("darkgrid")
# cbcbgres = ['#edf8e9','#c7e9c0','#a1d99b','#74c476','#41ab5d','#238b45','#005a32']
# cbcbgres = cbcbgres[::-1]
# cbcbreds = ['#fee5d9','#fcbba1','#fc9272','#fb6a4a','#ef3b2c','#cb181d','#99000d']
# cbcbreds = cbcbreds[::-1]
# cbcbblus = ['#eff3ff','#c6dbef','#9ecae1','#6baed6','#4292c6','#2171b5','#084594']
# cbcbblus = cbcbblus[::-1]
# cbcbgras = ['#f7f7f7','#d9d9d9','#bdbdbd','#969696','#737373','#525252','#252525']
# cbcbgras = [::-1]

fig = figure("lineplot", figsize=(10,10))
for i in range(1, sims+1)
    if i == sims+1
        plot(price[i,:], label = "Drift Only")
    else
        plot(price[i,:], label = "Drift+Sigma " * string(i))
    end
end

# println(price)

# df = pd.DataFrame({'B': [4, 2, 1]})
# print(pd.ewma(df, com = 1))
ylabel("Prices")
xlabel("Days")
legend()
show()
#
println("Done")
# Plot the result.


text:
"""
Problem: 120-bit sparse subset

Let a 120-bit string be b = [b_1|b_2|···|b_20], where b_i, i = 1, 2, ..., 20 are
six-bit substrings referred to as blocks. Define the sequence `000001` to be
the target configuration for a block, and denote this configuration by b_t.
The objective function is defined such that the optimal solution is
b* = [b_t|b_t|···|b_t], that is, the string with all 20 blocks having the target
configuration.

This solution can be expressed as the index vector v* = [6, 12, 18,...,120].
"""

using Evolutionary, Test, Random

function fitness(oset, bsize = 6)
    scores = Dict(i => (i != bsize ? 3i : 20) for i in 0:bsize)
    # count 1s in blocks
    ht = Dict{Int,Int}()
    sl = sr = 0
    for i in oset
        if i > 60
            sr += 1
        else
            sl += 1
        end
        blk = div(i, bsize)
        blk -= i % bsize == 0 ? 1 : 0
        if haskey(ht, blk)
            ht[blk] += 1
        else
            ht[blk] = 1
        end
    end
    # calculate total score
    ss = 0
    for blk in sort(collect(keys(ht)))
        cnt = ht[blk]
        if cnt == 7
            println(oset)
            println(ht)
            error("Problem")
        end
        ss += scores[cnt]
        if (cnt == 1) && ((blk+1)*bsize in oset)
            ss += 9
        end
        #println("$blk, $cnt, $(scores[cnt]), $ss")
    end
    ss -= 2(sl > 13 ? sl : 0)
    ss -= 2(sr > 13 ? sr : 0)
    ss
end

# Bit string examples
bstr = "000100 001010 000010 111111 000100 101000 000010 000000 000001 000000 000010 000001 001000 000000 000000 010000 000000 000010 000000 000000"
idxs = [i for (i,j) in enumerate(filter(c->c != ' ', bstr)) if j == '1']
@test fitness(idxs) == 50

# optimal solution
idxs_opt = [6*i for i in 1:20]
@test fitness(idxs_opt) == 240

# GA solution
mthd = GA(populationSize = 100, selection = tournament(5),
          crossover = SSX, crossoverRate = 0.99,
          mutation  = replace(collect(1:120)), mutationRate = 0.1)

Random.seed!(42)
opts = Evolutionary.Options(show_trace=false, successive_f_tol=30)
init_pop = ()->randperm(120)[1:20]
res = Evolutionary.optimize(idxs->-fitness(idxs), init_pop, mthd, opts)
println(res)
Evolutionary.minimizer(res) |> sort


text:
using PairArithmetic, Test

@test true


text:
mutable struct PublishDiagnosticsParams
    uri::String
    diagnostics::Vector{Diagnostic}
end

mutable struct MarkedString
    language::String
    value::AbstractString
end

mutable struct CompletionItem
    label::String
    kind::Int
    documentation::Union{String,MarkedString}
    textEdit::TextEdit
    additionalTextEdits::Vector{TextEdit}
end

mutable struct CompletionList
    isIncomplete::Bool
    items::Vector{CompletionItem}
end

mutable struct Hover
    contents::Vector{Union{AbstractString,MarkedString}}
end

mutable struct ParameterInformation
    label::String
    #documentation::String
end

mutable struct SignatureInformation
    label::String
    documentation::Union{String,MarkedString}
    parameters::Vector{ParameterInformation}
end

mutable struct SignatureHelp
    signatures::Vector{SignatureInformation}
    activeSignature::Int
    activeParameter::Int
end

mutable struct SignatureHelpRegistrationOptions end

@json_read mutable struct ReferenceContext
    includeDeclaration::Bool
end

@json_read mutable struct ReferenceParams
    textDocument::TextDocumentIdentifier
    position::Position
    context::ReferenceContext
end

mutable struct DocumentHighlight
    range::Range
    kind::Integer
end

# Document Symbols Provider
@json_read mutable struct DocumentSymbolParams
    textDocument::TextDocumentIdentifier
end

mutable struct SymbolInformation
    name::String
    kind::Int
    deprecated::Union{Nothing,Bool}
    location::Location
    containername::Union{Nothing,String}
end

@json_read mutable struct WorkspaceSymbolParams
    query::String
end

# const CompletionItemKind = Dict("Text" => 1,
#                                 "Method" => 2,
#                                 "Function" => 3,
#                                 "Constructor" => 4,
#                                 "Field" => 5,
#                                 "Variable" => 6,
#                                 "Class" => 7,
#                                 "Interface" => 8,
#                                 "Module" => 9,
#                                 "Property" => 10,
#                                 "Unit" => 11,
#                                 "Value" => 12,
#                                 "Enum" => 13,
#                                 "Keyword" => 14,
#                                 "Snippet" => 15,
#                                 "Color" => 16,
#                                 "File" => 17,
#                                 "Reference" => 18)

MarkedString(x) = MarkedString("julia", string(x))
Base.hash(x::MarkedString) = hash(x.value) # for unique

# Make more specific if we extend completions (i.e. brackets for functions w/ arg placements)
import Base.==
==(x::CompletionItem, y::CompletionItem) = x.label == y.label
==(m1::MarkedString, m2::MarkedString) = m1.language == m2.language && m1.value == m2.value

# ReferenceContext(d::Dict) = ReferenceContext(d["includeDeclaration"] == "true")
# ReferenceParams(d::Dict) = ReferenceParams(TextDocumentIdentifier(d["textDocument"]), Position(d["position"]), ReferenceContext(d["context"]))
# DocumentSymbolParams(d::Dict) = DocumentSymbolParams(TextDocumentIdentifier(d["textDocument"]))

# const SymbolKind = Dict("File" => 1,
#                         "Module" => 2,
#                         "Namespace" => 3,
#                         "Package" => 4,
#                         "Class" => 5,
#                         "Method" => 6,
#                         "Property" => 7,
#                         "Field" => 8,
#                         "Constructor" => 9,
#                         "Enum" => 10,
#                         "Interface" => 11,
#                         "Function" => 12,
#                         "Variable" => 13,
#                         "Constant" => 14,
#                         "String" => 15,
#                         "Number" => 16,
#                         "Boolean" => 17,
#                         "Array" => 18)

@json_read mutable struct CodeActionContext
    diagnostics::Vector{Diagnostic}
end

@json_read mutable struct CodeActionParams
    textDocument::TextDocumentIdentifier
    range::Range
    context::CodeActionContext
end

# Code Lens
@json_read mutable struct CodeLensParams
    textDocument::TextDocumentIdentifier
end

mutable struct CodeLens
    range::Range
    command::Command
    data::Any
end

@json_read mutable struct CodeLensRegistrationOptions
    resolveProvider::Bool
end

# Document Link Provider

@json_read mutable struct DocumentLinkParams
    textDocument::TextDocumentIdentifier
end

mutable struct DocumentLink
    range::Range
    target::String
end

@json_read mutable struct FormattingOptions
    tabSize::Integer
    insertSpaces::Bool
end

@json_read mutable struct DocumentFormattingParams
    textDocument::TextDocumentIdentifier
    options::FormattingOptions
end

@json_read mutable struct DocumentRangeFormattingParams
    textDocument::TextDocumentIdentifier
    range::Range
    options::FormattingOptions
end

@json_read mutable struct DocumentOnTypeFormattingParams
    textDocument::TextDocumentIdentifier
    position::Position
    ch::String
    options::FormattingOptions
end

@json_read mutable struct DocumentOnTypeFormattingRegistrationOptions
    documentSelector::DocumentSelector
    firstTriggerCharacter::String
    moreTriggerCharacer::Vector{String}
end

@json_read mutable struct RenameParams
    textDocument::TextDocumentIdentifier
    position::Position
    newName::String
end

@json_read mutable struct ExecuteCommandParams
    command::String
    arguments::Vector{Any}
end

@json_read mutable struct ExecuteCommandRegistrationOptions
    commands::Vector{String}
end

@json_read mutable struct ApplyWorkspaceEditParams
    label::Union{Nothing,String}
    edit::WorkspaceEdit
end

@json_read mutable struct ApplyWorkspaceEditResponse
    applied::Bool
end

# WorkspaceSymbolParams(d::Dict) = WorkspaceSymbolParams(d["query"])
# CodeActionContext(d::Dict) = CodeActionContext(Diagnostic.(d["diagnostics"]))
# CodeActionParams(d::Dict) = CodeActionParams(TextDocumentIdentifier(d["textDocument"]), Range(d["range"]), CodeActionContext(d["context"]))
# CodeLensParams(d::Dict) = CodeLensParams(TextDocumentIdentifier(d["textDocument"]))
# DocumentLinkParams(d::Dict) = DocumentLinkParams(TextDocumentIdentifier(d["textDocument"]))
# FormattingOptions(d::Dict) = FormattingOptions(d["tabSize"], d["insertSpaces"])
# DocumentFormattingParams(d::Dict) = DocumentFormattingParams(TextDocumentIdentifier(d["textDocument"]), FormattingOptions(d["options"]))
# RenameParams(d::Dict) = RenameParams(TextDocumentIdentifier(d["textDocument"]), Position(d["position"]), d["newName"])
# ApplyWorkspaceEditResponse(d::Dict) = ApplyWorkspaceEditResponse(d["applied"])


text:
"""
    jpeg_decode([T,] filename::AbstractString; kwargs...) -> Matrix{T}
    jpeg_decode([T,] io::IO; kwargs...) -> Matrix{T}
    jpeg_decode([T,] data::Vector{UInt8}; kwargs...) -> Matrix{T}

Decode the JPEG image as colorant matrix. The source data can be either a filename, an IO
, or an in-memory byte sequence.

# parameters

- `transpose::Bool`: whether we need to permute the image's width and height dimension
  before encoding. The default value is `false`.
- `scale_ratio::Real`: scale the image by ratio `scale_ratio` in `M/8` with `M ∈ 1:16`. The
  default value is `1`. For values are not in the range, they will be mapped to the nearest
  value, e.g., `0.3 => 2/8` and `0.35 => 3/8`. `scale_ratio` and `preferred_size` may not be
  used together.
- `preferred_size::Tuple`: infer the minimal `scale_ratio` that `all(size(out) .>=
  preferred_size))` holds. It can optionally be `(op, preferred_size)` format, with compare
  operation `op` be one of `>`, `>=`, `<` or `<=`. If `op in (>=, >)` then it gets the
  minimal `scale_ratio`, otherwise it gets the maximum `scale_ratio` for `op in (<=, <)`.
  `scale_ratio` and `preferred_size` may not be used together. The `preferred_size`
  dimensions are not affected by keyword `transpose`.

# Examples

```jldoctest
julia> using JpegTurbo, TestImages, ImageCore

julia> filename = testimage("earth", download_only=true);

julia> img = jpeg_decode(filename); summary(img)
"3002×3000 Array{RGB{N0f8},2} with eltype RGB{N0f8}"

julia> img = jpeg_decode(Gray, filename; scale_ratio=0.25); summary(img)
"751×750 Array{Gray{N0f8},2} with eltype Gray{N0f8}"
```

For image preview and similar purposes, `T` and `scale_ratio` are useful parameters to
accelerate the JPEG decoding process. For color JPEG image, `jpeg_decode(Gray, filename)` is
faster than `jpeg_decode(filename)` since the color components need not be processed.
Smaller `scale_ratio` permits significantly faster decoding since fewer pixels need be
processed and a simpler IDCT method can be used.

```julia
using BenchmarkTools, TestImages, JpegTurbo
filename = testimage("earth", download_only=true)
# full decompression
@btime jpeg_decode(filename); # 224.760 ms (7 allocations: 51.54 MiB)
# only decompress luminance component
@btime jpeg_decode(Gray, filename); # 91.157 ms (6 allocations: 17.18 MiB)
# process only a few pixels
@btime jpeg_decode(filename; scale_ratio=0.25); # 77.254 ms (8 allocations: 3.23 MiB)
# process only a few pixels for luminance component
@btime jpeg_decode(Gray, filename; scale_ratio=0.25); # 63.119 ms (6 allocations: 1.08 MiB)
```

"""
function jpeg_decode(
        ::Type{CT},
        data::Vector{UInt8};
        transpose=false,
        scale_ratio::Union{Nothing,Real}=nothing,
        preferred_size::Union{Nothing,Tuple}=nothing) where CT<:Colorant
    _jpeg_check_bytes(data)
    out_CT, jpeg_cls = _jpeg_out_color_space(CT)

    cinfo_ref = Ref(LibJpeg.jpeg_decompress_struct())
    jerr = Ref{LibJpeg.jpeg_error_mgr}()
    try
        cinfo = cinfo_ref[]
        cinfo.err = LibJpeg.jpeg_std_error(jerr)
        LibJpeg.jpeg_create_decompress(cinfo_ref)
        LibJpeg.jpeg_mem_src(cinfo_ref, data, length(data))
        LibJpeg.jpeg_read_header(cinfo_ref, true)

        # set decompression parameters, if given
        if !isnothing(preferred_size) && !transpose
            if preferred_size[1] isa Function
                preferred_size = (preferred_size[1], reverse(preferred_size[2]))
            else
                preferred_size = reverse(preferred_size)
            end
        end
        r = _cal_scale_ratio(scale_ratio, preferred_size, cinfo)
        cinfo.scale_num, cinfo.scale_denom = r.num, r.den
        cinfo.out_color_space = jpeg_cls

        # eagerly calculate dimension information so that `output_XXX` fields are valid.
        LibJpeg.jpeg_calc_output_dimensions(cinfo_ref)
        out_size = (Int(cinfo.output_width), Int(cinfo.output_height))
        if !all(x -> x<=65535, out_size)
            error("Suspicious inferred image size $out_size: each dimension is expected to have at most 65535 pixels.")
        end
        out_ndims = Int(cinfo.output_components)
        @assert out_ndims == length(out_CT) "Suspicous output color space: $cinfo.out_color_space"

        out = Matrix{out_CT}(undef, out_size)
        _jpeg_decode!(out, cinfo_ref)

        if out_CT <: CT
            return transpose ? out : permutedims(out, (2, 1))
        else
            return transpose ? CT.(out) : CT.(PermutedDimsArray(out, (2, 1)))
        end
    finally
        LibJpeg.jpeg_destroy_decompress(cinfo_ref)
    end
end
jpeg_decode(data; kwargs...) = jpeg_decode(_default_out_color_space(data), data; kwargs...)

# TODO(johnnychen94): support Progressive JPEG
# TODO(johnnychen94): support partial decoding
function jpeg_decode(::Type{CT}, filename::AbstractString; kwargs...) where CT<:Colorant
    open(filename, "r") do io
        jpeg_decode(CT, io; kwargs...)
    end
end
jpeg_decode(filename::AbstractString; kwargs...) = jpeg_decode(read(filename); kwargs...)

jpeg_decode(io::IO; kwargs...) = jpeg_decode(read(io); kwargs...)
jpeg_decode(::Type{CT}, io::IO; kwargs...) where CT<:Colorant = jpeg_decode(CT, read(io); kwargs...)

function _jpeg_decode!(out::Matrix{<:Colorant}, cinfo_ref::Ref{LibJpeg.jpeg_decompress_struct})
    row_stride = size(out, 1) * length(eltype(out))
    buf = Vector{UInt8}(undef, row_stride)
    buf_ref = Ref(pointer(buf))
    out_uint8 = reinterpret(UInt8, out)

    cinfo = cinfo_ref[]
    LibJpeg.jpeg_start_decompress(cinfo_ref)
    while cinfo.output_scanline < cinfo.output_height
        # TODO(johnnychen94): try if we can directly write to `out` without using `buf`
        GC.@preserve buf LibJpeg.jpeg_read_scanlines(cinfo_ref, buf_ref, 1)
        copyto!(out_uint8, (cinfo.output_scanline-1) * row_stride + 1, buf, 1, row_stride)
    end
    LibJpeg.jpeg_finish_decompress(cinfo_ref)

    return out
end

_jpeg_decode!(out::Matrix{<:Colorant}, cinfo::LibJpeg.jpeg_decompress_struct) = _jpeg_decode!(out, Ref(cinfo))

# libjpeg-turbo only supports ratio M/8 with M from 1 to 16
const _allowed_scale_ratios = ntuple(i->i//8, 16)
function _cal_scale_ratio(::Real, ::Tuple, cinfo)
    throw(ArgumentError("Keywords `aspect_ratio` and `preferred_size` are exclusive to each other: you should only specify one of them."))
end
_cal_scale_ratio(::Nothing, ::Nothing, cinfo) = 1//1
_cal_scale_ratio(r::Real, ::Nothing, cinfo) = _allowed_scale_ratios[findmin(x->abs(x-r), _allowed_scale_ratios)[2]]
function _cal_scale_ratio(::Nothing, preferred_size::Tuple, cinfo)
    cinfo.scale_num, cinfo.scale_denom = 1, 1
    LibJpeg.jpeg_calc_output_dimensions(Ref(cinfo))
    out_size = (Int(cinfo.output_width), Int(cinfo.output_height))
    op, preferred_size = if preferred_size[1] isa Function
        op = preferred_size[1]
        op in (>, >=, <, <=) || throw(ArgumentError("the compare operation must be one of `>`, `>=`, `<` and `<=`."))
        op, preferred_size[2]
    else
        >=, preferred_size
    end
    if op in (>, >=)
        idx = findfirst(x->all(op.(x .* out_size, preferred_size)), _allowed_scale_ratios)
        if isnothing(idx)
            @warn "Failed to infer appropriate scale ratio, use `scale_ratio=2` instead." actual_size=out_size preferred_size
            idx = length(_allowed_scale_ratios)
        end
    elseif op in (<, <=)
        idx = findlast(x->all(op.(x .* out_size, preferred_size)), _allowed_scale_ratios)
        if isnothing(idx)
            @warn "Failed to infer appropriate scale ratio, use `scale_ratio=1/8` instead." actual_size=out_size preferred_size
            idx = 1
        end
    end
    return _allowed_scale_ratios[idx]
end

function _default_out_color_space(data::Vector{UInt8})
    _jpeg_check_bytes(data)
    cinfo_ref = Ref(LibJpeg.jpeg_decompress_struct())
    try
        jerr = Ref{LibJpeg.jpeg_error_mgr}()
        cinfo_ref[].err = LibJpeg.jpeg_std_error(jerr)
        LibJpeg.jpeg_create_decompress(cinfo_ref)
        LibJpeg.jpeg_mem_src(cinfo_ref, data, length(data))
        LibJpeg.jpeg_read_header(cinfo_ref, true)
        LibJpeg.jpeg_calc_output_dimensions(cinfo_ref)
        return jpeg_color_space(cinfo_ref[].out_color_space)
    finally
        LibJpeg.jpeg_destroy_decompress(cinfo_ref)
    end
end

function _jpeg_out_color_space(::Type{CT}) where CT
    try
        n0f8(CT), jpeg_color_space(n0f8(CT))
    catch e
        @debug "Unsupported libjpeg-turbo color space, fallback to RGB{N0f8}" e
        RGB{N0f8}, jpeg_color_space(RGB{N0f8})
    end
end

# provides some basic integrity check
# TODO(johnnychen94): redirect libjpeg-turbo error to julia
_jpeg_check_bytes(filename::AbstractString) = open(_jpeg_check_bytes, filename, "r")
function _jpeg_check_bytes(io::IO)
    seekend(io)
    nbytes = position(io)
    nbytes > 623 || throw(ArgumentError("Invalid number of bytes."))

    buf = UInt8[]
    seekstart(io)
    readbytes!(io, buf, 623)
    seek(io, nbytes-2)
    append!(buf, read(io, 2))
    return _jpeg_check_bytes(buf)
end
function _jpeg_check_bytes(data::Vector{UInt8})
    length(data) > 623 || throw(ArgumentError("Invalid number of bytes."))
    data[1:2] == [0xff, 0xd8] || throw(ArgumentError("Invalid JPEG byte sequence."))
    data[end-1:end] == [0xff, 0xd9] || @warn "Premature end of JPEG byte sequence."
    return true
end


text:
# MonoidAlternative
# =================

# orelse
@test Either{String, Int}("hi") ⊘ Either{String, Int}(1) == Either{String, Int}(1)
@test Either{String, Int}("hi") ⊘ Either{String, Int}("ho") == Either{String, Int}("ho")
@test Either{String, Int}(1) ⊘ Either{String, Int}(4) == Either{String, Int}(1)

# combine
@test_throws MethodError Either{Int}(true) ⊕ Either{Int}("ho")
@test Either{Int, String}("hi") ⊕ Either{Int, String}("ho") == Either{Int, String}("hiho")
@test Either{String, Int}("hi") ⊕ Either{String, Int}("ho") == Either{String, Int}("hiho")

# FunctorApplicativeMonad
# =======================

@test map(Either{String}(3)) do x
  x * x
end == Either{String}(9)

@test map(Either{String, Int}("hi")) do x
  x * x
end == Either{String, Int}("hi")

@test mapn(Either{String, Int}(2), Either{String, Int}("ho")) do x, y
  x + y
end == Const("ho")
# TODO we loose type information here, however it is tough to infer through the generic curry function constructed by mapn

@test mapn(Either{String, Int}("hi"), Either{String, Int}(3)) do x, y
  x + y
end == Const("hi")

@test mapn(Either{String, Int}("hi"), Either{String, Int}("ho")) do x, y
  x + y
end == Const("hi")

he = @syntax_flatmap begin
  a = Either{String, Int}(2)
  b = Either{String, Int}(4)
  @pure a + b
end
@test he == Either{String}(6)

h = @syntax_flatmap begin
  a = Either{String, Int}("hi")
  b = Either{String, Int}(4)
  @pure a + b
end
@test h == Either{String, Int}("hi")

h = @syntax_flatmap begin
  a = Either{String, Int}(2)
  b = Either{String, Int}("ho")
  @pure a + b
end
@test h == Either{String, Int}("ho")

@test pure(Either{String}, 3) == Identity(3)
@test pure(Either, 3) == Identity(3)

# FlipTypes
# =========

@test flip_types(Const([1,2,3])) == Const.([1,2,3])
@test flip_types(Identity([1,2,3])) == Identity.([1,2,3])


text:
doc"""
apply Hodrick-Prescott filter to `AbstractVector`.

##### Arguments
- `y::AbstractVector` : data to be detrended
- `λ::Real` : penalty on variation in trend

##### Returns
- `y_cyclical::Vector`: cyclical component
- `y_trend::Vector`: trend component
"""
function hp_filter(y::AbstractVector{T}, λ::Real) where T <: Real
    y = Vector(y)
    N = length(y)
    H = spdiagm(-2 => fill(λ, N-2),
                -1 => vcat(-2λ, fill(-4λ, N - 3), -2λ),
                 0 => vcat(1 + λ, 1 + 5λ, fill(1 + 6λ, N-4),
                           1 + 5λ, 1 + λ),
                 1 => vcat(-2λ, fill(-4λ, N - 3), -2λ),
                 2 => fill(λ, N-2))
    y_trend = H \ y
    y_cyclical = y - y_trend
    return y_cyclical, y_trend
end

doc"""
This function applies "Hamilton filter" to `AbstractVector`.

http://econweb.ucsd.edu/~jhamilto/hp.pdf

##### Arguments
- `y::AbstractVector` : data to be filtered
- `h::Integer` : Time horizon that we are likely to predict incorrectly.
                 Original paper recommends 2 for annual data, 8 for quarterly data,
                 24 for monthly data.
- `p::Integer` : Number of lags in regression. Must be greater than `h`.
Note: For seasonal data, it's desirable for `p` and `h` to be integer multiples
      of the number of obsevations in a year.
      e.g. For quarterly data, `h = 8` and `p = 4` are recommended.
##### Returns
- `y_cycle::Vector` : cyclical component
- `y_trend::Vector` : trend component
"""
function hamilton_filter(y::AbstractVector, h::Integer, p::Integer)
    y = Vector(y)
    T = length(y)
    y_cycle = fill(NaN, T)

    # construct X matrix of lags
    X = ones(T-p-h+1)
    for j = 1:p
        X = hcat(X, y[p-j+1:T-h-j+1])
    end

    # do OLS regression
    b = (X'*X)\(X'*y[p+h:T])
    y_cycle[p+h:T] = y[p+h:T] - X*b
    y_trend = vcat(fill(NaN, p+h-1), X*b)
    return y_cycle, y_trend
end

doc"""
This function applies "Hamilton filter" to `<:AbstractVector`
under random walk assumption.

http://econweb.ucsd.edu/~jhamilto/hp.pdf

##### Arguments
- `y::AbstractVector` : data to be filtered
- `h::Integer` : Time horizon that we are likely to predict incorrectly.
                 Original paper recommends 2 for annual data, 8 for quarterly data,
                 24 for monthly data.
Note: For seasonal data, it's desirable for `h` to be an integer multiple
      of the number of obsevations in a year.
      e.g. For quarterly data, `h = 8` is recommended.
##### Returns
- `y_cycle::Vector` : cyclical component
- `y_trend::Vector` : trend component
"""
function hamilton_filter(y::AbstractVector, h::Integer)
    y = Vector(y)
    T = length(y)
    y_cycle = fill(NaN, T)
    y_cycle[h+1:T] = y[h+1:T] - y[1:T-h]
    y_trend = y - y_cycle
    return y_cycle, y_trend
end


text:
using ArgParse

function main(args)

    # initialize the settings (the description is for the help screen)
    s = ArgParseSettings(description = "Example 1 for argparse.jl: minimal usage.")

    @add_arg_table! s begin
        "--opt1"               # an option (will take an argument)
        "--opt2", "-o"         # another option, with short form
        "arg1"                 # a positional argument
    end

    parsed_args = parse_args(s) # the result is a Dict{String,Any}
    println("Parsed args:")
    for (key,val) in parsed_args
        println("  $key  =>  $(repr(val))")
    end
end

main(ARGS)

max_stars_repo_name: dbindel/btg

max_issues_repo_name: dbindel/btg

max_forks_repo_name: dbindel/btg


text:
using Plots
gr(size=(750,400))
title = plot(title = "Plot title", grid = false, showaxis = false, bottom_margin = -50Plots.px)
p1 = scatter(rand(5, 1), title = "Subplot 1")
p2 = scatter(rand(5, 1), title = "Subplot 2")
plot(title, p1, p2, layout = @layout([A{0.01h}; [B C]]))


text:
using Manopt, Manifolds, Makie, Colors, LinearAlgebra, ColorSchemes, Random
Random.seed!(42)
#
# Helpers and Function
rot_x(φ) = [1 0 0; 0 cos(φ) -sin(φ); 0 sin(φ) cos(φ)]
rot_y(φ) = [cos(φ) 0 -sin(φ); 0 1 0; sin(φ) 0 cos(φ)]
rot_z(φ) = [cos(φ) -sin(φ) 0; sin(φ) cos(φ) 0; 0 0 1]
spherical_to_euclidean(θ, φ, r=1) = [r * sin(θ) * cos(φ), r * sin(θ) * sin(φ), r * cos(θ)]
function euclidean_to_spherical(x, y, z)
    return [acos(z / sqrt(x^2 + y^2 + z^2)), atan(y, x), sqrt(x^2 + y^2 + z^2)]
end

bob(x, x0, r=1) = (norm(x - x0) <= r) ? 1 - norm(x - x0) / r : 0
p1 = [0.0, 0.0, 1.0]
function F(::Manifolds.Sphere, x)
    s = euclidean_to_spherical(x[1], x[2], x[3])
    θ = s[1]
    φ = mod(s[2], 2π)
    v = sin(5θ + 3φ) + sin(3θ - 5φ) - 0.5 * (bob(x, p1, π / 2)^2 + bob(x, -p1, π / 2)^2)
    return v
end
M = Manifolds.Sphere(2)

#
# Plot Settings
n_lon = 801
n_lat = 401
lat = range(0, π; length=n_lat)
lon = range(-π, π; length=n_lon)
mesh_x = [spherical_to_euclidean(θ, φ)[1] for θ in lat, φ in lon]
mesh_y = [spherical_to_euclidean(θ, φ)[2] for θ in lat, φ in lon]
mesh_z = [spherical_to_euclidean(θ, φ)[3] for θ in lat, φ in lon]
mesh_pts = [spherical_to_euclidean(θ, φ) for θ in lat, φ in lon]
data = [F(M, spherical_to_euclidean(θ, φ)) for θ in lat, φ in lon]
# Init contour plot
scene = Scene()
mesh!(
    scene,
    Makie.Sphere(Point3f0(0), 0.9975f0);
    color=data,
    colormap=ColorSchemes.viridis,
    levels=50,
    interpolate=false,
    show_axis=false,
)
#
# Run PSO
# (a) equiangular x0
N = 50
x0 = [random_point(M) for i in 1:200]
xPlot = deepcopy(x0)
v0 = [zero_vector(M, y) for y in x0]
o = particle_swarm(
    M,
    F;
    x0=x0,
    velocity=v0,
    inertia=0.05,
    social_weight=0.3,
    cognitive_weight=0.2,
    stopping_criterion=StopAfterIteration(800),
    debug=[:Iteration, " ", 100],
    record=[:x, :p, :velocity],
    return_options=true,
);
path = [x[1] for x in get_record(o, :x)] # x0
velocities = [v[1] for v in get_record(o, :velocity)] # x0

# Animate / record
t = Node(xPlot) # create a life signal
b = Node(xPlot[argmin([F(M, y) for y in xPlot])])

scatter!(# plot population
    scene,
    lift(t -> [x[1] for x in t], t),
    lift(t -> [x[2] for x in t], t),
    lift(t -> [x[3] for x in t], t);
    markersize=0.025,
)
# plot best
scatter!(#plot best
    scene,
    lift(b -> [b[1]], b),
    lift(b -> [b[2]], b),
    lift(b -> [b[3]], b);
    markersize=0.033,
    color=:white,
)
N = length(path)
filename = string(@__DIR__, "/record_video.mkv")
record(scene, filename, 1:N; framerate=30) do i
    t[] = path[i]
    return b[] = path[i][argmin([F(M, y) for y in path[i]])]
end
best = get_solver_result(o)