text:
"""
    Unfold( Z::Array )

Unfolds a tensor into a 2-tensor.
"""
function Unfold(Z::Array)
    dimensions = size( Z )
    return reshape( Z, ( dimensions[ 1 ], prod( dimensions[ 2 : end ] ) ) )
end

struct MultiCenter{B} <: Transform
    Mean::B
    Mode::Int
    invertible::Bool
end

"""
    MultiCenter(Z, mode = 1)

Acquires the mean of the specified mode in `Z` and returns a transform that will remove those means from any future data.
"""
function MultiCenter(Z, mode = 1)
    Modes = size(Z)
    Core = Base.permutedims(Z, vcat(mode, setdiff( 1:length(Modes), mode ) ) )
    Core = reshape( Core , size(Core)[ 1 ], prod( size(Core)[ 2 : end ] ) )
    return MultiCenter( StatsBase.mean(Core, dims = 2), mode, true )
end

"""
    (T::MultiCenter)(Z; inverse = false)

Centers data in Tensor `Z` mode-wise according to learned centers in MultiCenter object `T`.
"""
function (T::MultiCenter)(Z; inverse = false)
    Modes = size(Z)
    Core = Base.permutedims(Z, vcat(T.Mode, setdiff( 1:length(Modes), T.Mode ) ) )
    ModesPerm = size(Core)
    Core = reshape( Core , size(Core)[ 1 ], prod( size(Core)[ 2 : end ] ) )
    if inverse
        Core = Core .+ T.Mean
    else
        Core = Core .- T.Mean
    end
    Core = reshape( Core,  ModesPerm  )
    Revert = collect(2:length(Modes))
    splice!(Revert, T.Mode:(T.Mode - 1), [1])
    return Base.permutedims(Core, Revert )
end

struct MultiScale{B} <: Transform
    StdDev::B
    Mode::Int
    invertible::Bool
end

"""
    MultiScale(Z, mode = 1)

Acquires the standard deviations of the specified mode in `Z` and returns a transform that will scale by those standard deviations from any future data.
"""
function MultiScale(Z, mode = 1)
    Modes = size(Z)
    Core = Base.permutedims(Z, vcat(mode, setdiff( 1:length(Modes), mode ) ) )
    Core = reshape( Core , size(Core)[ 1 ], prod( size(Core)[ 2 : end ] ) )
    return MultiCenter( StatsBase.std(Core, dims = 2), mode, true )
end

"""
    (T::MultiScale)(Z; inverse = false)

Scales data in Tensor `Z` mode-wise according to learned standard deviations in MultiScale object `T`.
"""
function (T::MultiScale)(Z; inverse = false)
    Modes = size(Z)
    Core = Base.permutedims(Z, vcat(T.Mode, setdiff( 1:length(Modes), T.Mode ) ) )
    ModesPerm = size(Core)
    Core = reshape( Core , size(Core)[ 1 ], prod( size(Core)[ 2 : end ] ) )
    if inverse
        Core = Core .* T.StdDev
    else
        Core = Core ./ T.StdDev
    end
    Core = reshape( Core,  ModesPerm  )
    Revert = collect(2:length(Modes))
    splice!(Revert, T.Mode:(T.Mode - 1), [1])
    return Base.permutedims(Core, Revert )
end

"""
    MultiNorm(T)

Computes the equivalent of the Froebinius norm on a tensor `T`. Returns a scalar.
"""
MultiNorm(T) = sqrt(sum(T .^ 2))

struct MultilinearPCA
    Core::Array
    Loadings::Array
    ExplainedVariance::Float64
end

"""
    HOSVD(X; Factors = 2)

Performs multilinear PCA aka Higher Order SVD aka Tucker, etc. The number of factors decomposed
can be a scalar (repeated across all modes) or a vector/tuple for each mode.

Returns a MultilinearPCA object containing (Core Tensor, Basis Tensors, Explained Variance)

Tucker, L. R. (1964). "The extension of factor analysis to three-dimensional matrices". In N. Frederiksen and H. Gulliksen (Eds.), Contributions to Mathematical Psychology. New York: Holt, Rinehart and Winston: 109–127.
"""
function HOSVD(X; Factors = 2)
    Modes = size(X)
    Factors = (length(Factors) == 1) ? repeat([Factors], length(Modes)) : Factors
    @assert length( Factors ) == length( Modes )
    @assert all( Factors .<= Modes)
    Order = length( Modes )
    Loadings = [ zeros(Modes[N], Factors[N]) for N in 1 : length(Modes) ]
    for n in 1 : Order
        resize = (n, setdiff( 1 : Order, n) )
        unfold = reshape( Base.permutedims( X, vcat(resize[1],resize[2]) ), Modes[ resize[ 1 ] ], prod( Modes[ resize[ 2 ] ] ) )
        svdres = LinearAlgebra.svd( unfold )
        factor = Factors[n]
        Loadings[n] = svdres.U[:, 1:factor]
    end
    Core = X
    modes = 1:length(Loadings)
    #ToDo Update to use the TensorProduct method...
    for i = modes #This is a doohicky to do the tensor products...
        Core = Base.permutedims(Core, vcat(i, setdiff( modes, i ) ) )
        Un = reshape( Core , size(Core)[ 1 ], prod( size(Core)[ 2 : end ] ) )
        Core = Loadings[i]' * Un
        newshape = Tuple(vcat(collect(Factors[1:i]), collect(Modes[ ( i + 1 ) : end])))
        Core = reshape( Core,  newshape  )
    end
    return MultilinearPCA(Core, Loadings, MultiNorm( Core ) / MultiNorm( X ) )
end

"""
    HOOI( X; Factors = 1, maxiters = 100, init = :HOSVD, tolerance = 1e-9 )

Performs multiway PCA aka Higher Order SVD aka Tucker, etc via the `Higher Order Orthogonal Iteration` (HOOI) of tensors.

Returns a MultilinearPCA object containing (Core Tensor, Basis Tensors, Explained Variance)

Lieven De Lathauwer, Bart De Moor, and Joos Van-dewalle. A multilinear singular value decomposition. SIAM J. Matrix Anal. Appl., 2000.
"""
function HOOI( X; Factors = 1, maxiters = 100, init = :HOSVD, tolerance = 1e-9 )
    Size = size(X)
    Modes = length(Size)
    X_loads = []
    if init == :HOSVD
        X_loads = HOSVD( X; Factors = Factors ).Loadings
    else #Random initialization - not reccomended for reproducibility...
        X_loads = [ randn( s, Factors ) for s in Size]
    end
    LastNorm = Inf
    Norm = X_loads[1]' * Unfold(X) * foldr(kron, X_loads[reverse(2:end)])
    #Norm = MultiNorm( foldl( kron, X_loads ) )
    it = 0
    while ( it < maxiters ) && ( (MultiNorm( LastNorm .- Norm ) / MultiNorm( Norm ) ) > tolerance )
        for Mode in 1 : Modes
            NotMode = setdiff( 1:Modes, Mode )
            Core = copy(X)
            for (Collapsed, NM) in enumerate( NotMode )
                Core = TensorProduct(Core, X_loads[NM], NM - Collapsed + 1, 1;
                                        RemoveSingularModes = true )
            end
            Core = Unfold( Core )
            #Get Left Hand Singular Vectors
            X_loads[ Mode ] = LinearAlgebra.svd( Core ).U[ : , 1 : Factors ]
        end
        it += 1
        LastNorm = deepcopy( Norm )
        Norm = X_loads[1]' * Unfold(X) * foldr(kron, X_loads[reverse(2:end)])
    end
    Core = X
    for M in 1 : Modes
        Core = TensorProduct(Core, X_loads[M], 1, 1;
                                RemoveSingularModes = false )
    end
    return MultilinearPCA( Core, X_loads, MultiNorm( Core ) / MultiNorm( X ) )
end

"""
    TensorProduct(A, B, IndexA, IndexB; RemoveSingularModes = true,
                        SizeA = size(A), SizeB = size(B) )

Computes the tensor product of tensors `A` & `B` across their respective indices.

Note: This is primairily an method for internal use to the library, but feel free to
use it for your own needs.

"""
function TensorProduct(A, B, IndexA, IndexB; RemoveSingularModes = true,
                        SizeA = size(A), SizeB = size(B) )
    ModesA, ModesB   = length( SizeA ), length( SizeB )
    Ac, Bc           = copy(A), copy(B)
    UnfoldA, UnfoldB = SizeA, SizeB
    #Do we need to permute A?
    if IndexA != 1
        Swap = vcat(IndexA, setdiff( 1:ModesA, IndexA )... )
        Ac = permutedims( Ac, Swap )
        UnfoldA = Swap
        SizeA = SizeA[Swap]
    end
    #Do we need to permute B?
    if IndexB != 1
        Swap = vcat(IndexB, setdiff( 1:ModesB, IndexB )...)
        Bc = permutedims( Bc, Swap )
        UnfoldB = Swap
        SizeB = SizeB[ Swap ]
    end
    #Unfold A and B into a matrix form.
    Ac = reshape( Ac, ( SizeA[ 1 ], prod( SizeA[ 2 : end ] ) ) )
    Bc = reshape( Bc, ( SizeB[ 1 ], prod( SizeB[ 2 : end ] ) ) )
    #Multiply them
    C = Ac' * Bc
    #New shape is now prod(Ja,Ka,..Za) x prod(Jb,Kb,..Zb)
    #Need to unfold to (Ja,Ka,..Za, Jb,Kb,..Zb )
    NewShape = collect(vcat( SizeA[2:end]..., SizeB[2:end]... ))
    if RemoveSingularModes
        NewShape = NewShape[ NewShape .!= 1 ]
    end
    return reshape( C, Tuple(NewShape)... )
end

struct MultilinearPLS
    XLoadings::Array    #W
    XScores::Array      #T
    YLoadings::Array    #Q
    YScores::Array      #U
    Coefficients::Array #B
    Factors::Int        ##
end

"""
    MultilinearPLS(Y, X; Factors = minimum(size(X)) - 2,
                         tolerance = 1e-8, maxiters = 200 )

Performs a Multilinear PLS regression from `X` and `Y` tensors. The number of
`Factors`, convergence `tolerance`, and the `maxiters`(maximum iterations) may be set.

Method returns a `MultilinearPLS` object.

Notes:
    - Only Y orders < 2 are currently supported.
    - X order must be >= 2
    - X orders > 3 are currently unreviewed. Please contribute!

Bro, Rasmus. (1996), Multiway calibration. Multilinear PLS. J. Chemometrics, 10: 47-61. doi:10.1002/(SICI)1099-128X(199601)10:1<47::AID-CEM400>3.0.CO;2-C
"""
function MultilinearPLS(Y, X; Factors = minimum(size(X)) - 2,
                           tolerance = 1e-8, maxiters = 200 )
    X_size,  Y_size  = size( forceMatrix( X ) ), size( forceMatrix( Y ) )
    X_order, Y_order = length( X_size ), length( Y_size )
    @assert(Y_order < 3, "Only Y orders < 2 are currently supported.")
    @assert(X_order > 2, "Use PartialLeastSquaresRegression when X order is < 3.")
    @warn("This code algorithm has only been inspected for X orders of 3, and Y orders < 3.\n Use at your own risk, and please report any bugs!")
    X_e, Y_e        = Unfold(deepcopy(X)), Unfold(deepcopy(Y))
    T = zeros( X_size[1], Factors )                     #X Scores
    W = [ zeros( i, Factors ) for i in X_size[2:end] ]  #X Loadings
    U = zeros( Y_size[1], Factors )                     #Y Scores
    Q = [ zeros( i, Factors ) for i in Y_size[2:end] ]  #Y Loadings
    B = zeros( Factors, Factors )                       #Coefficient matrix
    iteration = 0
    for Factor in 1 : Factors
        u = [0.0]
        Weights_unfolded = [0.0]
        iteration = 0
        #Initialize Y Scores
        if (length( Q ) == 1) && (Y_size[2] == 1)
            u = Y_e
        else
            #Could extend Y decomposition to higher orders but for now consider Classic PLS2
            #mpcay = HOOI( Y_e; Factors = 1 ) #u = mpcay.Core[:] .* mpcay.Loadings[ 1 ]
            u = copy( Y_e[ :, argmax( [ (Y_e[:,col]' * Y_e[:,col])[1] for col in 1:Y_size[2]] ) ] )
        end
        change = Inf
        while (change > tolerance) && (iteration < maxiters)
            iteration += 1
            #Calculate X Contributions
            u_prime = copy( u ) #Hacky but it works
            X_project = reshape( (X_e' * u), X_size[2], prod( X_size[3:end] ) )
            mpca = HOOI( X_project; Factors = 1, tolerance = tolerance)
            for (i, w) in enumerate( mpca.Loadings )
                #99.9% sure HOOI/HOSVD scales by tensor core so no need for it here?
                W[i][:, Factor] = w
            end
            Weights_unfolded = foldr(kron, reverse(mpca.Loadings) )
            T[ :, Factor ] = X_e * Weights_unfolded
            #Calculate Y Contributions
            q = transpose( T[ :, Factor ] ) * Y_e
            q = q ./ sqrt(sum( q .^ 2))
            Q[1][:, Factor] = q[:]
            u = Y_e * q'
            U[:, Factor] = u
            #Monitor convergence by tensor norm of U
            change = sqrt( sum( (u_prime - U[:, Factor]) .^ 2 ) / sum( U[:, Factor] .^ 2 ) )
        end
        #Solve for regression coefficients and prediction intermediates
        TTT = Base.inv(T[:,1:Factor]' * T[:,1:Factor]) * T[:,1:Factor]'
        B[1:Factor,Factor] .= TTT * U[:,Factor]
        #Deflate/map residues
        Y_e = Y - (T[ :, 1:Factor] * B[1:Factor, 1:Factor] * Q[1][:, 1:Factor]')
        X_e = X_e - (T[ :, Factor ] * Weights_unfolded')
    end

    return MultilinearPLS( W, T, Q, U, B, Factors)
end

"""
    (M::MultilinearPLS)( X; Factors = M.Factors )

Applies a Multilinear PLS regression object to new `X` data with a prescribed number of
`Factors`. Method returns a matrix of the calibrated size `Y`.

Bro, Rasmus. (1996), Multiway calibration. Multilinear PLS. J. Chemometrics, 10: 47-61. doi:10.1002/(SICI)1099-128X(199601)10:1<47::AID-CEM400>3.0.CO;2-C
"""
function (M::MultilinearPLS)(X; Factors = M.Factors)
    X_size = size( forceMatrix( X ) )
    X_order = length( X_size )
    XProjections = zeros( X_size[1] , Factors )
    X_e = Unfold( copy(X) )
    for Factor in 1:Factors
        Weights_unfolded = foldr(kron, map( x -> x[:,Factor]', reverse(M.XLoadings) ) )
        XProjections[:,Factor] = X_e * Weights_unfolded'
        X_e = X_e - XProjections[:,Factor] * Weights_unfolded
    end
    F = 1:Factors
    return XProjections[ :, F ] * M.Coefficients[ F, F ] * M.YLoadings[1][ :, F ]'
end


text:
@testset "GrpAbFinGen" begin
  @testset "Type stuff" begin
    @test elem_type(GrpAbFinGen) == GrpAbFinGenElem
    @test parent_type(GrpAbFinGenElem) == GrpAbFinGen
  end

  @testset "Constructor" begin
    M1 = matrix(FlintZZ, 2, 3, [1, 2, 3, 4, 5, 6])
    G = @inferred AbelianGroup(M1)
    @test isa(G, GrpAbFinGen)
    @test G.rels == M1

    M = FlintZZ[1 2 3; 4 5 6] # fmpz_mat
    G = @inferred AbelianGroup(M)
    @test isa(G, GrpAbFinGen)
    @test G.rels == M1

    M = fmpz[1 2 3; 4 5 6]
    G = @inferred AbelianGroup(M)
    @test isa(G, GrpAbFinGen)
    @test G.rels == M1

    M = [1 2 3; 4 5 6]
    G = @inferred AbelianGroup(M)
    @test isa(G, GrpAbFinGen)
    @test G.rels == M1

    M = fmpz[1, 2, 3, 4, 5, 6]
    G = @inferred AbelianGroup(M)
    @test isa(G, GrpAbFinGen)
    @test G.rels == matrix(FlintZZ, 1, 6, M)

    M = [1, 2, 3, 4, 5, 6]
    G = @inferred AbelianGroup(M)
    @test isa(G, GrpAbFinGen)
    @test G.rels == matrix(FlintZZ, 1, 6, M)

    M = [3, 0]
    G = @inferred DiagonalGroup(M)
    @test isa(G, GrpAbFinGen)

    M = fmpz[3, 0]
    G = @inferred DiagonalGroup(M)
    @test isa(G, GrpAbFinGen)

    M = matrix(FlintZZ, 1, 2, [3, 0])
    G = @inferred DiagonalGroup(M)
    @test isa(G, GrpAbFinGen)

    N = [3, 5]
    G = @inferred DiagonalGroup(N)
    @test isa(G, GrpAbFinGen)
    @test G.rels == matrix(FlintZZ, 2, 2, [3, 0, 0, 5])

    N = fmpz[3, 5]
    G = @inferred DiagonalGroup(N)
    @test isa(G, GrpAbFinGen)
    @test G.rels == matrix(FlintZZ, 2, 2, [3, 0, 0, 5])

    N = matrix(FlintZZ, 1, 2, [3, 5])
    G = @inferred DiagonalGroup(N)
    @test isa(G, GrpAbFinGen)
    @test G.rels == matrix(FlintZZ, 2, 2, [3, 0, 0, 5])

    @test_throws ErrorException DiagonalGroup(FlintZZ[1 2; 3 4])

    @testset "String I/O" begin
      @test issnf(M)
      @test isa(string(M), String)
      @test isa(string(N), String)
    end

    @testset "Field access" begin
      S = DiagonalGroup([3, 0])
      @test @inferred issnf(S)
      @test @inferred ngens(S) == 2
      @test @inferred nrels(S) == 2
      @test @inferred rels(S) == matrix(FlintZZ, 2, 2, [3, 0, 0, 0])

      G = DiagonalGroup([3, 5])
      @test @inferred !issnf(G)
      @test @inferred ngens(G) == 2
      @test @inferred nrels(G) == 2
      @test @inferred rels(G) == matrix(FlintZZ, 2, 2, [3, 0, 0, 5])
    end

    @testset "Hermite normal form" begin
      M   = FlintZZ[1 2 3; 4 5 6]
      HNF = FlintZZ[1 2 3; 0 3 6]
      G = AbelianGroup(M)
      Hecke.assure_has_hnf(G)
      @test G.hnf == HNF
    end

    @testset "Smith normal form" begin
      M = FlintZZ[16 17 2 ; 19 23 8 ; 16 17 2]
      G = AbelianGroup(M)
      S, mS = @inferred snf(G)
      @test issnf(S)
      @test S.snf == fmpz[45, 0]
      @test codomain(mS) == G
      @test domain(mS) == S
    end

    @testset "Finiteness" begin
      G = DiagonalGroup([3, 15])
      @test issnf(G)
      @test @inferred isfinite(G)
      @test @inferred !isinfinite(G)

      G = DiagonalGroup([3, 5])
      @test @inferred isfinite(G)
      @test @inferred !isinfinite(G)

      G = DiagonalGroup([3, 15, 0])
      @test issnf(G)
      @test @inferred !isfinite(G)
      @test @inferred isinfinite(G)

      G = DiagonalGroup([3, 5, 0])
      @test @inferred !isfinite(G)
      @test @inferred isinfinite(G)
    end

    @testset "Rank" begin
      G = DiagonalGroup([3, 15])
      @test @inferred rank(G) == 0

      G = DiagonalGroup([3, 5])
      @test @inferred rank(G) == 0

      G = DiagonalGroup([3, 15, 0])
      @test @inferred rank(G) == 1

      G = DiagonalGroup([3, 5, 0])
      @test @inferred rank(G) == 1
    end

    @testset "Order" begin
      G = DiagonalGroup([3, 5])
      @test @inferred order(G) == 15
      G = DiagonalGroup([3, 15])
      @test @inferred order(G) == 45
      G = DiagonalGroup([3, 5, 0])
      @test_throws ErrorException order(G)
    end

    @testset "Exponent" begin
      G = DiagonalGroup([3, 5])
      @test @inferred exponent(G) == 15
      G = DiagonalGroup([3, 15])
      @test @inferred exponent(G) == 15
    end

    @testset "Trivial" begin
      G = DiagonalGroup([1])
      @test @inferred istrivial(G)
      G = DiagonalGroup([1, 1, 1])
      @test @inferred istrivial(G)
      G = DiagonalGroup([3, 3])
      @test @inferred !istrivial(G)
      G = DiagonalGroup([3, 5])
      @test @inferred !istrivial(G)
    end

    @testset "Isomorphism" begin
      b = @inferred isisomorphic(DiagonalGroup(Int[]), DiagonalGroup(Int[]))
      @test b

      G = DiagonalGroup([2, 3, 5])
      H = DiagonalGroup([30])
      @test @inferred isisomorphic(G, H)
    end

    @testset "Direct product" begin
      G = DiagonalGroup([5, 3])
      H = DiagonalGroup([4])
      K = @inferred direct_product(G, H)
      @test isisomorphic(K, DiagonalGroup([60]))
    end

    @testset "Torsion" begin
      G = DiagonalGroup([5, 4])
      @test @inferred istorsion(G)
      H, mH = torsion_subgroup(G)
      @test order(H) == 20

      G = DiagonalGroup([5, 0, 4, 0])
      @test @inferred !istorsion(G)
      H, mH = torsion_subgroup(G)
      @test isisomorphic(H, DiagonalGroup([5, 4]))
    end

    @testset "Subgroup" begin
      @test_throws ErrorException sub(GrpAbFinGenElem[])

      G = AbelianGroup(FlintZZ[3 0 0 ; 0 15 0])
      g1 = G[1]
      g2 = G[2]
      g3 = G[3]
      S, S_map = @inferred sub([g1, g2, g3])
      @test isisomorphic(G, S)

      G = AbelianGroup(FlintZZ[3 0 0 ; 0 15 0])
      S, mS = snf(G)
      s1 = S[1]
      s2 = S[2]
      s3 = S[3]
      H, mH = @inferred sub(S, [s1, s2, s3])
      @test isisomorphic(H, G)

      G = AbelianGroup(FlintZZ[3 0 0 ; 0 15 0])
      g1 = G[1]
      H, mH = @inferred sub(G, [g1])
      @test isisomorphic(H, DiagonalGroup([3]))

      G = AbelianGroup(FlintZZ[3 0 0 ; 0 15 0])
      S, mS = snf(G)
      s1 = S[1]
      H, mH = @inferred sub(S, [s1])
      @test isisomorphic(H, DiagonalGroup([3]))

      # G contains empty relation
      G = AbelianGroup(FlintZZ[3 0 0 ; 0 15 0 ; 0 0 30 ; 0 0 0])
      g1 = G[3]
      S, mS = @inferred sub(G, [g1])
      @test isisomorphic(S, DiagonalGroup([30]))

      # n*G

      G = DiagonalGroup([6, 6, 12, 5])
      H, mH = @inferred sub(G, 2)
      @test isisomorphic(H, DiagonalGroup([3, 3, 6, 5]))

      H, mH = @inferred sub(G, fmpz(2))
      @test isisomorphic(H, DiagonalGroup([3, 3, 6, 5]))
    end

    @testset "Quotient" begin
      G = AbelianGroup(FlintZZ[3 0 0 ; 0 15 0])

      Q, mQ = @inferred quo(G, GrpAbFinGenElem[])
      @test isisomorphic(Q, G)

      g2 = G[2]
      Q, mQ = @inferred quo(G, [g2])
      @test isisomorphic(Q, DiagonalGroup([3, 0]))

      S = DiagonalGroup([3, 15, 0])
      @test issnf(S)
      g2 = S[2]
      Q, mQ = @inferred quo(S, [g2])
      @test isisomorphic(Q, DiagonalGroup([3, 0]))

      G = DiagonalGroup([6, 6, 12, 5, 0])
      H, mH = @inferred quo(G, 2)
      @test isisomorphic(H, DiagonalGroup([2, 2, 2, 2]))

      H, mH = @inferred quo(G, fmpz(2))
      @test isisomorphic(H, DiagonalGroup([2, 2, 2, 2]))
    end

    @testset "Cyclic" begin
      G = DiagonalGroup([3, 5])
      @test @inferred iscyclic(G)

      G = DiagonalGroup([3, 15])
      @test @inferred !iscyclic(G)
    end

    @testset "p-Sylow subgroup" begin
      G = DiagonalGroup([1, 3, 9, 5, 15, 20, 7])
      P, mP = psylow_subgroup(G, 3)
      @test order(P) == 3^valuation(order(G), 3)
      P, mP = psylow_subgroup(G, 5)
      @test order(P) == 5^valuation(order(G), 5)
      P, mP = psylow_subgroup(G, 11)
      @test order(P) == 11^valuation(order(G), 11)
    end
  end
end

ext: jl


text:
module LibOpenJPEG

include("libopenjp3d_h.jl")
include("libopenjp3d.jl")

end # module


text:
"""
    get_imf_datasets()

Return the list of datasets that are accessible from the IMF API, along with their dataset IDs, as a `DataFrame`.
"""
function get_imf_datasets()
    # Get list of datasets and IDs
    api_method = "/Dataflow"
    query = string(API_URL, api_method)
    response = HTTP.get(query)
    if response.status != 200
        error("Invalid request")
    end
    response_body = String(response.body)
    response_json = JSON.parse(response_body)

    dsets_dicts = response_json["Structure"]["Dataflows"]["Dataflow"]
    dbid = String[]
    dbname = String[]
    for dict in dsets_dicts
        push!(dbid, dict["KeyFamilyRef"]["KeyFamilyID"])
        push!(dbname, dict["Name"]["#text"])
    end
    datasets = DataFrame(dataset_id = dbid, dataset_name = dbname)
    sort!(datasets, [:dataset_id])

    return datasets
end


text:
using BayesianOptimization, GaussianProcesses, PGFPlotsX, Random
push!(PGFPlotsX.CUSTOM_PREAMBLE, "\\usepgfplotslibrary{fillbetween}")

Random.seed!(134)
f(x, noisevariance = 1) = .1*sum((x .- 2).^2) + cos(sum(π/2 * x)) + noisevariance * randn()
model = ElasticGPE(1, mean = MeanConst(0.),
                   kernel = SEArd([0.], 5.), logNoise = 0.)
modeloptimizer = MAPGPOptimizer(every = 50, noisebounds = [-2., 3],
                                kernbounds = [[-1, 0], [4, 10]], maxeval = 40)
opt = BOpt(f, model, ExpectedImprovement(),
           modeloptimizer, [-5.], [5.],
           maxiterations = 5, sense = Min, repetitions = 5,
           acquisitionoptions = (maxeval = 4000, restarts = 50),
           verbosity = Progress)
result = boptimize!(opt)

acqfunc = BayesianOptimization.acquisitionfunction(opt.acquisition, model)
xs = -5:.02:5
ms, var = predict_f(model, xs)
sig = sqrt.(var)
fmax, xmax = BayesianOptimization.acquire_max(opt.opt,
                        opt.lowerbounds, opt.upperbounds,
                        opt.acquisitionoptions.restarts)
@pgf GroupPlot({group_style = {group_size = "1 by 2", vertical_sep = "4mm"},
                height = "4cm", width = "8cm", legend_pos = "outer north east",
                legend_style = {draw = "none"}},
               {legend_columns = 1, xticklabels = ""},
             Plot({only_marks}, Coordinates(model.x[:], -model.y[:])),
             "\\addlegendentry{observations}",
             Plot({no_marks, "red!20", name_path = "A", forget_plot}, Coordinates(xs, -ms .+ sig)),
             Plot({no_marks, "red!20", name_path = "B", forget_plot}, Coordinates(xs, -ms .- sig)),
             "\\addplot[red!20] fill between [of=A and B];",
             "\\addlegendentry{model std}",
             Plot({no_marks, blue, very_thick}, Coordinates(xs, -ms)),
             "\\addlegendentry{model mean}",
             Plot({no_marks, "green!80!black", very_thick}, Coordinates(xs, f.(xs, 0))),
             "\\addlegendentry{noisefree target}",
             {height = "3cm", ytick=[0, .05, .1], yticklabels = [0, "0.05", "0.1"]},
             Plot({only_marks, red, mark="triangle*",
                   mark_size = "5pt", mark_options = {rotate = "0"}},
                  Coordinates(xmax, [fmax])),
             Plot({no_marks, very_thick}, Coordinates(xs, (x -> acqfunc([x])).(xs))),
             "\\addlegendentry{next acquisition}",
             "\\addlegendentry{acquisition function}")


text:
@testset "Fishery Domain" begin
    ## Check distance calculation
    loctuples = [(0.0, 0.0) (5.0, 12.0); (3.0, 4.0) (0.0, 3.0)]
    @test all(FisherySim.calculate_distances(loctuples)[:, 1] .== [0.0, 5.0, 13.0, 3.0])

    randsamp = sample(Ω, 400)
    randhist = fit(Histogram, randsamp, closed = :right)
    ## FIXME: Need a test for the unweighted sampling case
    prefsamp = sample(Ω, weights(2last.(Ω.locs)), 400)
    prefhist = fit(Histogram, prefsamp, closed = :right)
    ## FIXME: Is this the best test to use here?
    @test prefhist.weights[1] < prefhist.weights[end]
end


text:
# recipes
@recipe function f(pt::Point2D)
    seriestype := :scatter
    label --> :none
    [(pt.x, pt.y)]
end

@recipe function f(pt::Point3D)
    seriestype := :scatter
    label --> :none
    [pt.x], [pt.y], [pt.z]
end

@recipe function f(c::Circle2D)
    seriestype := :shape
    linecolor --> :black
    aspect_ratio --> :equal
    fillalpha --> 0.25
    label --> :none
    θ = 0:0.1:2π
    c.pt.x .+ c.r .* cos.(θ), c.pt.y .+ c.r .* sin.(θ)
end

@recipe function f(particle::Particle2D)
    particle.c
end

@recipe function f(c::Circle3D)
    seriestype := :scatter
    label --> :none
    markersize --> 10c.r
    [c.pt.x], [c.pt.y], [c.pt.z]
end

@recipe function f(geomobjs::AbstractArray{<:ConcreteGeometricTypes})
    for obj in geomobjs
        @series begin
            obj
        end
    end
end

@recipe f(geomobjs::T...) where {T<:ConcreteGeometricTypes} = collect(geomobjs)


text:
# Copyright 2016 Martin Holters
# See accompanying license file.

using ACME

# Model of "Der Super Over", see
# http://diy.musikding.de/wp-content/uploads/2013/06/superoverschalt.pdf
# for schematics.
# Note: R19 and LED D5 have been omitted from the model.

function superover(::Type{Circuit}; drive=nothing, tone=nothing, level=nothing, sym::Bool=false)
    r1 = resistor(2.2e6)
    r2 = resistor(10e3)
    r3 = resistor(470e3)
    r4 = resistor(10e3)
    r5 = resistor(100e3)
    r6 = resistor(33e3)
    r7 = resistor(4.7e3)
    r8 = resistor(10e3)
    r10 = resistor(10e3)
    r11 = resistor(470)
    r12 = resistor(4.7e3)
    r13 = resistor(1e6)
    r14 = resistor(10e3)
    r15 = resistor(1e3)
    r16 = resistor(100e3)
    r17 = resistor(33e3)
    r18 = resistor(33e3)
    r20 = resistor(22e3)
    if drive == nothing
        p1 = potentiometer(1e6)
    else
        p1 = potentiometer(1e6, drive)
    end
    if tone == nothing
        p2 = potentiometer(20e3)
    else
        p2 = potentiometer(20e3, tone)
    end
    if level == nothing
        p3 = potentiometer(10e3)
    else
        p3 = potentiometer(10e3, level)
    end

    c1 = capacitor(47e-9)
    c2 = capacitor(18e-9)
    c4 = capacitor(47e-9)
    c5 = capacitor(18e-9)
    c6 = capacitor(27e-9)
    c7 = capacitor(10e-9)
    c8 = capacitor(1e-3)
    c9 = capacitor(47e-9)
    c10 = capacitor(1e-6)
    c11 = capacitor(100e-6)
    c12 = capacitor(47e-6)

    d1 = diode(is=4e-9, η=2) # 1N914
    d2 = diode(is=3e-9, η=2) # 1N914
    d3 = diode(is=5e-9, η=2) # 1N914
    d4 = diode(is=12e-9, η=2) # 1N4001
    q1 = bjt(:npn, is=80e-15, βf=500, βr=10)
    q2 = bjt(:npn, is=80e-15, βf=500, βr=10)

    ic1a = opamp()
    ic1b = opamp()

    j1 = voltagesource() # input
    j2 = voltageprobe() # output
    j3 = voltagesource(9) # 9V power supply

    circ = Circuit()

    # power supply
    connect!(circ, j3[:+], :vcc)
    connect!(circ, j3[:-], :gnd)
    connect!(circ, d4[:-], c11[1], :vcc)
    connect!(circ, d4[:+], c11[2], :gnd)
    connect!(circ, :vcc, r17[1])
    connect!(circ, r17[2], r18[1], c12[1], :vb)
    connect!(circ, :gnd, r18[2], c12[2])

    # input stage
    connect!(circ, j1[:-], r1[2], :gnd)
    connect!(circ, j1[:+], r1[1], c1[1])
    connect!(circ, c1[2], r2[1])
    connect!(circ, r2[2], q1[:base], r3[1])
    connect!(circ, r3[2], :vb)
    connect!(circ, q1[:collector], :vcc)
    connect!(circ, q1[:emitter], r4[1], c2[1])
    connect!(circ, r4[2], :gnd)
    connect!(circ, c2[2], r5[1])
    connect!(circ, r5[2], :vb)

    # distortion stage
    connect!(circ, c2[2], ic1a["in+"])
    connect!(circ, ic1a["out+"], d3[:+], d1[:-], p1[2], p1[3])
    connect!(circ, ic1a["in-"], d2[:-], d1[:+], r6[1], c4[1])
    connect!(circ, ic1a["out-"], :gnd)
    if sym
        connect!(circ, d3[:-], d3[:+])
    end
    connect!(circ, r6[2], p1[1])
    connect!(circ, d2[:+], d3[:-])
    connect!(circ, c4[2], r7[1])
    connect!(circ, r7[2], :vb)

    # tone control stage
    connect!(circ, r8[1], ic1a["out+"])
    connect!(circ, r8[2], c5[1], ic1b["in+"])
    connect!(circ, c5[2], :gnd)
    connect!(circ, ic1b["out+"], r10[1], c7[1])
    connect!(circ, ic1b["in-"], r10[2], c7[2], p2[3])
    connect!(circ, ic1b["out-"], :gnd)
    connect!(circ, ic1b["in+"], p2[1])
    connect!(circ, p2[2], c6[1])
    connect!(circ, c6[2], r11[1])
    connect!(circ, r11[2], :gnd)

    # output stage
    connect!(circ, ic1b["out+"], c8[1])
    connect!(circ, c8[2], r12[1])
    connect!(circ, r12[2], p3[3])
    connect!(circ, p3[2], r20[1])
    connect!(circ, p3[1], :vb)
    connect!(circ, r20[2], c9[1])
    connect!(circ, c9[2], r13[1], q2[:base])
    connect!(circ, r13[2], :vb)
    connect!(circ, q2[:collector], :vcc)
    connect!(circ, q2[:emitter], r14[1], r15[1])
    connect!(circ, r14[2], :gnd)
    connect!(circ, r15[2], c10[1])
    connect!(circ, c10[2], r16[1])
    connect!(circ, r16[2], :gnd)
    connect!(circ, c10[2], j2[:+])
    connect!(circ, :gnd, j2[:-])

    return circ
end

superover{T<:DiscreteModel}(::Type{T}=DiscreteModel; drive=nothing, tone=nothing, level=nothing, sym::Bool=false, fs=44100) =
    T(superover(Circuit, drive=drive, tone=tone, level=level, sym=sym), 1/fs)


text:
using CellListMap
using ForwardDiff
using Unitful
using Measurements
using LinearAlgebra: norm_sqr

#
# This function computes the sum of the squared distances of the particles
#
function sumsq(x,sides,cutoff;parallel=false)
    box = Box(sides,cutoff)
    cl = CellList(x,box,parallel=parallel)
    s = zero(eltype(x[1]^2))
    s = map_pairwise(
        (x,y,i,j,d2,s) -> s += d2,
        s, box, cl, parallel=parallel
    )
    return s
end

#
# This is the analytical gradient of the above function
#
function sumsq_grad(x,sides,cutoff;parallel=false)
    g = similar(x)
    box = Box(sides,cutoff)
    cl = CellList(x,box)
    g .= zero(eltype(x))
    map_pairwise!(
        (x,y,i,j,d2,g) -> begin
            dx = x - y
            g[:,i] .+= 2*dx
            g[:,j] .-= 2*dx
            return g
        end,
        g, box, cl, parallel=parallel
    )
    return g
end

#
# Propagating measurements (or other more general types)
#
function sumsq_measurements(x_input,sides,cutoff;parallel=false)

    # The dual type of measurement does not propagate well on
    # all operations of CellListMap, and also comes with a signficant
    # cost, because they are not isbits types. Therefore, it is better
    # to bypass the internal computations by closing over the
    # input array and computing the result directly from the original
    # data. Here, `x_input` is the original array of coordinates
    # with uncertainties.
    function sum_sqr_pair(i,j,s,x_input,box)
        xi = x_input[i]
        xj = CellListMap.wrap_relative_to(x_input[j],xi,box)
        s += norm_sqr(xi - xj)
        return s
    end

    # Copy input vector of coordinates with uncertainties to a vector
    # of coordintes with values only
    x = [ getproperty.(v,:val) for v in x_input ]

    # Build cell lists
    box = Box(sides,cutoff)
    cl = CellList(x,box)

    # The initial result is initialized with the appropriate type.
    s = measurement(0.,0.)

    # And instead of using the `x` and `y` coordinates provided by the
    # interface, we close over the `x_input` and `box` for the calculations.
    s = map_pairwise(
        (x,y,i,j,d2,s) -> sum_sqr_pair(i,j,s,x_input,box),
        s, box, cl, parallel=parallel
    )
    return s
end

#
# Using generic types
#
function generic_types(iprint=true;parallel=false)

    #
    # Compare analtical and finite-difference gradient. Note that we convert the `sides`
    # and `cutoff` variables to the type of variable in `x`, to allow the propagation of the
    # dual numbers required to ForwardDiff and Unitful
    #
    x = rand(3,1000)
    cutoff = 0.1
    sides = [1.0, 1.0, 1.0]

    function sumsq_generic(x)
        cutoff_generic = eltype(x).(cutoff) # cutoff is closed over
        sides_generic = eltype(x).(sides) # sides is closed over
        return sumsq(x, sides_generic, cutoff_generic)
    end
    check_grad = sumsq_grad(x,sides,cutoff) ≈ ForwardDiff.gradient(sumsq_generic, x)
    iprint && println("Gradients are correct: ", check_grad)

    #
    # Now let us propagate units
    #
    x = rand(3,1000)u"nm"
    cutoff = 0.1u"nm"
    sides = [1.0, 1.0, 1.0]u"nm"
    runit = sumsq(x,sides,cutoff)
    iprint && println("Result with units: ", runit)

    #
    # Propagating uncertainties with Measurements
    #
    x = [ SVector{3}(measurement(rand(),0.01*rand()) for i in 1:3) for j in 1:1000 ]
    cutoff = 0.1
    sides = [1.0, 1.0, 1.0]
    rmeasurement = sumsq_measurements(x,sides,cutoff,parallel=parallel)
    iprint && println("Result with uncertainty: ", rmeasurement)

    return check_grad, unit(runit), typeof(rmeasurement)
end


text:
function KeplerianPropagator(arg0::Orbit)
    return KeplerianPropagator((Orbit,), arg0)
end

function KeplerianPropagator(arg0::Orbit, arg1::AttitudeProvider)
    return KeplerianPropagator((Orbit, AttitudeProvider), arg0, arg1)
end

function KeplerianPropagator(arg0::Orbit, arg1::AttitudeProvider, arg2::jdouble)
    return KeplerianPropagator((Orbit, AttitudeProvider, jdouble), arg0, arg1, arg2)
end

function KeplerianPropagator(arg0::Orbit, arg1::AttitudeProvider, arg2::jdouble, arg3::jdouble)
    return KeplerianPropagator((Orbit, AttitudeProvider, jdouble, jdouble), arg0, arg1, arg2, arg3)
end

function KeplerianPropagator(arg0::Orbit, arg1::jdouble)
    return KeplerianPropagator((Orbit, jdouble), arg0, arg1)
end

function reset_initial_state(obj::KeplerianPropagator, arg0::SpacecraftState)
    return jcall(obj, "resetInitialState", void, (SpacecraftState,), arg0)
end


text:
module LineSpectraEstimation

#TODO change benchmark to JuMP?

using BenchmarkTools
using StructuredOptimization
using Convex
using MathProgBase
using ECOS
using SCS
using AbstractOperators
using PyPlot

function set_up(;opt="")

    srand(39)

    fs = 16e3
    Nt = 2^7 #time samples
    y0 = zeros(Nt)
    SNR = 20

    s = 4 #super-resolution factor
    f_s  = linspace(0,  fs,       s*Nt+1)[1:end-1]     # super resolution frequency axis
    f_s2 = linspace(0,fs/2,div(s*Nt,2)+1)              # super resolution frequency axis (up to Nyquist)
    t  = 0:1/fs:(Nt-1)/fs                              # time axis
    f  = linspace(0,fs,Nt+1)[1:end-1]                  # frequency axis
    f2 = linspace(0,fs/2,div(Nt,2)+1)                  # frequency axis
    K = 14                                             # number of sinusoids
    Nf = div(s*Nt,4)+1
    fk = f_s2[randperm(Nf)[1:K]]                   # sinusoids frequencies
    ak = 0.1*randn(K)+0.7                              # amplitude

    for i in eachindex(fk) y0 .+= ak[i].*sin.(2*π*fk[i].*t) end
    y = y0.+10^(-SNR/10)*sqrt(var(y0))*randn(length(y0))

	xzp = rfft([y;zeros((s-1)*length(y))])
	IDFTm = [exp(im*2*pi*k*n/(s*Nt))  for k =0:s*Nt-1, n=0:s*Nt-1] #Inverse Fourier Matrix
	S = [speye(Nt) spzeros(Nt,(s-1)*Nt)] # selection matrix
	Fm = full(1/(s*Nt).*S*IDFTm)
    alpha = 0.001
	lambda_max_m = norm(Fm'*y, Inf)
	lambda_m = alpha*lambda_max_m

    F = 1/(s*Nt)*DFT(s*Nt)'[1:Nt] # Abstract Operator
	lambda_max = norm(F'*y, Inf)
	lambda = alpha*lambda_max

	Fc = [real(Fm) -imag(Fm); imag(Fm) real(Fm)]
	# needed in cvxpy (currently does not support complex variables)

	if opt == "MatrixFree"
		setup = K,  F, Fc, lambda, lambda_m
	else
		setup = K, Fm, Fc, lambda, lambda_m
	end
	return setup, t, f, f_s2, fk, ak, s, Nt, fs, xzp, y

end

function run_demo()

    tol = 1e-8
    verb = 1
    solver = PANOC

	setup, t, f, fs, fk, ak, s, Nt, Fs, xzp, y = set_up(opt = "MatrixFree")
	slv = solver(tol = tol, verbose = verb)
	x = init_variable(s*Nt,slv)

	println("Solving LASSO (Abstract Operator)")
	@time solve_problem!(slv, x, y, setup...)
	x1 = copy(~x)

	println("Refine solution by solving non-convex problem (Abstract Operator)")
	@time solve_problem_ncvx!(slv, x, y, setup...)
	x0 = copy(~x)

	slv = solver(tol = tol, verbose = verb)
	setup, t, f, fs, fk, ak, s, Nt, Fs, xzp, y = set_up()
	x0m = init_variable(s*Nt,slv)

	println("Solving LASSO (Matrix Operator)")
	@time solve_problem!(slv, x0m, y, setup...)

	println("Refine solution by solving non-convex problem (Matrix Operator)")
	@time solve_problem_ncvx!(slv, x0m, y, setup...)

	x1 = x1[1:div(s*Nt,2)+1]
	x0 = x0[1:div(s*Nt,2)+1]
	return t, f, fs, fk, ak, s, Nt, Fs, xzp, y, x1, x0
end

function run_demo_Convex()
	slv = ECOSSolver()
	setup, t, f, fs, fk, ak, s, Nt, Fs, xzp, y = set_up()
	x0m = init_variable(s*Nt,slv)

	println("Solving LASSO with Convex.jl (Matrix Operator)")
	@time x0m, = solve_problem!(slv, x0m, y, setup...)

	x1 = x0m.value
	x1 = x1[1:div(s*Nt,2)+1]
	return t, f, fs, fk, ak, s, Nt, Fs, xzp, y, x1, zeros(x1)
end

init_variable(N,slv::S) where {S <: StructuredOptimization.ForwardBackwardSolver} = StructuredOptimization.Variable(Complex{Float64}, N)
init_variable(N,slv::S) where {S <: MathProgBase.SolverInterface.AbstractMathProgSolver} = Convex.ComplexVariable(N)
init_variable(N,slv::S) where {S <: AbstractString} = cvx.Variable(N), cvx.Variable(N)

#StructuredOptimization Matrix Free
function solve_problem!(slv::S, x0, y, K, F::A, Fc, lambda, lambda_m) where {S <: StructuredOptimization.ForwardBackwardSolver, A <: AbstractOperator}
    it, = @minimize ls(F*x0-y)+lambda*norm(x0,1) with slv
	return x0, it
end

function solve_problem_ncvx!(slv::S, x0, y, K, F::A, Fc, lambda, lambda_m) where {S <: StructuredOptimization.ForwardBackwardSolver, A <: AbstractOperator}
	it, = @minimize ls(F*x0-y) st norm(x0,0) <= 2*K with slv
	return x0, it
end

#StructuredOptimization non-Matrix Free
function solve_problem!(slv::S, x0, y, K, F::A, Fc, lambda, lambda_m) where {S <: StructuredOptimization.ForwardBackwardSolver, A <: AbstractMatrix}
    it, = @minimize ls(F*x0-complex(y))+lambda_m*norm(x0,1) with slv
	return x0, it
end

function solve_problem_ncvx!(slv::S, x0, y, K, F::A, Fc, lambda, lambda_m) where {S <: StructuredOptimization.ForwardBackwardSolver, A <: AbstractMatrix}
    it, = @minimize ls(F*x0-complex(y)) st norm(x0,0) <= 2*K with slv
	return x0, it
end

#Convex
function solve_problem!(slv::S, x0, y, K, F, Fc, lambda, lambda_m) where {S <: MathProgBase.SolverInterface.AbstractMathProgSolver}
	problem = minimize(0.5*norm(F*x0-y,2)^2+lambda_m*norm(x0,1))
	Convex.solve!(problem,slv)
	return x0, 0
end

function benchmark(;verb = 0, samples = 5, seconds = 100, tol = 1e-8, maxit = 20000)

	suite = BenchmarkGroup()

	solvers = ["PANOC", "ZeroFPR", "FPG", "PG",]
	slv_opt = ["(verbose = $verb, tol = $tol, maxit = $maxit)",
               "(verbose = $verb, tol = $tol, maxit = $maxit)",
               "(verbose = $verb, tol = $tol, maxit = $maxit)",
               "(verbose = $verb, tol = $tol, maxit = $maxit)",]

	its = Dict([(sol,0.) for sol in solvers])
	for i in eachindex(solvers)

		setup, t, f, fs, fk, ak, s, Nt, Fs, xzp, y = set_up()
		solver = eval(parse(solvers[i]*slv_opt[i]))
		x0 = init_variable(Nt*s,solver)

		suite[solvers[i]] =
		@benchmarkable((x0,it) = solve_problem!(solver, x0, y, setup...),
			       setup = (
					it = 0;
					x0 = deepcopy($x0);
					setup = deepcopy($setup);
					y = $y;
					solver = deepcopy($solver) ),
			       teardown = (
					  $its[$solvers[$i]] = it;
					  ),
			       evals = 1, samples = samples, seconds = seconds)
	end

	results = run(suite, verbose = (verb != 0))
	println("LineSpectraEstimation its")
	println(its)
	return results
end

function benchmarkMatrixFree(;verb = 0, samples = 5, seconds = 100, tol = 1e-8, maxit = 20000)

	suite = BenchmarkGroup()

	solvers = ["PANOC", "ZeroFPR", "FPG", "PG"]
	slv_opt = ["(verbose = $verb, tol = $tol, maxit = $maxit)",
               "(verbose = $verb, tol = $tol, maxit = $maxit)",
               "(verbose = $verb, tol = $tol, maxit = $maxit)",
               "(verbose = $verb, tol = $tol, maxit = $maxit)"]

	its = Dict([(sol,0.) for sol in solvers])
	for i in eachindex(solvers)

		setup, t, f, fs, fk, ak, s, Nt, Fs, xzp, y = set_up(opt = "MatrixFree")
		solver = eval(parse(solvers[i]*slv_opt[i]))
		x0 = init_variable(Nt*s,solver)

		suite[solvers[i]] =
		@benchmarkable((x0,it) = solve_problem!(solver, x0, y, setup...),
			       setup = (
					it = 0;
					x0 = deepcopy($x0);
					setup = deepcopy($setup);
					y = $y;
					solver = deepcopy($solver) ),
			       teardown = (
					  $its[$solvers[$i]] = it;
					  ),
			       evals = 1, samples = samples, seconds = seconds)
	end

	results = run(suite, verbose = (verb != 0))
	println("LineSpectraEstimation (MatrixFree) its")
	println(its)
	return results
end

function show_results(t, f, fs, fk, ak, s, Nt, Fs, xzp, y, x1, x0)

	figure()
	plot(fs,abs.(xzp./Nt ), label = "dft zero pad.")
	plot(f,        abs.(fft(y)./Nt)       , label = "dft")
	plot(fk,       abs.(ak)/2     , "r*", label = "true amp.")
    plot(fs,abs.(x1./(s*Nt)), "k*", label = "LASSO")
    plot(fs,abs.(x0./(s*Nt)), "go", label = "IndBallL0")
	xlim([0;Fs/4])
	legend()

end

end


text:
@system Weather begin
    calendar(context) ~ ::Calendar
    _w: weather_data ~ provide(index=:DATE, init=calendar.date, parameter)

    DATE ~ drive::date(from=_w)

    SRAD: solar_radiation ~ drive(from=_w, u"MJ/m^2/d")
    #PAR(s): photosynthetically_active_radiation ~ drive(from=_w, u"MJ/m^2/d")
    PAR(SRAD): photosynthetically_active_radiation => 0.5SRAD ~ track(u"MJ/m^2/d")

    TMAX: maximum_temperature ~ drive(from=_w, u"°C")
    TMIN: minimum_temperature ~ drive(from=_w, u"°C")
    TMN(TMAX, TMIN): mean_temperature => begin
        # explicit conversion due to strictness of temperature units handling by Unitful.jl
        0.5(u"K"(TMAX) + u"K"(TMIN))
    end ~ track(u"°C")

    RAIN: rainfall ~ drive(from=_w, u"mm/d")
end


text:
using Test
using Manifolds: adbackend, adbackends, adbackend!, _gradient, _jacobian
using LinearAlgebra: Diagonal, dot

@testset "AD backend" begin
    @testset "adbackend" begin
        @test adbackend() == :finitedifferences
        @test adbackend(:default) == :finitedifferences
        @test adbackend(:finitedifferences) == :finitedifferences
        @test adbackends() == [:finitedifferences]

        @test adbackend!(:default) == :finitedifferences
        @test adbackend() == :finitedifferences
        @test adbackend!(:finitedifferences) == :finitedifferences
        @test adbackend() == :finitedifferences
        @test_throws ArgumentError adbackend!(:blah)
        @test_throws ArgumentError adbackend!(:forwarddiff)
    end

    using ForwardDiff

    @testset "forwarddiff" begin
        @test adbackend() == :finitedifferences
        @test adbackends() == [:finitedifferences, :forwarddiff]
        @test adbackend(:forwarddiff) == :forwarddiff

        @test adbackend!(:forwarddiff) == :forwarddiff
        @test adbackend() == :forwarddiff
        @test adbackend!(:finitedifferences) == :finitedifferences
        @test adbackend() == :finitedifferences

        adbackend!(:forwarddiff)
        @test adbackend!(:default) == :forwarddiff
        @test adbackend() == :forwarddiff
        adbackend!(:finitedifferences)
    end

    @testset "gradient/jacobian" begin
        adbackend!(:finitedifferences)
        @testset for backend in [:default, :finitedifferences, :forwarddiff]
            adbackend!(backend)
            @test _gradient(sin, 0.5) ≈ cos(0.5)
            @test _gradient(x -> dot(x, [1.0, 2.0, 3.0]), [4.0, 5.0, 6.0]) ≈ [1.0, 2.0, 3.0]
            J = _jacobian(x -> [x[1], x[2]^2, x[3]^3], [1.0, 2.0, 3.0])
            @test J ≈ collect(Diagonal([1.0, 4.0, 27.0])) atol=1e-6
            J = _jacobian([1.0 2.0; 3.0 4.0]) do x
                return [x[1] x[3]^2; x[2]^2 x[4]^2]
            end
            J = _jacobian([1.0 2.0; 3.0 4.0]) do x
                return [x[1] x[2]^2; x[3]^2 x[4]^2]
            end
            @test J ≈ [1 0 0 0; 0 0 4 0; 0 6 0 0; 0 0 0 8] atol=1e-6
        end
        adbackend!(:finitedifferences)
    end
end


text:
module FastModulo
export Mod,fastmod,fastmod!,divtest

struct Mod
    modulo::UInt32
    modulo_inv::UInt64
    function Mod(d::UInt32)
        cmod::UInt64 = trunc(UInt64,typemax(UInt64) / d) + 1
        return new(d,cmod)
    end
    function Mod(d::Int)
        ud = convert(UInt32, d)
        return Mod(ud)
    end
end

@inline function fastmod(n::UInt32,T::Mod)::UInt32
    lowbits::UInt64 = T.modulo_inv * n
    return unsafe_trunc(UInt32,(unsafe_trunc(UInt128,lowbits) * T.modulo) >> 64)
end

@inline function fastmod(n::Int,T::Mod)
    return fastmod(convert(UInt32,n),T)
end

#not much better than a loop, need avx to support UInt128
function fastmod!(n::Array{UInt32,N},T::Mod) where N
    n .= (convert.(UInt128,(T.modulo_inv .* n)) .* T.modulo) .>> 64
end

@inline @fastmath function divtest(n::UInt32,T::Mod)::Bool
    return (n*T.modulo_inv) <= (T.modulo_inv - 1)
end
@inline function divtest(n::Int,T::Mod)
    return divtest(convert(UInt32,n),T)
end

# struct SignedMod
#     modulo::UInt32
#     modulo_inv::UInt64
#     function SignedMod(d::Int32)
#         pd = d < 0 ? -d : d
#         cmod::UInt64 = div(typemax(UInt64), d) + 1 + ((pd & (pd -1))==0 ? 1 : 0)
#         return new(pd,cmod)
#     end
#     function SignedMod(d::Int)
#         ud = convert(Int32, d)
#         return SignedMod(ud)
#     end
# end

# @inline function fastmod(n::Int,T::SignedMod)
#     return fastmod(convert(Int32,n),T)
# end
# @inline function fastmod(n::Int32,T::SignedMod)::Int32
#     lowbits::UInt64 = T.modulo_inv * n
#     highbits::Int32 = (convert(UInt128,lowbits) * T.modulo) >> 64
#     return convert(Int32,highbits  - ((T.modulo - 1) & (n >> 31)))
# end

end


text:
module STLsTests

using Test
using STLCutters
using Gridap
using Gridap.Geometry
using Gridap.ReferenceFEs

using STLCutters: read_stl
using STLCutters: compute_stl_model
using STLCutters: split_disconnected_parts
using STLCutters: save_as_stl

using STLCutters: is_water_tight
using STLCutters: merge_nodes

using STLCutters: STL

X,T,N = read_stl(joinpath(@__DIR__,"data/cube.stl"))

stlmodel = compute_stl_model(T,X)
@test !is_water_tight(stlmodel)
#writevtk(stl.grid,"cube",cellfields=["normals"=>N])

stl = STL(stlmodel)

@test num_faces(stl) == num_faces(stlmodel)

stlmodel = merge_nodes(stlmodel)
@test is_water_tight(stlmodel)
#writevtk(stl.grid,"cube",cellfields=["normals"=>N])

stl = STL(stlmodel)

@test num_faces(stl) == num_faces(stlmodel)

f = save_as_stl(stlmodel,"_cube")
X1,T1,N1 = read_stl(f)
@test X1 == X
@test T1 == T
@test N1 == N
rm(f)

X,T,N = read_stl(joinpath(@__DIR__,"data/65904.stl"))
stlmodel = compute_stl_model(T,X)
stlmodel = merge_nodes(stlmodel)

stls = split_disconnected_parts(stlmodel)

@test length(stls) == 3
@test sum(num_cells,stls) == num_cells(stlmodel)
@test sum(num_vertices,stls) == num_vertices(stlmodel)

f = save_as_stl(stls,"_65904")

rm.(f)

end # module


text:
function create_bucket_order(bucket)
    groups = [[] for _ in 1:length(bucket)]
    for i in 1:length(bucket)
        push!(groups[bucket[i]], i)
    end

    last_id = sort(unique(bucket),rev=true)[1]

    stat_bucket = ""
    for i in 1:length(bucket)
        if size(groups[i],1) > 0
            for j in 1:size(groups[i],1)
                if j != size(groups[i],1)
                    stat_bucket *= " $(groups[i][j]) ,"
                else
                    if i == last_id
                        stat_bucket *= " $(groups[i][j]) "
                    else
                        stat_bucket *= " $(groups[i][j]) |"
                    end
                end
            end
        end
    end
    return stat_bucket
end

max_stars_repo_name: LuizHNLorena/AbrkgaObop

max_issues_repo_name: LuizHNLorena/AbrkgaObop

max_forks_repo_name: LuizHNLorena/AbrkgaObop


text:
using StaticLint, SymbolServer
using CSTParser, Test
using StaticLint: scopeof, bindingof, refof, errorof, check_all

server = StaticLint.FileServer();

function get_ids(x, ids=[])
    if StaticLint.typof(x) == CSTParser.IDENTIFIER
        push!(ids, x)
    else
        for a in x
            get_ids(a, ids)
        end
    end
    ids
end

function parse_and_pass(s)
    empty!(server.files)
    f = StaticLint.File("", s, CSTParser.parse(s, true), nothing, server)
    StaticLint.setroot(f, f)
    StaticLint.setfile(server, "", f)
    StaticLint.scopepass(f)
    return f.cst
end

function check_resolved(s)
    cst = parse_and_pass(s)
    IDs = get_ids(cst)
    [(refof(i) !== nothing) for i in IDs]
end

@testset "StaticLint" begin

    @testset "Basic bindings" begin

        @test check_resolved("""
x
x = 1
x
""")  == [false, true, true]

        @test check_resolved("""
x, y
x = y = 1
x, y
""")  == [false, false, true, true, true, true]

        @test check_resolved("""
x, y
x, y = 1, 1
x, y
""")  == [false, false, true, true, true, true]

        @test check_resolved("""
M
module M end
M
""")  == [false, true, true]

        @test check_resolved("""
f
f() = 0
f
""")  == [false, true, true]

        @test check_resolved("""
f
function f end
f
""")  == [false, true, true]

        @test check_resolved("""
f
function f() end
f
""")  == [false, true, true]

        @test check_resolved("""
function f(a)
end
""")  == [true, true]

        @test check_resolved("""
f, a
function f(a)
    a
end
f, a
""")  == [false, false, true, true, true, true, false]

        @test check_resolved("""
x
let x = 1
    x
end
x
""")  == [false, true, true, false]

        @test check_resolved("""
x,y
let x = 1, y = 1
    x, y
end
x, y
""")  == [false, false, true, true, true, true, false, false]

        @test check_resolved("""
function f(a...)
    f(a)
end
""")  == [true, true, true, true]

        @test check_resolved("""
for i = 1:1
end
""")  == [true]

        @test check_resolved("""
[i for i in 1:1]
""")  == [true, true]

        @test check_resolved("""
[i for i in 1:1 if i]
""")  == [true, true, true]

# @test check_resolved("""
# @deprecate f(a) sin(a)
# f
# """)  == [true, true, true, true, true, true]

        @test check_resolved("""
@deprecate f sin
f
""")  == [true, true, true, true]

        @test check_resolved("""
module Mod
f = 1
end
using .Mod: f
f
""") == [true, true, true, true, true]

        @test check_resolved("""
module Mod
module SubMod
    f() = 1
end
using .SubMod: f
f
end
""") == [true, true, true, true, true, true]

        @test check_resolved("""
struct T
    field
end
function f(arg::T)
    arg.field
end
""") == [true, true, true, true, true, true, true]

        @test check_resolved("""
f(arg) = arg
""") == [1, 1, 1]

        @test check_resolved("-(r::T) where T = r") == [1, 1, 1, 1]
        @test check_resolved("[k * j for j = 1:10 for k = 1:10]") == [1, 1, 1, 1]
        @test check_resolved("[k * j for j in 1:10 for k in 1:10]") == [1, 1, 1, 1]

        @testset "inference" begin
            @test bindingof(parse_and_pass("f(arg) = arg")[1]).type == StaticLint.CoreTypes.Function
            @test bindingof(parse_and_pass("function f end")[1]).type == StaticLint.CoreTypes.Function
            @test bindingof(parse_and_pass("struct T end")[1]).type == StaticLint.CoreTypes.DataType
            @test bindingof(parse_and_pass("mutable struct T end")[1]).type == StaticLint.CoreTypes.DataType
            @test bindingof(parse_and_pass("abstract type T end")[1]).type == StaticLint.CoreTypes.DataType
            @test bindingof(parse_and_pass("primitive type T 8 end")[1]).type == StaticLint.CoreTypes.DataType
            @test bindingof(parse_and_pass("x = 1")[1][1]).type == StaticLint.CoreTypes.Int
            @test bindingof(parse_and_pass("x = 1.0")[1][1]).type == StaticLint.CoreTypes.Float64
            @test bindingof(parse_and_pass("x = \"text\"")[1][1]).type == StaticLint.CoreTypes.String
            @test bindingof(parse_and_pass("module A end")[1]).type == StaticLint.CoreTypes.Module
            @test bindingof(parse_and_pass("baremodule A end")[1]).type == StaticLint.CoreTypes.Module

    # @test parse_and_pass("function f(x::Int) x end")[1][2][3].binding.t == StaticLint.getsymbolserver(server)["Core"].vals["Function"]
            let cst = parse_and_pass("""
        struct T end
        function f(x::T) x end""")
                @test bindingof(cst[1]).type == StaticLint.CoreTypes.DataType
                @test bindingof(cst[2]).type == StaticLint.CoreTypes.Function
                @test bindingof(cst[2][2][3]).type == bindingof(cst[1])
                @test refof(cst[2][3][1]) == bindingof(cst[2][2][3])
            end
            let cst = parse_and_pass("""
        struct T end
        T() = 1
        function f(x::T) x end""")
                @test bindingof(cst[1]).type == StaticLint.CoreTypes.DataType
                @test bindingof(cst[3]).type == StaticLint.CoreTypes.Function
                @test bindingof(cst[3][2][3]).type == bindingof(cst[1])
                @test refof(cst[3][3][1]) == bindingof(cst[3][2][3])
            end

            let cst = parse_and_pass("""
        struct T end
        t = T()""")
                @test bindingof(cst[1]).type == StaticLint.CoreTypes.DataType
                @test bindingof(cst[2][1]).type == bindingof(cst[1])
            end

            let cst = parse_and_pass("""
        module A
        module B
        x = 1
        end
        module C
        import ..B
        B.x
        end
        end""")
                @test refof(cst[1][3][2][3][2][3][1]) == bindingof(cst[1][3][1][3][1][1])
            end

            let cst = parse_and_pass("""
        struct T0
            x
        end
        struct T1
            field::T0
        end
        function f(arg::T1)
            arg.field.x
        end""");
                @test refof(cst[3][3][1][1][1]) == bindingof(cst[3][2][3])
                @test refof(cst[3][3][1][1][3][1]) == bindingof(cst[2][3][1])
                @test refof(cst[3][3][1][3][1]) == bindingof(cst[1][3][1])
            end

            let cst = parse_and_pass("""
        raw"whatever"
        """)
                @test refof(cst[1][1]) !== nothing
            end
            let cst = parse_and_pass("""
        macro mac_str() end
        mac"whatever"
        """)
                @test refof(cst[2][1]) == bindingof(cst[1])
            end

            let cst = parse_and_pass("""
        [i * j for i = 1:10 for j = i:10]
        """)
                @test refof(cst[1][2][1][3][3][1]) == bindingof(cst[1][2][1][1][3][1])
            end
            let cst = parse_and_pass("""
        [i * j for i = 1:10, j = 1:10 for k = i:10]
        """)
                @test refof(cst[1][2][1][3][3][1]) == bindingof(cst[1][2][1][1][3][1])
            end

            let cst = parse_and_pass("""
        module Reparse
        end
        using .Reparse, CSTParser
        """)
                @test refof(cst[2][3]).val == bindingof(cst[1])
            end

            let cst = parse_and_pass("""
        module A
        A
        end
        """)
                @test scopeof(cst).names["A"] == scopeof(cst[1]).names["A"]
                @test refof(cst[1][2]) == bindingof(cst[1])
                @test refof(cst[1][3][1]) == bindingof(cst[1])
            end
    # let cst = parse_and_pass("""
    #     using Test: @test
    #     """)
    #     @test bindingof(cst[1][4]) !== nothing
    # end
            let cst = parse_and_pass("""
        sin(1,2,3)
        """)
                check_all(cst, StaticLint.LintOptions(:), server)
                @test errorof(cst[1]) === StaticLint.IncorrectCallArgs
            end
            let cst = parse_and_pass("""
        for i in length(1) end
        for i in 1.1 end
        for i in 1 end
        for i in 1:1 end
        """)
                check_all(cst, StaticLint.LintOptions(:), server)
                @test errorof(cst[1][2]) === StaticLint.IncorrectIterSpec
                @test errorof(cst[2][2]) === StaticLint.IncorrectIterSpec
                @test errorof(cst[3][2]) === StaticLint.IncorrectIterSpec
                @test errorof(cst[4][2]) === nothing
            end

            let cst = parse_and_pass("""
        [i for i in length(1) end]
        [i for i in 1.1 end]
        [i for i in 1 end]
        [i for i in 1:1 end]
        """)
                check_all(cst, StaticLint.LintOptions(:), server)
                @test errorof(cst[1][2][3]) === StaticLint.IncorrectIterSpec
                @test errorof(cst[2][2][3]) === StaticLint.IncorrectIterSpec
                @test errorof(cst[3][2][3]) === StaticLint.IncorrectIterSpec
                @test errorof(cst[4][2][3]) === nothing
            end

            let cst = parse_and_pass("a == nothing")
                check_all(cst, StaticLint.LintOptions(:), server)
                @test errorof(cst[1][2]) === StaticLint.NothingEquality
            end

            let cst = parse_and_pass("""
        struct Graph
            children:: T
        end

        function test()
            g = Graph()
            f = g.children
        end""")
                @test cst[2][3][2][3][3][1] in bindingof(cst[1][3][1]).refs
            end

            let cst = parse_and_pass("""
        __source__
        __module__
        macro m()
            __source__
            __module__
        end""")
                @test refof(cst[1]) === nothing
                @test refof(cst[2]) === nothing
                @test refof(cst[3][3][1]) !== nothing
                @test refof(cst[3][3][2]) !== nothing
            end
        end

        @testset "macros" begin
            @test check_resolved("""
    @enum(E,a,b)
    E
    a
    b
    """)  == [true, true, true, true, true, true, true]
        end

        @test check_resolved("""
    @enum E a b
    E
    a
    b
    """)  == [true, true, true, true, true, true, true]

        @test check_resolved("""
    @enum E begin
        a
        b
    end
    E
    a
    b
    """)  == [true, true, true, true, true, true, true]
    end

    @testset "tuple args" begin
        let cst = parse_and_pass("""
        function f((arg1, arg2))
            arg1, arg2
        end""")
            @test StaticLint.hasref(cst[1][3][1][1])
            @test StaticLint.hasref(cst[1][3][1][3])
        end

        let cst = parse_and_pass("""
        function f((arg1, arg2) = (1,2))
            arg1, arg2
        end""")
            @test StaticLint.hasref(cst[1][3][1][1])
            @test StaticLint.hasref(cst[1][3][1][3])
        end

        let cst = parse_and_pass("""
        function f((arg1, arg2)::Tuple{Int,Int})
            arg1, arg2
        end""")
            @test StaticLint.hasref(cst[1][3][1][1])
            @test StaticLint.hasref(cst[1][3][1][3])
        end
    end

    @testset "type params check" begin
        let cst = parse_and_pass("""
        f() where T
        f() where {T,S}
        f() where {T<:Any}
        """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test StaticLint.errorof(cst[1][3]) == StaticLint.UnusedTypeParameter
            @test StaticLint.errorof(cst[2][4]) == StaticLint.UnusedTypeParameter
            @test StaticLint.errorof(cst[2][6]) == StaticLint.UnusedTypeParameter
            @test StaticLint.errorof(cst[3][4]) == StaticLint.UnusedTypeParameter
        end
        let cst = parse_and_pass("""
        f(x::T) where T
        f(x::T,y::S) where {T,S}
        f(x::T) where {T<:Any}
        """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test !StaticLint.haserror(cst[1][3])
            @test !StaticLint.haserror(cst[2][4])
            @test !StaticLint.haserror(cst[2][6])
            @test !StaticLint.haserror(cst[3][4])
        end
    end

    @testset "overwrites_imported_function" begin
        let cst = parse_and_pass("""
        import Base:sin
        using Base:cos
        sin(x) = 1
        cos(x) = 1
        Base.tan(x) = 1
        """)

            @test StaticLint.overwrites_imported_function(bindingof(cst[3]))
            @test !StaticLint.overwrites_imported_function(bindingof(cst[4]))
            @test StaticLint.overwrites_imported_function(bindingof(cst[5]))
        end
    end

    @testset "pirates" begin
        let cst = parse_and_pass("""
        import Base:sin
        struct T end
        sin(x::Int) = 1
        sin(x::T) = 1
        sin(x::Array{T}) = 1
        """)
            StaticLint.check_for_pirates(cst[3])
            StaticLint.check_for_pirates(cst[4])
            @test errorof(cst[3]) === StaticLint.TypePiracy
            @test errorof(cst[4]) === nothing
        end
        let cst = parse_and_pass("""
        struct AreaIterator{T}
            array::AbstractMatrix{T}
            radius::Int
        end
        Base.eltype(::Type{AreaIterator{T}}) where T = Tuple{T, AbstractVector{T}}
        """)
            StaticLint.check_for_pirates(cst[2])
            @test errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        import Base:sin
        abstract type T end
        sin(x::Array{T}) = 1
        sin(x::Array{<:T}) = 1
        sin(x::Array{Number}) = 1
        sin(x::Array{<:Number}) = 1
        """)
            StaticLint.check_for_pirates(cst[3])
            StaticLint.check_for_pirates(cst[4])
            StaticLint.check_for_pirates(cst[5])
            StaticLint.check_for_pirates(cst[6])
            @test errorof(cst[3]) === nothing
            @test errorof(cst[4]) === nothing
            @test errorof(cst[5]) === StaticLint.TypePiracy
            @test errorof(cst[6]) === StaticLint.TypePiracy
        end
        let cst = parse_and_pass("""
        abstract type At end
        struct Ty end
        Base.eltype(::Type{Ty{T}} where {T}) = 1
        Base.length(s::Ty{T} where T <: At) = 1
        """)
            @test StaticLint.check_for_pirates(cst[3]) === nothing
            @test StaticLint.check_for_pirates(cst[4]) === nothing
        end

        let cst = parse_and_pass("""
        !=(a,b) = true
        Base.:!=(a,b) = true
        !=(a::T,b::T) = true
        !=(a::T,b::T) where T= true
        """)
            StaticLint.check_for_pirates.(cst)

            @test errorof(cst[1]) === StaticLint.NotEqDef
            @test errorof(cst[2]) === StaticLint.NotEqDef
            @test errorof(cst[3]) === StaticLint.NotEqDef
            @test errorof(cst[4]) === StaticLint.NotEqDef
        end
    end

    @testset "docs for undescribed variables" begin
        let cst = parse_and_pass("""
    \"\"\"
        somefunc() = true
    \"\"\"
    somefunc
    somefunc() = true
    """)
            @test StaticLint.hasref(cst[1][3])
            @test StaticLint.hasbinding(cst[1][3])
            @test refof(cst[1][3]) == bindingof(cst[1][3])
        end
    end

    @testset "check_call" begin
        let cst = parse_and_pass("""
        sin(1)
        sin(1,2)
        """)
            StaticLint.check_call(cst[1], server)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[1]) === nothing
            @test StaticLint.errorof(cst[2]) == StaticLint.IncorrectCallArgs
        end

        let cst = parse_and_pass("""
        Base.sin(a,b) = 1
        function Base.sin(a,b)
            1
        end
        """)
            StaticLint.check_call(cst[1][1], server)
            @test StaticLint.errorof(cst[1][1]) === nothing
            StaticLint.check_call(cst[2][2], server)
            @test StaticLint.errorof(cst[2][2]) === nothing
        end

        let cst = parse_and_pass("""
        f(x) = 1
        f(1, 2)
        """)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === StaticLint.IncorrectCallArgs
        end

        let cst = parse_and_pass("""
        view([1], 1, 2, 3)
        """)
            StaticLint.check_call(cst[1], server)
            @test StaticLint.errorof(cst[1]) === nothing
        end

        let cst = parse_and_pass("""
        f(a...) = 1
        f(1)
        f(1, 2)
        """)
            StaticLint.check_call(cst[2], server)
            StaticLint.check_call(cst[3], server)
            @test StaticLint.errorof(cst[2]) === nothing
            @test StaticLint.errorof(cst[3]) === nothing
        end
        let cst = parse_and_pass("""
        function func(a, b)
            func(a...)
        end
        """)
            StaticLint.check_call(cst[1][3][1], server)
            m_counts = StaticLint.func_nargs(cst[1])
            call_counts = StaticLint.call_nargs(cst[1][3][1])
            @test StaticLint.errorof(cst[1][3][1]) === nothing
        end
        let cst = parse_and_pass("""
        function func(@nospecialize args...) end
        func(1, 2)
        """)
            @test StaticLint.func_nargs(cst[1]) == (0, typemax(Int), String[], false)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        argtail(x, rest...) = 1
        tail(x::Tuple) = argtail(x...)
        """)
            @test StaticLint.func_nargs(cst[1]) == (1, typemax(Int), String[], false)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        func(arg::Vararg{T,N}) where N = arg
        func(a,b)
        """)

            @test StaticLint.func_nargs(cst[1]) == (0, typemax(Int), String[], false)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        function f(a, b; kw = kw) end
        f(1,2, kw = 1)
        """)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        func(a,b,c,d) = 1
        func(a..., 2)
        """)
            StaticLint.call_nargs(cst[2])
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        @kwdef struct A
            x::Float64
        end
        A(x = 5.0)
        """)
            StaticLint.check_call(cst[2], server)
            @test StaticLint.errorof(cst[2]) === nothing
        end
        let cst = parse_and_pass("""
        import Base: sin
        \"\"\"
        docs
        \"\"\"
        sin
        sin(a,b) = 1
        sin(1)
        """)
        # Checks that documented symbols are skipped
            StaticLint.check_all(cst, StaticLint.LintOptions(), server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
        let cst = parse_and_pass("""
        import Base: sin
        sin(a,b) = 1
        sin(1)
        """)
        # Checks that documented symbols are skipped
            StaticLint.check_all(cst, StaticLint.LintOptions(), server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
        let cst = parse_and_pass("""
            function f(a::F)::Bool where {F} end
            """)
            # ensure we strip all type decl code from around signature
            StaticLint.check_all(cst, StaticLint.LintOptions(), server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
    end

    @testset "check_modulename" begin
        let cst = parse_and_pass("""
        module Mod1
        module Mod11
        end
        end
        module Mod2
        module Mod2
        end
        end
        """)
            StaticLint.check_modulename(cst[1])
            StaticLint.check_modulename(cst[1][3][1])
            StaticLint.check_modulename(cst[2])
            StaticLint.check_modulename(cst[2][3][1])

            @test StaticLint.errorof(cst[1][2]) === nothing
            @test StaticLint.errorof(cst[1][3][1][2]) === nothing
            @test StaticLint.errorof(cst[2][2]) === nothing
            @test StaticLint.errorof(cst[2][3][1][2]) === StaticLint.InvalidModuleName
        end
    end

    if !(VERSION < v"1.3")
        @testset "non-std var syntax" begin
            let cst = parse_and_pass("""
        var"name" = 1
        var"func"(arg) = arg
        function var"func1"() end
        name
        func
        func1
        """)
                StaticLint.collect_hints(cst, server)
                @test all(n in keys(cst.meta.scope.names) for n in ("name", "func"))
                @test StaticLint.hasref(cst[4])
                @test StaticLint.hasref(cst[5])
                @test StaticLint.hasref(cst[6])
            end
        end
    end

    if false # Not to be run, requires JuMP
        @testset "JuMP macros" begin
            let cst = parse_and_pass("""
    using JuMP
    model = Model()
    some_bound = 1
    @variable(model, x0)
    @variable(model, x1, somekw=1)
    @variable(model, x2 <= 1)
    @variable(model, x3 >= 1)
    @variable(model, 1 <= x4)
    @variable(model, 1 >= x5)
    @variable(model, x6 >= some_bound)
    # @variable(model, some_bound >= x7)
    """)
                @test isempty(StaticLint.collect_hints(cst, server))
            end

            let cst = parse_and_pass("""
    using JuMP
    model = Model()
    some_bound = 1
    @variable model x0
    @variable model x1 somekw=1
    @variable model x2 <= 1
    @variable model x3 >= 1
    @variable model 1 <= x4
    @variable model 1 >= x5
    @variable model x6 >= some_bound
    # @variable(model, some_bound >= x7)
    """)
                @test isempty(StaticLint.collect_hints(cst, server))
            end

            let cst = parse_and_pass("""
    using JuMP
    model = Model()
    some_bound = 1
    @variable(model, some_bound >= x7)
    """)
                @test !StaticLint.hasref(cst[4][5][3])
            end

            let cst = parse_and_pass("""
    using JuMP
    model = Model()
    some_bound = 1
    @expression(model, ex, some_bound >= 1)
    """)
                @test isempty(StaticLint.collect_hints(cst, server))
            end

            let cst = parse_and_pass("""
    using JuMP
    model = Model()
    @expression(model, expr, 1 == 1)
    @constraint(model, con1, expr)
    @constraint model con2 expr
    """)
                @test isempty(StaticLint.collect_hints(cst, server))
            end
        end
    end

    @testset "stdcall" begin
        let cst = parse_and_pass("""
        ccall(:GetCurrentProcess, stdcall, Ptr{Cvoid}, ())""")
            StaticLint.collect_hints(cst, server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
        let cst = parse_and_pass("""
        stdcall
        """)
            @test !StaticLint.hasref(cst[1])
        end
    end

    @testset "check_if_conds" begin
        let cst = parse_and_pass("""
        if true end
        """)
            StaticLint.check_if_conds(cst[1])
            @test cst[1][2].meta.error == StaticLint.ConstIfCondition
        end
        let cst = parse_and_pass("""
        if x = 1 end
        """)
            StaticLint.check_if_conds(cst[1])
            @test cst[1][2].meta.error == StaticLint.EqInIfConditional
        end
        let cst = parse_and_pass("""
        if a || x = 1 end
        """)
            StaticLint.check_if_conds(cst[1])
            @test cst[1][2].meta.error == StaticLint.EqInIfConditional
        end
        let cst = parse_and_pass("""
        if x = 1 && b end
        """)
            StaticLint.check_if_conds(cst[1])
            @test cst[1][2].meta.error == StaticLint.EqInIfConditional
        end
    end

    @testset "check_farg_unused" begin
        let cst = parse_and_pass("function f(arg1, arg2) arg1 end")
            StaticLint.check_farg_unused(cst[1])
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[3]) === nothing
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[5]) === StaticLint.UnusedFunctionArgument
        end
        let cst = parse_and_pass("function f(arg1::T, arg2::T) arg1 end")
            StaticLint.check_farg_unused(cst[1])
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[3]) === nothing
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[5]) === StaticLint.UnusedFunctionArgument
        end
        let cst = parse_and_pass("function f(arg1, arg2::T, arg3 = 1, arg4::T = 1) end")
            StaticLint.check_farg_unused(cst[1])
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[3]) === StaticLint.UnusedFunctionArgument
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[5]) === StaticLint.UnusedFunctionArgument
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[7][1]) === StaticLint.UnusedFunctionArgument
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[9][1]) === StaticLint.UnusedFunctionArgument
        end
        let cst = parse_and_pass("function f(arg) arg = 1 end")
            StaticLint.check_farg_unused(cst[1])
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[3]) === nothing
        end
        let cst = parse_and_pass("function f(arg) 1 end")
            StaticLint.check_farg_unused(cst[1])
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[3]) === nothing
        end
        let cst = parse_and_pass("f(arg) = true")
            StaticLint.check_farg_unused(cst[1])
            @test StaticLint.errorof(CSTParser.get_sig(cst[1])[3]) === nothing
        end
        let cst = parse_and_pass("func(@nospecialize(arg)) = arg")
            StaticLint.check_farg_unused(cst[1])
            @test cst[1].args[1].args[3].meta.error === nothing
        end
    end

    @testset "check redefinition of const" begin
        let cst = parse_and_pass("""
        T = 1
        struct T end
        """)
            StaticLint.check_const_decl(cst[2])
            @test cst[2].meta.error == StaticLint.CannotDeclareConst
        end
        let cst = parse_and_pass("""
        struct T end
        T = 1
        """)
            StaticLint.check_const_redef(cst[2][1])
            @test cst[2][1].meta.error == StaticLint.InvalidRedefofConst
        end
        let cst = parse_and_pass("""
        struct T end
        T() = 1
        """)
            StaticLint.check_const_redef(cst[2])
            @test cst[2].meta.error === nothing
        end
    end

    @testset "hoisting of inner constructors" begin
        let cst = parse_and_pass("""
        struct ASDF
            x::Int
            y::Int
            ASDF(x::Int) = new(x, 1)
        end
        ASDF() = something
        """)
            @test bindingof(cst[1]) === bindingof(cst[1][3][3]).prev
            @test bindingof(cst[1][3][3]) === bindingof(cst[2]).prev
        end
    end

    @testset "using statements" begin # e.g. `using StaticLint: StaticLint`
        let cst = parse_and_pass("""
        using Base.Filesystem: Filesystem
        """)
            @test StaticLint.hasref(cst[1][6])
        end
        let cst = parse_and_pass("""
            using Base: Ordering
            """)
            @test StaticLint.hasbinding(cst[1][4])
        end
        let cst = parse_and_pass("""
            module Outer
            module Inner
            x = 1
            export x
            end
            using .Inner
            end
            using .Outer: x, rand
            """)
            @test StaticLint.hasbinding(cst[2][5])
            @test StaticLint.hasbinding(cst[2][7])
        end
    end

    @testset "don't report unknown getfields when a custom getproperty is defined" begin # e.g. `using StaticLint: StaticLint`
        let cst = parse_and_pass("""
        struct T end
        Base.getproperty(x::T, s) = 1
        T
        """)
            @test StaticLint.has_getproperty_method(bindingof(cst[1]))
            @test StaticLint.has_getproperty_method(refof(cst[3]))
        end
        let cst = parse_and_pass("""
        struct T
            f1
            f2
        end
        Base.getproperty(x::T, s) = 1
        f(x::T) = x.f3
        """)
            @test !StaticLint.hasref(cst[3][3][1][3][1])
            @test isempty(StaticLint.collect_hints(cst, server))
        end
        let cst = parse_and_pass("""
        struct T{S}
            f1
            f2
        end
        Base.getproperty(x::T{Int}, s) = 1
        f(x::T) = x.f3
        """)
            @test !StaticLint.hasref(cst[3][3][1][3][1])
            @test StaticLint.is_type_of_call_to_getproperty(cst[2][1][3][3][1])
            @test isempty(StaticLint.collect_hints(cst, server))
        end

        let cst = parse_and_pass("""
        f(x::Module) = x.parent1
        """)
            @test StaticLint.has_getproperty_method(server.symbolserver[:Core][:Module], server)
            @test !StaticLint.has_getproperty_method(server.symbolserver[:Core][:DataType], server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
        let cst = parse_and_pass("""
        f(x::DataType) = x.sdf
        """)
            @test !isempty(StaticLint.collect_hints(cst, server))
        end
    end
    @testset "using of self" begin # e.g. `using StaticLint: StaticLint`
        let cst = parse_and_pass("""
        function f(a::rand) a end
        function f(a::Base.rand) a end
        function f(a::Int) a end
        Base.Int32(x) = 1
        function f(a::Int32) a end
        Base.fetch(x) = 1
        function f(a::fetch) a end
        """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test errorof(cst[1][2][3]) === StaticLint.InvalidTypeDeclaration
            @test errorof(cst[2][2][3]) === StaticLint.InvalidTypeDeclaration
            @test errorof(cst[3][2][3]) === nothing
            @test errorof(cst[5][2][3]) === nothing
            @test errorof(cst[7][2][3]) === StaticLint.InvalidTypeDeclaration
        end

        @testset "interpret @eval" begin # e.g. `using StaticLint: StaticLint`
            let cst = parse_and_pass("""
        let
            @eval adf = 1
        end
        """)
                @test StaticLint.scopehasbinding(scopeof(cst), "adf")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "adf")
            end
            let cst = parse_and_pass("""
        let
            @eval a,d,f = 1,2,3
        end
        """)
                @test StaticLint.scopehasbinding(scopeof(cst), "a")
                @test StaticLint.scopehasbinding(scopeof(cst), "d")
                @test StaticLint.scopehasbinding(scopeof(cst), "f")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "a")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "d")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "f")
            end
            let cst = parse_and_pass("""
        let
            @eval a = 1
            @eval d = 2
            @eval f = 3
        end
        """)
                @test StaticLint.scopehasbinding(scopeof(cst), "a")
                @test StaticLint.scopehasbinding(scopeof(cst), "d")
                @test StaticLint.scopehasbinding(scopeof(cst), "f")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "a")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "d")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "f")
            end

            let cst = parse_and_pass("""
        let name = :adf
            @eval \$name = 1
        end
        """)
                @test StaticLint.scopehasbinding(scopeof(cst), "adf")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "adf")
            end
            let cst = parse_and_pass("""
        let name = [:adf]
            @eval \$name = 1
        end
        """)
                @test !StaticLint.scopehasbinding(scopeof(cst), "adf")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "adf")
            end

            let cst = parse_and_pass("""
        for name = [:adf, :asdf, :asdfs]
            @eval \$name = 1
        end
        """)
                @test StaticLint.scopehasbinding(scopeof(cst), "adf")
                @test StaticLint.scopehasbinding(scopeof(cst), "asdf")
                @test StaticLint.scopehasbinding(scopeof(cst), "asdfs")
            end
            let cst = parse_and_pass("""
        for name = (:adf, :asdf, :asdfs)
            @eval \$name = 1
        end
        """)
                @test StaticLint.scopehasbinding(scopeof(cst), "adf")
                @test StaticLint.scopehasbinding(scopeof(cst), "asdf")
                @test StaticLint.scopehasbinding(scopeof(cst), "asdfs")
            end
            let cst = parse_and_pass("""
        let name = :adf
            @eval \$name(x) = 1
        end
        adf(1,2)
        """)
                StaticLint.check_all(cst, StaticLint.LintOptions(), server)
                @test StaticLint.scopehasbinding(scopeof(cst), "adf")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "adf")
                @test errorof(cst[2]) === StaticLint.IncorrectCallArgs
            end
            let cst = parse_and_pass("""
        for name in (:sdf, :asdf)
            @eval \$name(x) = 1
        end
        sdf(1,2)
        """)
                StaticLint.check_all(cst, StaticLint.LintOptions(), server)
                @test StaticLint.scopehasbinding(scopeof(cst), "sdf")
                @test !StaticLint.scopehasbinding(scopeof(cst[1]), "asdf")
                @test errorof(cst[2]) === StaticLint.IncorrectCallArgs
            end
        end
    end

    @testset "check for " begin # e.g. `using StaticLint: StaticLint`
        let cst = parse_and_pass("""
        module A
        module B
        struct T end
        end
        using .B
        function T(t::B.T)
        end
        end
        """)
            @test bindingof(cst[1][3][3]) != refof(cst[1][3][3][2][3][3][3][1])
            @test bindingof(cst[1][3][1][3][1]) == refof(cst[1][3][3][2][3][3][3][1])
        end
    end
    @testset "misc" begin # e.g. `using StaticLint: StaticLint`
        let cst = parse_and_pass("""
        import Base: Bool
        function Bool(x) x end
        ^(z::Complex, n::Bool) = n ? z : one(z)
        """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
        let cst = parse_and_pass("""
        (rand(d::Vector{T})::T) where {T}  =  1
        """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
    end
    @testset "Test self" begin
        empty!(server.files)
        f = StaticLint.loadfile(server, joinpath(@__DIR__, "..", "src", "StaticLint.jl"))
        StaticLint.scopepass(f)
    end

    let cst = parse_and_pass("""
    using Base.@irrational
    @irrational ase 0.45343 π
    ase
    """)
        StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
        @test isempty(StaticLint.collect_hints(cst, server))
    end

    @testset "quoted getfield" begin
        let cst = parse_and_pass("""
    Base.:sin
    """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test isempty(StaticLint.collect_hints(cst[1], server))
        end
        @testset "quoted getfield" begin
            let cst = parse_and_pass("""
        Base.:sin
        """)
                StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
                @test isempty(StaticLint.collect_hints(cst[1], server))
            end

            let cst = parse_and_pass("""
        sin(1,1)
        Base.sin(1,1)
        Base.:sin(1,1)
        """)
                StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
                @test errorof(cst[1]) === errorof(cst[2]) === errorof(cst[3])
            end
        end
        @testset "overloading" begin
    # overloading of a function that happens to be exported into the current scope.
            let cst = parse_and_pass("""
        Base.sin() = nothing
        sin()
        """)
                @test haskey(cst.meta.scope.names, "sin") #
                @test cst.meta.scope.names["sin"].prev == server.symbolserver[:Base][:sin]
                StaticLint.check_call(cst[2], server)
                @test isempty(StaticLint.collect_hints(cst, server))
            end
    # As above but for user defined function
            let cst = parse_and_pass("""
        module M
        f(x) = nothing
        end
        M.f(a,b) = nothing
        M.f(1,2)
        """)
                @test !haskey(cst.meta.scope.names, "f")
                StaticLint.check_call(cst[3], server)
                @test errorof(cst[3]) === nothing
            end

            let cst = parse_and_pass("""
    sin(1,1)
    Base.sin(1,1)
    Base.:sin(1,1)
    """)
                StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
                @test errorof(cst[1]) === errorof(cst[2]) === errorof(cst[3])
            end
        end
    # Non exported function is overloaded
        let cst = parse_and_pass("""
        Base.argtail() = nothing
        Base.argtail()
        """)
            @test !haskey(cst.meta.scope.names, "argtail") #
            StaticLint.check_call(cst[2], server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end
    # As above but for user defined function
        let cst = parse_and_pass("""
        module M
        ff(x) = nothing
        end
        M.ff() = nothing
        M.ff()
        """)
            @test !haskey(cst.meta.scope.names, "ff") #
            StaticLint.check_call(cst[3], server)
            @test isempty(StaticLint.collect_hints(cst, server))
        end

        let cst = parse_and_pass("""
        import Base:argtail
        Base.argtail() = nothing
        Base.argtail()
        argtail()
        """)

            @test cst.meta.scope.names["argtail"] === bindingof(cst[2])
            @test bindingof(cst[2]).prev == bindingof(cst[1][4])
            @test refof(cst[3][1][3][1]) === bindingof(cst[2])
            StaticLint.check_call(cst[3], server)
            StaticLint.check_call(cst[4], server)
            @test isempty(StaticLint.collect_hints(cst, server))

        end
    end

    @testset "on demand resolving of export statements" begin
        let cst = parse_and_pass("""
            module TopModule
            abstract type T end
            export T
            module SubModule
            using ..TopModule
            T
            end
            end""")
            @test refof(cst[1][3][3][3][2]) !== nothing
        end
    end

    @testset "check kw default definition" begin
        function kw_default_ok(s)
            cst = parse_and_pass(s)
            StaticLint.check_kw_default(cst[1][3], server)
            @test errorof(cst[1][3][3]) === nothing
        end
        function kw_default_notok(s)
            cst = parse_and_pass(s)
            StaticLint.check_kw_default(cst[1][3], server)
            @test errorof(cst[1][3][3]) == StaticLint.KwDefaultMismatch
        end

        kw_default_ok("f(x::Float64 = 0.1)")
        kw_default_ok("f(x::Float64 = f())")
        kw_default_ok("f(x::Float32 = f())")
        kw_default_ok("f(x::Float32 = 3f0")
        kw_default_ok("f(x::Float32 = 3_0f0")
        kw_default_ok("f(x::Float32 = 0f00")
        kw_default_ok("f(x::Float32 = -0f02")
        kw_default_ok("f(x::Float32 = Inf32")
        kw_default_ok("f(x::Float32 = 30f3")
        kw_default_ok("f(x::String = \"1\")")
        kw_default_ok("f(x::String = f())")
        kw_default_ok("f(x::Symbol = :x")
        kw_default_ok("f(x::Symbol = f()")
        kw_default_ok("f(x::Char = 'a'")
        kw_default_ok("f(x::Bool = true")
        kw_default_ok("f(x::Bool = false")
        kw_default_ok("f(x::UInt8 = 0b0100_0010")
        kw_default_ok("f(x::UInt16 = 0b0000_0000_0000")
        kw_default_ok("f(x::UInt32 = 0b00000000000000000000000000000000")
        kw_default_ok("f(x::UInt8 = 0o000")
        kw_default_ok("f(x::UInt16 = 0o0_0_0_0_0_0")
        kw_default_ok("f(x::UInt32 = 0o000000000")
        kw_default_ok("f(x::UInt64 = 0o000_000_000_000_0")
        kw_default_ok("f(x::UInt8 = 0x0")
        kw_default_ok("f(x::UInt16 = 0x0000")
        kw_default_ok("f(x::UInt32 = 0x00000")
        kw_default_ok("f(x::UInt32 = -0x00000")
        kw_default_ok("f(x::UInt64 = 0x0000_0000_0")
        kw_default_ok("f(x::UInt128 = 0x00000000_00000000_00000000_00000000")
        kw_default_ok("f(x::UInt128 = 0x00000000_00000000_00000000_00000000")
        if Sys.WORD_SIZE == 64
            kw_default_ok("f(x::Int64 = 0")
            kw_default_ok("f(x::UInt = 0x0000_0000_0")
        else
            kw_default_ok("f(x::Int32 = 0")
            kw_default_ok("f(x::UInt = 0x0000_0")
        end
        kw_default_ok("f(x::Int = 1)")
        kw_default_ok("f(x::Int = f())")
        kw_default_ok("f(x::Int8 = Int8(0)")
        kw_default_ok("f(x::Int8 = convert(Int8,0)")

        if Sys.WORD_SIZE == 64
            kw_default_notok("f(x::Int8 = 0")
            kw_default_notok("f(x::Int16 = 0")
            kw_default_notok("f(x::Int32 = 0")
            kw_default_notok("f(x::Int64 = 0x0000_0000_0")
            kw_default_notok("f(x::Int128 = 0")
        else
            kw_default_notok("f(x::Int8 = 0")
            kw_default_notok("f(x::Int16 = 0")
            kw_default_notok("f(x::Int32 = 0x0000_0")
            kw_default_notok("f(x::Int64 = 0")
            kw_default_notok("f(x::Int128 = 0")
        end
        kw_default_notok("f(x::Int8 = 0000_0000")
        kw_default_notok("f(x::Int16 = 0000_0000")
        kw_default_notok("f(x::Int128 = 0000_0000")
        kw_default_notok("f(x::Float64 = 1)")
        kw_default_notok("f(x::Float32 = 3.4")
        kw_default_notok("f(x::Float32 = -23.")
        kw_default_notok("f(x::Int = 0.1)")
        kw_default_notok("f(x::String = 0.1)")
        kw_default_notok("f(x::Symbol = \"a\"")
        kw_default_notok("f(x::Char = \"a\"")
        kw_default_notok("f(x::Bool = 1")
        kw_default_notok("f(x::Bool = 0x01")
        kw_default_notok("f(x::UInt8 = 0b000000000")
        kw_default_notok("f(x::UInt16 = 0b0000_0000_0000_0000_0")
        kw_default_notok("f(x::UInt32 = 0b0")
        kw_default_notok("f(x::UInt64 = 0b0_0")
        kw_default_notok("f(x::UInt128 = 0b0")
        kw_default_notok("f(x::UInt8 = 0o0000")
        kw_default_notok("f(x::UInt16 = 0o0")
        kw_default_notok("f(x::UInt32 = 0o00000000000000")
        kw_default_notok("f(x::UInt64 = 0o0_0")
        kw_default_notok("f(x::UInt128 = 0o00")
        kw_default_notok("f(x::UInt8 = 0x000")
        kw_default_notok("f(x::UInt16 = 0x00000")
        kw_default_notok("f(x::UInt32 = 0x0000_00_000")
        kw_default_notok("f(x::UInt64 = 0x000_0_0")
        kw_default_notok("f(x::UInt128 = 0x000000")
    end

    @testset "check_use_of_literal" begin
        let cst = parse_and_pass("""
            module \"a\" end
            abstract type \"\"\"123\"\"\" end
            primitive type 1 8 end
            struct 1.0 end
            mutable struct 'a' end
            1 = 1
            f(true = 1)
            123::123
            123 isa false
            """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test errorof(cst[1][2]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[2][3]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[3][3]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[4][2]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[5][3]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[6][1]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[7][3][1]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[8][3]) === StaticLint.InappropriateUseOfLiteral
            @test errorof(cst[9][3]) === StaticLint.InappropriateUseOfLiteral
        end
    end

    @testset "check_break_continue" begin
        let cst = parse_and_pass("""
            for i = 1:10
                continue
            end
            break
            """)
            StaticLint.check_all(cst, StaticLint.LintOptions(:), server)
            @test errorof(cst[1][3][1]) === nothing
            @test errorof(cst[2]) === StaticLint.ShouldBeInALoop
        end
    end

    @testset "@." begin
        let cst = parse_and_pass("@. a + b")
            @test StaticLint.hasref(cst[1][1][2])
        end
    end

    @testset "issue 1609" begin
        let
            cst1 = parse_and_pass("function g(@nospecialize(x), y) x + y end")
            cst2 = parse_and_pass("function g(@nospecialize(x), y) y end")
            StaticLint.check_all(cst1, StaticLint.LintOptions(), server)
            StaticLint.check_all(cst2, StaticLint.LintOptions(), server)
            @test !StaticLint.haserror(cst1[1][2][3][3])
            @test StaticLint.haserror(cst2[1][2][3][3])
        end
    end
end


text:
urlinks = ["https://images.wallpaperscraft.com/image/man_paint_sky_129261_320x480.jpg",
    "https://images.wallpaperscraft.com/image/zhang_bin_girl_art_wind_100944_320x480.jpg",
    "https://images.wallpaperscraft.com/image/girl_art_brush_128328_320x480.jpg",
    "https://images.wallpaperscraft.com/image/landscape_art_moon_127187_320x480.jpg",
    "https://images.wallpaperscraft.com/image/landscape_art_trees_132641_320x480.jpg",
    "https://images.wallpaperscraft.com/image/kimi_no_tonari_de_koishiteru_hoshino_nagisa_girl_school_uniform_101974_320x480.jpg",
    "https://images.wallpaperscraft.com/image/girl_anime_sadness_127305_320x480.jpg",
    "https://images.wallpaperscraft.com/image/anime_girl_wings_angel_persons_profile_13291_320x480.jpg",
    "https://images.wallpaperscraft.com/image/night_room_girls_friends_things_computer_drinks_lamp_shelves_tv_87239_320x480.jpg",
    "https://images.wallpaperscraft.com/image/bleach_naruto_naruto_vs_ichigo_crossover_naruto_shippuden_93631_320x480.jpg",
    "https://images.wallpaperscraft.com/image/silhouette_art_sky_129925_320x480.jpg",
    "https://images.wallpaperscraft.com/image/anime_couple_love_bed_88134_320x480.jpg",
    "https://images.wallpaperscraft.com/image/art_lm7_op_center_girl_katana_weapons_hat_smiley_anime_94028_320x480.jpg",
    "https://images.wallpaperscraft.com/image/vocaloid_hatsune_miku_girl_microphone_tie_song_35368_320x480.jpg",
    "https://images.wallpaperscraft.com/image/asuna_yuuki_sword_art_online_sword_art_online_ii_113741_320x480.jpg"]
urlTop = [
    "https://images.wallpaperscraft.com/image/attack_on_titan_eren_jaeger_shingeki_no_kyojin_104200_320x480.jpg",
    "https://images.wallpaperscraft.com/image/fullmetal_alchemist_edward_alphonse_boys_blondes_pigeons_smiles_29947_320x480.jpg",
    "https://images.wallpaperscraft.com/image/naruto_uzumaki_naruto_ninja_113276_320x480.jpg",
    "https://images.wallpaperscraft.com/image/dragon_ball_z_goku_aggression_guy_102646_320x480.jpg",
    "https://images.wallpaperscraft.com/image/fairy_tail_loke_guy_glasses_107942_320x480.jpg",
    "https://images.wallpaperscraft.com/image/sword_art_online_yuuki_asuna_girl_elf_104363_320x480.jpg",
    "https://images.wallpaperscraft.com/image/bleach_ichigo_bankai_72081_320x480.jpg",
    "https://images.wallpaperscraft.com/image/code_geass_boy_girl_smile_costumes_27609_320x480.jpg",
    "https://images.wallpaperscraft.com/image/saipaco_makise_kurisu_girl_brunette_shirt_tie_shorts_35369_320x480.jpg",
    "https://images.wallpaperscraft.com/image/anime_blue_exorcist_ao_no_exorcist_rin_okumura_28370_320x480.jpg",
    "https://images.wallpaperscraft.com/image/death_note_boy_brunette_space_36764_320x480.jpg",
    "https://images.wallpaperscraft.com/image/chelsea_akame_ga_kill_anime_girl_face_102715_320x480.jpg",
    "https://images.wallpaperscraft.com/image/attack_of_the_titans_pokemon_pikachu_art_98697_320x480.jpg",
    "https://images.wallpaperscraft.com/image/inuyasha_kagome_girl_brunette_dream_tree_41238_320x480.jpg",
    "https://images.wallpaperscraft.com/image/girl_school_classroom_desk_briefcase_smile_12112_320x480.jpg",
    "https://images.wallpaperscraft.com/image/one_punch_man_saitama_character_113257_320x480.jpg",
    "https://images.wallpaperscraft.com/image/fate_zero_boy_girl_walking_street_25212_320x480.jpg",
    "https://images.wallpaperscraft.com/image/elfen_lied_girl_jewelry_box_look_street_27850_320x480.jpg",
    "https://images.wallpaperscraft.com/image/evangelion_girl_sky_pose_costume_gesture_25523_320x480.jpg",
    "https://images.wallpaperscraft.com/image/fate_stay_night_girl_blond_nice_sword_25595_320x480.jpg"
];

max_stars_repo_name: lazarusA/helpfulJulia

max_issues_repo_name: lazarusA/helpfulJulia

max_forks_repo_name: lazarusA/helpfulJulia


text:
import Base.show

function padZeroCols(x::Matrix, desiredSize::Int)
  @assert size(x, 2) <= desiredSize

  n = size(x, 1)

  if size(x, 2) == desiredSize
    return x
  else
    return padZeroCols([x zeros(n)], desiredSize)
  end
end

#= Test
padZeroCols(randn(3,5), 10)
=#

"""
Do `expr` if `condition` holds.
"""
macro doIf(condition, expr)
  return quote
    if $(esc(condition))
      $(esc(expr))
    end
  end
end

# Pretty printing of InverseGamma
function show(io::IO, x::Distributions.InverseGamma)
  print(io, "InverseGamma(shape=$(shape(x)), scale=$(scale(x)))")
end

# Pretty printing of Gamma
function show(io::IO, x::Distributions.Gamma)
  print(io, "Gamma(shape=$(shape(x)), rate=$(rate(x)))")
end

"""
log info with println and flush
"""
function logger(x; newline=true)
  if newline
    println(x)
  else
    print(x)
  end
  flush(stdout)
end

"""
solve for inverse gamma parameters
"""
function solve_ig_params(; mu::Float64, sig2::Float64)
  @assert mu > 0
  @assert sig2 > 0
  a = (mu^2 / sig2) + 2
  b = mu * (a - 1)
  return (a, b)
end

"""
sample from inverse gamma with an upper truncation point
"""
function rand_uptrunc_ig(ig::InverseGamma, upper::Float64)
  lg_u_max = logcdf(ig, upper)
  lg_u = log(rand()) + lg_u_max
  init = upper / 2.0
  return invlogcdf(ig, lg_u)
end

#= Test
ig = InverseGamma(1002, 1001)
mean(ig), std(ig)
@time x = [rand_uptrunc_ig(ig, .3) for i in 1:10000];
=#

"""
Read CB data from a text file.
Text file must have following properties:
- first line is: "N: N1 N2 N3"
- second line is the name of the markers separated by a single space
- the remainder of the file is the marker expression levels for each cell
  by sample. No line breaks are necessary between samples. Each line should
  contain expression levels for each cell equal to the number of markers.

Usage
=====

y  = loadCB(path_to_data)
"""
function loadCB(path_to_data; ElType::Type=Float64)
  return open(path_to_data) do f
    # read number of cells in first line
    N = readline(f)
    N = split(N)[2:end]
    N = parse.(Int, N)

    # Number of samples
    I = length(N)

    # Read marker names
    markers = split(readline(f))

    # Read data into separate samples
    y = [begin
           yi = Vector{ElType}[]
           for _ in 1:N[i]
             line = split(readline(f))
             line = [replace(obs, "NA" => "NaN") for obs in line]
             line = parse.(ElType, line)
             append!(yi, [line])
           end
           Matrix(hcat(yi...)')
         end for i in 1:I]

    return y
  end
end