text:
# Allocation free reshaping (cf. Issue #36313)
_no_alloc_reshape(a, dims) = invoke(Base._reshape, Tuple{AbstractArray,typeof(dims)}, a, dims)

# NOTE: hack _setindex from Base to improve type stability (cf. Issue #39944 and PR #40635)
Base._setindex(v, i::Int, args...) = ntuple(dim -> ifelse(i == dim, v, args[dim]), length(args))

# NOTE: add intersect method for ProductIterator for performance (match intersect behaviour on CartesianIndices)
Base.intersect(a::Base.Iterators.ProductIterator, b::Base.Iterators.ProductIterator) =
    Base.Iterators.ProductIterator(intersect.(a.iterators, b.iterators))

# Implement fast interval matrix multiplication
# S. M. Rump, [Verification methods: Rigorous results using floating-point arithmetic](https://doi.org/10.1017/S096249291000005X), *Acta Numerica*, **19** (2010), 287-449.
@inline __mul!(C, A, B, α, β) = mul!(C, A, B, α, β)
for (T, S) ∈ ((:Interval, :Interval), (:Interval, :Any), (:Any, :Interval))
    @eval @inline function __mul!(C, A::AbstractMatrix{T}, B::AbstractVecOrMat{S}, α, β) where {T<:$T,S<:$S}
        if iszero(α)
            if iszero(β)
                C .= zero(eltype(C))
            elseif !isone(β)
                C .*= β
            end
        else
            ABinf, ABsup = __mul(A, B)
            if isone(α)
                if iszero(β)
                    C .= Interval.(ABinf, ABsup)
                elseif isone(β)
                    C .+= Interval.(ABinf, ABsup)
                else
                    C .= Interval.(ABinf, ABsup) .+ C .* β
                end
            else
                if iszero(β)
                    C .= Interval.(ABinf, ABsup) .* α
                elseif isone(β)
                    C .+= Interval.(ABinf, ABsup) .* α
                else
                    C .= Interval.(ABinf, ABsup) .* α .+ C .* β
                end
            end
        end
        return C
    end
end
for (T, S) ∈ ((:(Complex{<:Interval}), :(Complex{<:Interval})),
        (:(Complex{<:Interval}), :Complex), (:Complex, :(Complex{<:Interval})))
    @eval @inline function __mul!(C, A::AbstractMatrix{T}, B::AbstractVecOrMat{S}, α, β) where {T<:$T,S<:$S}
        if iszero(α)
            if iszero(β)
                C .= zero(eltype(C))
            elseif !isone(β)
                C .*= β
            end
        else
            A_real, A_imag = reim(A)
            B_real, B_imag = reim(B)
            ABinf_1, ABsup_1 = __mul(A_real, B_real)
            ABinf_2, ABsup_2 = __mul(A_imag, B_imag)
            ABinf_3, ABsup_3 = __mul(A_real, B_imag)
            ABinf_4, ABsup_4 = __mul(A_imag, B_real)
            if isone(α)
                if iszero(β)
                    C .= complex.(Interval.(ABinf_1, ABsup_1) .- Interval.(ABinf_2, ABsup_2),
                        Interval.(ABinf_3, ABsup_3) .+ Interval.(ABinf_4, ABsup_4))
                elseif isone(β)
                    C .+= complex.(Interval.(ABinf_1, ABsup_1) .- Interval.(ABinf_2, ABsup_2),
                        Interval.(ABinf_3, ABsup_3) .+ Interval.(ABinf_4, ABsup_4))
                else
                    C .= complex.(Interval.(ABinf_1, ABsup_1) .- Interval.(ABinf_2, ABsup_2),
                        Interval.(ABinf_3, ABsup_3) .+ Interval.(ABinf_4, ABsup_4)) .+ C .* β
                end
            else
                if iszero(β)
                    C .= complex.(Interval.(ABinf_1, ABsup_1) .- Interval.(ABinf_2, ABsup_2),
                        Interval.(ABinf_3, ABsup_3) .+ Interval.(ABinf_4, ABsup_4)) .* α
                elseif isone(β)
                    C .+= complex.(Interval.(ABinf_1, ABsup_1) .- Interval.(ABinf_2, ABsup_2),
                        Interval.(ABinf_3, ABsup_3) .+ Interval.(ABinf_4, ABsup_4)) .* α
                else
                    C .= complex.(Interval.(ABinf_1, ABsup_1) .- Interval.(ABinf_2, ABsup_2),
                        Interval.(ABinf_3, ABsup_3) .+ Interval.(ABinf_4, ABsup_4)) .* α .+ C .* β
                end
            end
        end
        return C
    end
end
for (T, S) ∈ ((:(Complex{<:Interval}), :Interval), (:(Complex{<:Interval}), :Any), (:Complex, :Interval))
    @eval begin
        @inline function __mul!(C, A::AbstractMatrix{T}, B::AbstractVecOrMat{S}, α, β) where {T<:$T,S<:$S}
            if iszero(α)
                if iszero(β)
                    C .= zero(eltype(C))
                elseif !isone(β)
                    C .*= β
                end
            else
                A_real, A_imag = reim(A)
                ABinf_real, ABsup_real = __mul(A_real, B)
                ABinf_imag, ABsup_imag = __mul(A_imag, B)
                if isone(α)
                    if iszero(β)
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag))
                    elseif isone(β)
                        C .+= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag))
                    else
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .+ C .* β
                    end
                else
                    if iszero(β)
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .* α
                    elseif isone(β)
                        C .+= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .* α
                    else
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .* α .+ C .* β
                    end
                end
            end
            return C
        end
        @inline function __mul!(C, A::AbstractMatrix{S}, B::AbstractVecOrMat{T}, α, β) where {S<:$S,T<:$T}
            if iszero(α)
                if iszero(β)
                    C .= zero(eltype(C))
                elseif !isone(β)
                    C .*= β
                end
            else
                B_real, B_imag = reim(B)
                ABinf_real, ABsup_real = __mul(A, B_real)
                ABinf_imag, ABsup_imag = __mul(A, B_imag)
                if isone(α)
                    if iszero(β)
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag))
                    elseif isone(β)
                        C .+= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag))
                    else
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .+ C .* β
                    end
                else
                    if iszero(β)
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .* α
                    elseif isone(β)
                        C .+= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .* α
                    else
                        C .= complex.(Interval.(ABinf_real, ABsup_real), Interval.(ABinf_imag, ABsup_imag)) .* α .+ C .* β
                    end
                end
            end
            return C
        end
    end
end
@inline function __mul(A::AbstractMatrix{T}, B::AbstractVecOrMat{S}) where {T<:Interval,S<:Interval}
    R = promote_type(T, S)
    return __mul(convert.(R, A), convert.(R, B))
end
@inline function __mul(A::AbstractMatrix{Interval{T}}, B::AbstractVecOrMat{Interval{T}}) where {T<:Real}
    Ainf = inf.(A)
    Asup = sup.(A)
    Binf = inf.(B)
    Bsup = sup.(B)
    mA, mB, R, Csup = setrounding(T, RoundUp) do
        mA = Ainf .+ (Asup .- Ainf) ./ 2
        mB = Binf .+ (Bsup .- Binf) ./ 2
        rA = mA - Ainf
        rB = mB - Binf
        R = abs.(mA) * rB .+ rA * (abs.(mB) .+ rB)
        Csup = mA * mB + R
        return mA, mB, R, Csup
    end
    Cinf = setrounding(T, RoundDown) do
        return mA * mB - R
    end
    return Cinf, Csup
end
@inline function __mul(A::AbstractMatrix{Interval{T}}, B::AbstractVecOrMat{T}) where {T<:Real}
    Ainf = inf.(A)
    Asup = sup.(A)
    mA, R, Csup = setrounding(T, RoundUp) do
        mA = Ainf .+ (Asup .- Ainf) ./ 2
        rA = mA - Ainf
        R = rA * abs.(B)
        Csup = mA * B + R
        return mA, R, Csup
    end
    Cinf = setrounding(T, RoundDown) do
        return mA * B - R
    end
    return Cinf, Csup
end
@inline function __mul(A::AbstractMatrix{T}, B::AbstractVecOrMat{Interval{T}}) where {T<:Real}
    Binf = inf.(B)
    Bsup = sup.(B)
    mB, R, Csup = setrounding(T, RoundUp) do
        mB = Binf .+ (Bsup .- Binf) ./ 2
        rB = mB - Binf
        R = abs.(A) * rB
        Csup = A * mB + R
        return mB, R, Csup
    end
    Cinf = setrounding(T, RoundDown) do
        return A * mB - R
    end
    return Cinf, Csup
end


text:
#!/usr/bin/env julia

using WCS
using Base.Test

wcs = WCSTransform(2;
                   alt     = 'B',
                   cdelt   = [-0.066667, 0.066667],
                   colnum  = 2,
                   ctype   = ["RA---AIR", "DEC--AIR"],
                   crpix   = [-234.75, 8.3393],
                   crval   = [0.0, -90.0],
                   obsgeo  = [1.0, 2.0, 3.0],
                   pc      = [1.0 0.0; 0.0 1.0],
                   pv      = [(2, 1, 45.0)],
                   velangl = 3,
                   wcsname = "WCSLIB.jl")

pixcoords = [0.0 24.0 45.0;  # x coords
             0.0 38.0 98.0]  # y coords

worldcoords = pix_to_world(wcs, pixcoords)

expected_world = [267.96547027 276.53931377 287.77080792;
                  -73.73660749 -71.97412809 -69.67813884]

@test maximum(abs(worldcoords .- expected_world)) < 5e-9
pixcoords_out = world_to_pix(wcs, worldcoords)
@test maximum(abs(pixcoords_out .- pixcoords)) < 1e-9

# Test Array{Float64, 1} methods of above
worldcoords = pix_to_world(wcs, pixcoords[:, 1])
@test maximum(abs(worldcoords .- expected_world[:, 1])) < 5e-9
pixcoords_out = world_to_pix(wcs, worldcoords)
@test maximum(abs(pixcoords_out .- pixcoords[:, 1])) < 1e-9

# Test retrieving attributes
@test wcs[:ctype] == ["RA---AIR", "DEC--AIR"]
@test wcs[:dateavg] == ""
@test wcs[:alt] == 'B'
@test wcs[:cdelt] == [-0.066667, 0.066667]
@test wcs[:cd] == [0.0 0.0; 0.0 0.0]
@test wcs[:obsgeo] == (1.0, 2.0, 3.0)

header = "SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                  -64 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                 3636 / length of data axis 1                          NAXIS2  =                 1939 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H WCSAXES =                    2 / Number of coordinate axes                      CRPIX1  =               1818.0 / Pixel coordinate of reference point            CRPIX2  =                969.5 / Pixel coordinate of reference point            CDELT1  =             -0.00825 / [deg] Coordinate increment at reference point  CDELT2  =              0.00825 / [deg] Coordinate increment at reference point  CUNIT1  = 'deg'                / Units of coordinate increment and value        CUNIT2  = 'deg'                / Units of coordinate increment and value        CTYPE1  = 'RA---CEA'           / Right ascension, cylindrical equal area projectCTYPE2  = 'DEC--CEA'           / Declination, cylindrical equal area projection CRVAL1  =            3.575E+02 / [deg] Coordinate value at reference point      CRVAL2  =            0.000E+00 / [deg] Coordinate value at reference point      PV2_1   =                  1.0 / CEA projection parameter                       LONPOLE =                  0.0 / [deg] Native longitude of celestial pole       LATPOLE =                 90.0 / [deg] Native latitude of celestial pole        RADESYS = 'ICRS'               / Equatorial coordinate system                                                                                COMMENT  WCS header keyrecords produced by WCSLIB 5.9                           "

ws = WCS.from_header(header)
@test length(ws) == 1
@test eltype(ws) === WCSTransform
w = ws[1]

@test w.naxis == 2

# Check that `to_header` succeeds and has the right number
# of records. (Checking exact equality of input and output
# strings is too demanding, as the exact formatting differs
# between minor WCSLIB versions. For example,
# `0.0E+00` vs `0.000E+00`.)
header_out = WCS.to_header(w)
@test length(header_out) == 17 * 80

# Test that wcslib_version works at all
@test WCS.wcslib_version() > v"5.0"

# Test propagating errors from wcslib.
# TODO: replace this with a public WCS routine that throws an error.
@test_throws ErrorException WCS.assert_ok(Cint(1))

ext: jl


text:
convert_to_int_vector(line) = map(x -> parse(Int64, x), split(line, ","))

function play_game(numbers, nr_turns)
    cache = Dict(number => ix for (ix, number) in enumerate(numbers[1:end-1]))
    last_spoken_number = last(numbers)
    ix = length(numbers)
    while ix < nr_turns
        if haskey(cache, last_spoken_number)
            next_number = ix - cache[last_spoken_number]
            cache[last_spoken_number] = ix
            last_spoken_number = next_number
        else
            cache[last_spoken_number] = ix
            last_spoken_number = 0
        end
        ix += 1
    end
    last_spoken_number
end

function main()
    starting_numbers = convert_to_int_vector(readline("../resources/input_15.txt"))
    nr_turns = 30000000
    result = play_game(starting_numbers, nr_turns)
    println(result)
end

main()


text:
const lscpu_NOCTUA1 = """CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0       yes    3700.0000 1000.0000
1   0    0      1    1:1:1:0       yes    3700.0000 1000.0000
2   0    0      2    2:2:2:0       yes    3700.0000 1000.0000
3   0    0      3    3:3:3:0       yes    3700.0000 1000.0000
4   0    0      4    4:4:4:0       yes    3700.0000 1000.0000
5   0    0      5    5:5:5:0       yes    3700.0000 1000.0000
6   0    0      6    6:6:6:0       yes    3700.0000 1000.0000
7   0    0      7    7:7:7:0       yes    3700.0000 1000.0000
8   0    0      8    8:8:8:0       yes    3700.0000 1000.0000
9   0    0      9    9:9:9:0       yes    3700.0000 1000.0000
10  0    0      10   10:10:10:0    yes    3700.0000 1000.0000
11  0    0      11   11:11:11:0    yes    3700.0000 1000.0000
12  0    0      12   12:12:12:0    yes    3700.0000 1000.0000
13  0    0      13   13:13:13:0    yes    3700.0000 1000.0000
14  0    0      14   14:14:14:0    yes    3700.0000 1000.0000
15  0    0      15   15:15:15:0    yes    3700.0000 1000.0000
16  0    0      16   16:16:16:0    yes    3700.0000 1000.0000
17  0    0      17   17:17:17:0    yes    3700.0000 1000.0000
18  0    0      18   18:18:18:0    yes    3700.0000 1000.0000
19  0    0      19   19:19:19:0    yes    3700.0000 1000.0000
20  1    1      20   20:20:20:1    yes    3700.0000 1000.0000
21  1    1      21   21:21:21:1    yes    3700.0000 1000.0000
22  1    1      22   22:22:22:1    yes    3700.0000 1000.0000
23  1    1      23   23:23:23:1    yes    3700.0000 1000.0000
24  1    1      24   24:24:24:1    yes    3700.0000 1000.0000
25  1    1      25   25:25:25:1    yes    3700.0000 1000.0000
26  1    1      26   26:26:26:1    yes    3700.0000 1000.0000
27  1    1      27   27:27:27:1    yes    3700.0000 1000.0000
28  1    1      28   28:28:28:1    yes    3700.0000 1000.0000
29  1    1      29   29:29:29:1    yes    3700.0000 1000.0000
30  1    1      30   30:30:30:1    yes    3700.0000 1000.0000
31  1    1      31   31:31:31:1    yes    3700.0000 1000.0000
32  1    1      32   32:32:32:1    yes    3700.0000 1000.0000
33  1    1      33   33:33:33:1    yes    3700.0000 1000.0000
34  1    1      34   34:34:34:1    yes    3700.0000 1000.0000
35  1    1      35   35:35:35:1    yes    3700.0000 1000.0000
36  1    1      36   36:36:36:1    yes    3700.0000 1000.0000
37  1    1      37   37:37:37:1    yes    3700.0000 1000.0000
38  1    1      38   38:38:38:1    yes    3700.0000 1000.0000
39  1    1      39   39:39:39:1    yes    3700.0000 1000.0000
"""

const lscpu_NOCTUA2LOGIN = """CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0       yes    3529.0520 1500.0000
1   0    0      1    1:1:1:0       yes    3529.0520 1500.0000
2   0    0      2    2:2:2:0       yes    3529.0520 1500.0000
3   0    0      3    3:3:3:0       yes    3529.0520 1500.0000
4   0    0      4    4:4:4:0       yes    3529.0520 1500.0000
5   0    0      5    5:5:5:0       yes    3529.0520 1500.0000
6   0    0      6    6:6:6:0       yes    3529.0520 1500.0000
7   0    0      7    7:7:7:0       yes    3529.0520 1500.0000
8   0    0      8    8:8:8:1       yes    3529.0520 1500.0000
9   0    0      9    9:9:9:1       yes    3529.0520 1500.0000
10  0    0      10   10:10:10:1    yes    3529.0520 1500.0000
11  0    0      11   11:11:11:1    yes    3529.0520 1500.0000
12  0    0      12   12:12:12:1    yes    3529.0520 1500.0000
13  0    0      13   13:13:13:1    yes    3529.0520 1500.0000
14  0    0      14   14:14:14:1    yes    3529.0520 1500.0000
15  0    0      15   15:15:15:1    yes    3529.0520 1500.0000
16  1    0      16   16:16:16:2    yes    3529.0520 1500.0000
17  1    0      17   17:17:17:2    yes    3529.0520 1500.0000
18  1    0      18   18:18:18:2    yes    3529.0520 1500.0000
19  1    0      19   19:19:19:2    yes    3529.0520 1500.0000
20  1    0      20   20:20:20:2    yes    3529.0520 1500.0000
21  1    0      21   21:21:21:2    yes    3529.0520 1500.0000
22  1    0      22   22:22:22:2    yes    3529.0520 1500.0000
23  1    0      23   23:23:23:2    yes    3529.0520 1500.0000
24  1    0      24   24:24:24:3    yes    3529.0520 1500.0000
25  1    0      25   25:25:25:3    yes    3529.0520 1500.0000
26  1    0      26   26:26:26:3    yes    3529.0520 1500.0000
27  1    0      27   27:27:27:3    yes    3529.0520 1500.0000
28  1    0      28   28:28:28:3    yes    3529.0520 1500.0000
29  1    0      29   29:29:29:3    yes    3529.0520 1500.0000
30  1    0      30   30:30:30:3    yes    3529.0520 1500.0000
31  1    0      31   31:31:31:3    yes    3529.0520 1500.0000
32  2    0      32   32:32:32:4    yes    3529.0520 1500.0000
33  2    0      33   33:33:33:4    yes    3529.0520 1500.0000
34  2    0      34   34:34:34:4    yes    3529.0520 1500.0000
35  2    0      35   35:35:35:4    yes    3529.0520 1500.0000
36  2    0      36   36:36:36:4    yes    3529.0520 1500.0000
37  2    0      37   37:37:37:4    yes    3529.0520 1500.0000
38  2    0      38   38:38:38:4    yes    3529.0520 1500.0000
39  2    0      39   39:39:39:4    yes    3529.0520 1500.0000
40  2    0      40   40:40:40:5    yes    3529.0520 1500.0000
41  2    0      41   41:41:41:5    yes    3529.0520 1500.0000
42  2    0      42   42:42:42:5    yes    3529.0520 1500.0000
43  2    0      43   43:43:43:5    yes    3529.0520 1500.0000
44  2    0      44   44:44:44:5    yes    3529.0520 1500.0000
45  2    0      45   45:45:45:5    yes    3529.0520 1500.0000
46  2    0      46   46:46:46:5    yes    3529.0520 1500.0000
47  2    0      47   47:47:47:5    yes    3529.0520 1500.0000
48  3    0      48   48:48:48:6    yes    3529.0520 1500.0000
49  3    0      49   49:49:49:6    yes    3529.0520 1500.0000
50  3    0      50   50:50:50:6    yes    3529.0520 1500.0000
51  3    0      51   51:51:51:6    yes    3529.0520 1500.0000
52  3    0      52   52:52:52:6    yes    3529.0520 1500.0000
53  3    0      53   53:53:53:6    yes    3529.0520 1500.0000
54  3    0      54   54:54:54:6    yes    3529.0520 1500.0000
55  3    0      55   55:55:55:6    yes    3529.0520 1500.0000
56  3    0      56   56:56:56:7    yes    3529.0520 1500.0000
57  3    0      57   57:57:57:7    yes    3529.0520 1500.0000
58  3    0      58   58:58:58:7    yes    3529.0520 1500.0000
59  3    0      59   59:59:59:7    yes    3529.0520 1500.0000
60  3    0      60   60:60:60:7    yes    3529.0520 1500.0000
61  3    0      61   61:61:61:7    yes    3529.0520 1500.0000
62  3    0      62   62:62:62:7    yes    3529.0520 1500.0000
63  3    0      63   63:63:63:7    yes    3529.0520 1500.0000
64  0    0      0    0:0:0:0       yes    3529.0520 1500.0000
65  0    0      1    1:1:1:0       yes    3529.0520 1500.0000
66  0    0      2    2:2:2:0       yes    3529.0520 1500.0000
67  0    0      3    3:3:3:0       yes    3529.0520 1500.0000
68  0    0      4    4:4:4:0       yes    3529.0520 1500.0000
69  0    0      5    5:5:5:0       yes    3529.0520 1500.0000
70  0    0      6    6:6:6:0       yes    3529.0520 1500.0000
71  0    0      7    7:7:7:0       yes    3529.0520 1500.0000
72  0    0      8    8:8:8:1       yes    3529.0520 1500.0000
73  0    0      9    9:9:9:1       yes    3529.0520 1500.0000
74  0    0      10   10:10:10:1    yes    3529.0520 1500.0000
75  0    0      11   11:11:11:1    yes    3529.0520 1500.0000
76  0    0      12   12:12:12:1    yes    3529.0520 1500.0000
77  0    0      13   13:13:13:1    yes    3529.0520 1500.0000
78  0    0      14   14:14:14:1    yes    3529.0520 1500.0000
79  0    0      15   15:15:15:1    yes    3529.0520 1500.0000
80  1    0      16   16:16:16:2    yes    3529.0520 1500.0000
81  1    0      17   17:17:17:2    yes    3529.0520 1500.0000
82  1    0      18   18:18:18:2    yes    3529.0520 1500.0000
83  1    0      19   19:19:19:2    yes    3529.0520 1500.0000
84  1    0      20   20:20:20:2    yes    3529.0520 1500.0000
85  1    0      21   21:21:21:2    yes    3529.0520 1500.0000
86  1    0      22   22:22:22:2    yes    3529.0520 1500.0000
87  1    0      23   23:23:23:2    yes    3529.0520 1500.0000
88  1    0      24   24:24:24:3    yes    3529.0520 1500.0000
89  1    0      25   25:25:25:3    yes    3529.0520 1500.0000
90  1    0      26   26:26:26:3    yes    3529.0520 1500.0000
91  1    0      27   27:27:27:3    yes    3529.0520 1500.0000
92  1    0      28   28:28:28:3    yes    3529.0520 1500.0000
93  1    0      29   29:29:29:3    yes    3529.0520 1500.0000
94  1    0      30   30:30:30:3    yes    3529.0520 1500.0000
95  1    0      31   31:31:31:3    yes    3529.0520 1500.0000
96  2    0      32   32:32:32:4    yes    3529.0520 1500.0000
97  2    0      33   33:33:33:4    yes    3529.0520 1500.0000
98  2    0      34   34:34:34:4    yes    3529.0520 1500.0000
99  2    0      35   35:35:35:4    yes    3529.0520 1500.0000
100 2    0      36   36:36:36:4    yes    3529.0520 1500.0000
101 2    0      37   37:37:37:4    yes    3529.0520 1500.0000
102 2    0      38   38:38:38:4    yes    3529.0520 1500.0000
103 2    0      39   39:39:39:4    yes    3529.0520 1500.0000
104 2    0      40   40:40:40:5    yes    3529.0520 1500.0000
105 2    0      41   41:41:41:5    yes    3529.0520 1500.0000
106 2    0      42   42:42:42:5    yes    3529.0520 1500.0000
107 2    0      43   43:43:43:5    yes    3529.0520 1500.0000
108 2    0      44   44:44:44:5    yes    3529.0520 1500.0000
109 2    0      45   45:45:45:5    yes    3529.0520 1500.0000
110 2    0      46   46:46:46:5    yes    3529.0520 1500.0000
111 2    0      47   47:47:47:5    yes    3529.0520 1500.0000
112 3    0      48   48:48:48:6    yes    3529.0520 1500.0000
113 3    0      49   49:49:49:6    yes    3529.0520 1500.0000
114 3    0      50   50:50:50:6    yes    3529.0520 1500.0000
115 3    0      51   51:51:51:6    yes    3529.0520 1500.0000
116 3    0      52   52:52:52:6    yes    3529.0520 1500.0000
117 3    0      53   53:53:53:6    yes    3529.0520 1500.0000
118 3    0      54   54:54:54:6    yes    3529.0520 1500.0000
119 3    0      55   55:55:55:6    yes    3529.0520 1500.0000
120 3    0      56   56:56:56:7    yes    3529.0520 1500.0000
121 3    0      57   57:57:57:7    yes    3529.0520 1500.0000
122 3    0      58   58:58:58:7    yes    3529.0520 1500.0000
123 3    0      59   59:59:59:7    yes    3529.0520 1500.0000
124 3    0      60   60:60:60:7    yes    3529.0520 1500.0000
125 3    0      61   61:61:61:7    yes    3529.0520 1500.0000
126 3    0      62   62:62:62:7    yes    3529.0520 1500.0000
127 3    0      63   63:63:63:7    yes    3529.0520 1500.0000"""

const lscpu_NOCTUA2 = """CPU NODE SOCKET CORE L1d:L1i:L2:L3  ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0        yes    3529.0520 1500.0000
1   0    0      1    1:1:1:0        yes    3529.0520 1500.0000
2   0    0      2    2:2:2:0        yes    3529.0520 1500.0000
3   0    0      3    3:3:3:0        yes    3529.0520 1500.0000
4   0    0      4    4:4:4:0        yes    3529.0520 1500.0000
5   0    0      5    5:5:5:0        yes    3529.0520 1500.0000
6   0    0      6    6:6:6:0        yes    3529.0520 1500.0000
7   0    0      7    7:7:7:0        yes    3529.0520 1500.0000
8   0    0      8    8:8:8:1        yes    3529.0520 1500.0000
9   0    0      9    9:9:9:1        yes    3529.0520 1500.0000
10  0    0      10   10:10:10:1     yes    3529.0520 1500.0000
11  0    0      11   11:11:11:1     yes    3529.0520 1500.0000
12  0    0      12   12:12:12:1     yes    3529.0520 1500.0000
13  0    0      13   13:13:13:1     yes    3529.0520 1500.0000
14  0    0      14   14:14:14:1     yes    3529.0520 1500.0000
15  0    0      15   15:15:15:1     yes    3529.0520 1500.0000
16  1    0      16   16:16:16:2     yes    3529.0520 1500.0000
17  1    0      17   17:17:17:2     yes    3529.0520 1500.0000
18  1    0      18   18:18:18:2     yes    3529.0520 1500.0000
19  1    0      19   19:19:19:2     yes    3529.0520 1500.0000
20  1    0      20   20:20:20:2     yes    3529.0520 1500.0000
21  1    0      21   21:21:21:2     yes    3529.0520 1500.0000
22  1    0      22   22:22:22:2     yes    3529.0520 1500.0000
23  1    0      23   23:23:23:2     yes    3529.0520 1500.0000
24  1    0      24   24:24:24:3     yes    3529.0520 1500.0000
25  1    0      25   25:25:25:3     yes    3529.0520 1500.0000
26  1    0      26   26:26:26:3     yes    3529.0520 1500.0000
27  1    0      27   27:27:27:3     yes    3529.0520 1500.0000
28  1    0      28   28:28:28:3     yes    3529.0520 1500.0000
29  1    0      29   29:29:29:3     yes    3529.0520 1500.0000
30  1    0      30   30:30:30:3     yes    3529.0520 1500.0000
31  1    0      31   31:31:31:3     yes    3529.0520 1500.0000
32  2    0      32   32:32:32:4     yes    3529.0520 1500.0000
33  2    0      33   33:33:33:4     yes    3529.0520 1500.0000
34  2    0      34   34:34:34:4     yes    3529.0520 1500.0000
35  2    0      35   35:35:35:4     yes    3529.0520 1500.0000
36  2    0      36   36:36:36:4     yes    3529.0520 1500.0000
37  2    0      37   37:37:37:4     yes    3529.0520 1500.0000
38  2    0      38   38:38:38:4     yes    3529.0520 1500.0000
39  2    0      39   39:39:39:4     yes    3529.0520 1500.0000
40  2    0      40   40:40:40:5     yes    3529.0520 1500.0000
41  2    0      41   41:41:41:5     yes    3529.0520 1500.0000
42  2    0      42   42:42:42:5     yes    3529.0520 1500.0000
43  2    0      43   43:43:43:5     yes    3529.0520 1500.0000
44  2    0      44   44:44:44:5     yes    3529.0520 1500.0000
45  2    0      45   45:45:45:5     yes    3529.0520 1500.0000
46  2    0      46   46:46:46:5     yes    3529.0520 1500.0000
47  2    0      47   47:47:47:5     yes    3529.0520 1500.0000
48  3    0      48   48:48:48:6     yes    3529.0520 1500.0000
49  3    0      49   49:49:49:6     yes    3529.0520 1500.0000
50  3    0      50   50:50:50:6     yes    3529.0520 1500.0000
51  3    0      51   51:51:51:6     yes    3529.0520 1500.0000
52  3    0      52   52:52:52:6     yes    3529.0520 1500.0000
53  3    0      53   53:53:53:6     yes    3529.0520 1500.0000
54  3    0      54   54:54:54:6     yes    3529.0520 1500.0000
55  3    0      55   55:55:55:6     yes    3529.0520 1500.0000
56  3    0      56   56:56:56:7     yes    3529.0520 1500.0000
57  3    0      57   57:57:57:7     yes    3529.0520 1500.0000
58  3    0      58   58:58:58:7     yes    3529.0520 1500.0000
59  3    0      59   59:59:59:7     yes    3529.0520 1500.0000
60  3    0      60   60:60:60:7     yes    3529.0520 1500.0000
61  3    0      61   61:61:61:7     yes    3529.0520 1500.0000
62  3    0      62   62:62:62:7     yes    3529.0520 1500.0000
63  3    0      63   63:63:63:7     yes    3529.0520 1500.0000
64  4    1      64   64:64:64:8     yes    3529.0520 1500.0000
65  4    1      65   65:65:65:8     yes    3529.0520 1500.0000
66  4    1      66   66:66:66:8     yes    3529.0520 1500.0000
67  4    1      67   67:67:67:8     yes    3529.0520 1500.0000
68  4    1      68   68:68:68:8     yes    3529.0520 1500.0000
69  4    1      69   69:69:69:8     yes    3529.0520 1500.0000
70  4    1      70   70:70:70:8     yes    3529.0520 1500.0000
71  4    1      71   71:71:71:8     yes    3529.0520 1500.0000
72  4    1      72   72:72:72:9     yes    3529.0520 1500.0000
73  4    1      73   73:73:73:9     yes    3529.0520 1500.0000
74  4    1      74   74:74:74:9     yes    3529.0520 1500.0000
75  4    1      75   75:75:75:9     yes    3529.0520 1500.0000
76  4    1      76   76:76:76:9     yes    3529.0520 1500.0000
77  4    1      77   77:77:77:9     yes    3529.0520 1500.0000
78  4    1      78   78:78:78:9     yes    3529.0520 1500.0000
79  4    1      79   79:79:79:9     yes    3529.0520 1500.0000
80  5    1      80   80:80:80:10    yes    3529.0520 1500.0000
81  5    1      81   81:81:81:10    yes    3529.0520 1500.0000
82  5    1      82   82:82:82:10    yes    3529.0520 1500.0000
83  5    1      83   83:83:83:10    yes    3529.0520 1500.0000
84  5    1      84   84:84:84:10    yes    3529.0520 1500.0000
85  5    1      85   85:85:85:10    yes    3529.0520 1500.0000
86  5    1      86   86:86:86:10    yes    3529.0520 1500.0000
87  5    1      87   87:87:87:10    yes    3529.0520 1500.0000
88  5    1      88   88:88:88:11    yes    3529.0520 1500.0000
89  5    1      89   89:89:89:11    yes    3529.0520 1500.0000
90  5    1      90   90:90:90:11    yes    3529.0520 1500.0000
91  5    1      91   91:91:91:11    yes    3529.0520 1500.0000
92  5    1      92   92:92:92:11    yes    3529.0520 1500.0000
93  5    1      93   93:93:93:11    yes    3529.0520 1500.0000
94  5    1      94   94:94:94:11    yes    3529.0520 1500.0000
95  5    1      95   95:95:95:11    yes    3529.0520 1500.0000
96  6    1      96   96:96:96:12    yes    3529.0520 1500.0000
97  6    1      97   97:97:97:12    yes    3529.0520 1500.0000
98  6    1      98   98:98:98:12    yes    3529.0520 1500.0000
99  6    1      99   99:99:99:12    yes    3529.0520 1500.0000
100 6    1      100  100:100:100:12 yes    3529.0520 1500.0000
101 6    1      101  101:101:101:12 yes    3529.0520 1500.0000
102 6    1      102  102:102:102:12 yes    3529.0520 1500.0000
103 6    1      103  103:103:103:12 yes    3529.0520 1500.0000
104 6    1      104  104:104:104:13 yes    3529.0520 1500.0000
105 6    1      105  105:105:105:13 yes    3529.0520 1500.0000
106 6    1      106  106:106:106:13 yes    3529.0520 1500.0000
107 6    1      107  107:107:107:13 yes    3529.0520 1500.0000
108 6    1      108  108:108:108:13 yes    3529.0520 1500.0000
109 6    1      109  109:109:109:13 yes    3529.0520 1500.0000
110 6    1      110  110:110:110:13 yes    3529.0520 1500.0000
111 6    1      111  111:111:111:13 yes    3529.0520 1500.0000
112 7    1      112  112:112:112:14 yes    3529.0520 1500.0000
113 7    1      113  113:113:113:14 yes    3529.0520 1500.0000
114 7    1      114  114:114:114:14 yes    3529.0520 1500.0000
115 7    1      115  115:115:115:14 yes    3529.0520 1500.0000
116 7    1      116  116:116:116:14 yes    3529.0520 1500.0000
117 7    1      117  117:117:117:14 yes    3529.0520 1500.0000
118 7    1      118  118:118:118:14 yes    3529.0520 1500.0000
119 7    1      119  119:119:119:14 yes    3529.0520 1500.0000
120 7    1      120  120:120:120:15 yes    3529.0520 1500.0000
121 7    1      121  121:121:121:15 yes    3529.0520 1500.0000
122 7    1      122  122:122:122:15 yes    3529.0520 1500.0000
123 7    1      123  123:123:123:15 yes    3529.0520 1500.0000
124 7    1      124  124:124:124:15 yes    3529.0520 1500.0000
125 7    1      125  125:125:125:15 yes    3529.0520 1500.0000
126 7    1      126  126:126:126:15 yes    3529.0520 1500.0000
127 7    1      127  127:127:127:15 yes    3529.0520 1500.0000
"""

const lscpu_FUGAKU = """CPU NODE CLUSTER CORE ONLINE MAXMHZ    MINMHZ
0   0    0       0    yes    2200.0000 1600.0000
1   1    1       1    yes    2200.0000 1600.0000
2   -    -       -    no     -         -
3   -    -       -    no     -         -
4   -    -       -    no     -         -
5   -    -       -    no     -         -
6   -    -       -    no     -         -
7   -    -       -    no     -         -
8   -    -       -    no     -         -
9   -    -       -    no     -         -
10  -    -       -    no     -         -
11  -    -       -    no     -         -
12  4    2       2    yes    2200.0000 1600.0000
13  4    2       3    yes    2200.0000 1600.0000
14  4    2       4    yes    2200.0000 1600.0000
15  4    2       5    yes    2200.0000 1600.0000
16  4    2       6    yes    2200.0000 1600.0000
17  4    2       7    yes    2200.0000 1600.0000
18  4    2       8    yes    2200.0000 1600.0000
19  4    2       9    yes    2200.0000 1600.0000
20  4    2       10   yes    2200.0000 1600.0000
21  4    2       11   yes    2200.0000 1600.0000
22  4    2       12   yes    2200.0000 1600.0000
23  4    2       13   yes    2200.0000 1600.0000
24  5    3       14   yes    2200.0000 1600.0000
25  5    3       15   yes    2200.0000 1600.0000
26  5    3       16   yes    2200.0000 1600.0000
27  5    3       17   yes    2200.0000 1600.0000
28  5    3       18   yes    2200.0000 1600.0000
29  5    3       19   yes    2200.0000 1600.0000
30  5    3       20   yes    2200.0000 1600.0000
31  5    3       21   yes    2200.0000 1600.0000
32  5    3       22   yes    2200.0000 1600.0000
33  5    3       23   yes    2200.0000 1600.0000
34  5    3       24   yes    2200.0000 1600.0000
35  5    3       25   yes    2200.0000 1600.0000
36  6    4       26   yes    2200.0000 1600.0000
37  6    4       27   yes    2200.0000 1600.0000
38  6    4       28   yes    2200.0000 1600.0000
39  6    4       29   yes    2200.0000 1600.0000
40  6    4       30   yes    2200.0000 1600.0000
41  6    4       31   yes    2200.0000 1600.0000
42  6    4       32   yes    2200.0000 1600.0000
43  6    4       33   yes    2200.0000 1600.0000
44  6    4       34   yes    2200.0000 1600.0000
45  6    4       35   yes    2200.0000 1600.0000
46  6    4       36   yes    2200.0000 1600.0000
47  6    4       37   yes    2200.0000 1600.0000
48  7    5       38   yes    2200.0000 1600.0000
49  7    5       39   yes    2200.0000 1600.0000
50  7    5       40   yes    2200.0000 1600.0000
51  7    5       41   yes    2200.0000 1600.0000
52  7    5       42   yes    2200.0000 1600.0000
53  7    5       43   yes    2200.0000 1600.0000
54  7    5       44   yes    2200.0000 1600.0000
55  7    5       45   yes    2200.0000 1600.0000
56  7    5       46   yes    2200.0000 1600.0000
57  7    5       47   yes    2200.0000 1600.0000
58  7    5       48   yes    2200.0000 1600.0000
59  7    5       49   yes    2200.0000 1600.0000"""


text:
using CUDA.CUSPARSE
using SparseArrays
using CUDA.CUSPARSE: CuSparseDeviceVector, CuSparseDeviceMatrixCSC, CuSparseDeviceMatrixCSR,
                     CuSparseDeviceMatrixBSR, CuSparseDeviceMatrixCOO

@testset "cudaconvert" begin
    @test isbitstype(CuSparseDeviceVector{Float32, Cint, CUDA.AS.Global})
    @test isbitstype(CuSparseDeviceMatrixCSC{Float32, Cint, CUDA.AS.Global})
    @test isbitstype(CuSparseDeviceMatrixCSR{Float32, Cint, CUDA.AS.Global})
    @test isbitstype(CuSparseDeviceMatrixBSR{Float32, Cint, CUDA.AS.Global})
    @test isbitstype(CuSparseDeviceMatrixCOO{Float32, Cint, CUDA.AS.Global})

    V = sprand(10, 0.5)
    cuV = CuSparseVector(V)
    @test cudaconvert(cuV) isa CuSparseDeviceVector{Float64, Cint, 1}

    A = sprand(10, 10, 0.5)
    cuA = CuSparseMatrixCSC(A)
    @test cudaconvert(cuA) isa CuSparseDeviceMatrixCSC{Float64, Cint, 1}

    cuA = CuSparseMatrixCSR(A)
    @test cudaconvert(cuA) isa CuSparseDeviceMatrixCSR{Float64, Cint, 1}

    cuA = CuSparseMatrixCOO(A)
    @test cudaconvert(cuA) isa CuSparseDeviceMatrixCOO{Float64, Cint, 1}

    cuA = CuSparseMatrixBSR(A, 2)
    @test cudaconvert(cuA) isa CuSparseDeviceMatrixBSR
end


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule duf_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("duf")
JLLWrappers.@generate_main_file("duf", UUID("77fda4b3-100c-5a35-9709-1e47c79e10df"))
end  # module duf_jll


text:
module AOC

include("1/fuel_counter.jl")

end # module


text:
using Test
using ConvDiffMIPDECO
using jInv.Mesh

domain = [0. 1. 0 1 0 1]
n      = [6 4 8]
M2D    = getRegularMesh(domain[1:4],n[1:2])

gx     = X -> X[:,1]
gy     = X -> ones(size(X,1))

xa,ya = getCellCenteredAxes(M2D)
gdir,gneu = getBoundaryFuncVal(gx, gy, M2D,(:dir,:dir,:dir,:dir))
@test isempty(gneu)
@test length(gdir) == sum(n[1:2])*2
@test all(gdir[1:n[2]].==0.0)
@test all(gdir[n[2].+(1:n[1])] .== xa)
@test all(gdir[sum(n[1:2]).+(1:n[2])].==1.0)
@test all(gdir[n[1].+2*n[2].+(1:n[1])] .== xa)

gdir,gneu = getBoundaryFuncVal(gx, gy, M2D,(:neu,:neu,:neu,:neu))
@test isempty(gdir)
@test length(gneu) == sum(n[1:2])*2
@test all(gneu[1:n[2]].== -M2D.h[1])
@test all(gneu[n[2].+(1:n[1])] .== -M2D.h[2])
@test all(gneu[sum(n[1:2]).+(1:n[2])].==M2D.h[1])
@test all(gneu[n[1].+2*n[2].+(1:n[1])] .== M2D.h[2])

M3D = getRegularMesh(domain,n)
xa,ya,za = getCellCenteredAxes(M3D)
gdir,gneu = getBoundaryFuncVal(gx, gy, M3D,(:dir,:dir,:dir,:dir,:dir,:dir))
@test isempty(gneu)
@test all(gdir[1:prod(n[2:3])].==0.0)
@test length(gdir) == 2*prod(n[2:3]) + 2*prod(n[[1,3]]) + 2*prod(n[1:2])

max_stars_repo_name: JuliaInv/ConvDiffMIPDECO

max_issues_repo_name: JuliaInv/ConvDiffMIPDECO

max_forks_repo_name: JuliaInv/ConvDiffMIPDECO


text:
# == Context ==================================================================

type SymEntry
    value
    kind::Symbol
    wrapped

    SymEntry(value, kind::Symbol) = new(value, kind, nothing)
end

type Context
    symbols::Dict{Symbol,SymEntry}  # current symbol bindings
    emit_function::Function              # sink for emitted instructions

    function Context(symbols::Dict{Symbol,SymEntry}, emit)
        new(symbols, emit, Symbol[], Symbol[])
    end

    inputs::Vector{Symbol}
    outputs::Vector{Symbol}
end

emit(c::Context, ex) = c.emit_function(ex)

function create_argument(kind::Symbol, context::Context, name::Symbol)
    if has(context.symbols, name)
        error("$name already exists in symbol table")
    end
    context.symbols[name] = SymEntry(name, kind)

    if     kind == :input;   append!(context.inputs,  [name])
    elseif kind == :output;  append!(context.outputs, [name])
    else;                    error("unknown argument kind: :$kind");
    end

    return name
end

# == Flatten ==================================================================

function expect_expr(ex, head::Symbol)
    if !isa(ex, Expr) || (ex.head != head)
        error("expected expr(:$head,...), found $ex")
    end
end

# -- expect_argument(kind, ...) -----------------------------------------------
# Try to extract and return an input/output (depending on kind) from name.
# If it's unbound, create one and return.
# If it exists and is of the wrong kind, throw an error.

function expect_argument(kind::Symbol, context::Context, name::Symbol)
    if has(context.symbols, name)
        entry = context.symbols[name]
        if entry.kind != kind
            error("expected $kind, found $entry")
        end
        return entry.value
    else
        return create_argument(kind, context, name)
    end
end

# -- flatten ------------------------------------------------------------------
# Flatten a scalar-valued rhs expr
# Returns the expr's value as a scalar var symbol

flatten(c::Context, exprs::Vector) = { flatten(c, ex) | ex in exprs }

function wrap_input(context::Context, name)
    entry = context.symbols[name]
    if entry.wrapped == nothing
        entry.wrapped = expr(:ref, name, expr(:(...), :indvars))
    end
    return entry.wrapped
end

flatten(::Context, ex::Any) = ex   # literal
function flatten(context::Context, name::Symbol)
    if has(context.symbols, name)
        entry = context.symbols[name]
        if entry.kind == :local
            return entry.value
        elseif entry.kind == :input
            return wrap_input(context, entry.value)
        else
            error("expected local/input, got $entry")
        end
    else
        # new input
        return wrap_input(context, create_argument(:input, context, name))
    end
end
function flatten(context::Context, ex::Expr)
    if ex.head == :line # ignore line numbers
        return nothing # CONSIDER: could this shadow the last actual value?
    elseif ex.head == :block    # exprs...
        value = nothing
        for subex in ex.args
            value = flatten(context, subex)
        end
        return value
    elseif ex.head == :(=)  # assignment: lvalue = expr
        lhs = flatten_lhs(context, ex.args[1])
        rhs = flatten(context, ex.args[2])
        return execute_assignment(context, lhs, rhs)
    elseif (ex.head == :call) || (ex.head == :ref) # :call(op, exprs...)
                                                   # :ref(input, exprs...)
        node = flatten_callref(context, ex)
        target = gensym()
        emit(context, expr(:(=), target, node))
        return target
    end
    error("unexpected scalar rhs: ex = $ex")
end

# -- flatten_callref ----------------------------------------------------------
# Flatten a scalar rhs :call / :ref expr
# Returns primivite expr with symbol-only arguments

function flatten_callref(context::Context, ex::Expr)
    if ex.head == :call
        op = ex.args[1]
        args = flatten(context, ex.args[2:end])
        return expr(ex.head, op, args...)
    elseif ex.head == :ref
        input = expect_argument(:input, context, ex.args[1])
        inds = flatten(context, ex.args[2:end])
        return expr(ex.head, input, inds...)
    end
end

# -- flatten_lhs --------------------------------------------------------------
# Flatten a scalar-valued lhs expr
# Returns the lhs as a symbol / :ref expr

flatten_lhs(context::Context, name::Symbol) = name # scalar var
function flatten_lhs(context::Context, ex::Expr)
    # assign[]
    expect_expr(ex, :ref)
    output = expect_argument(:output, context, ex.args[1])
    inds = flatten(context, ex.args[2:end])
    return expr(:ref, output, inds...)
end

# -- execute_assignment(context::Context, lhs, rhs) ---------------------------
# Process assignment lhs = rhs.
# Returns value = rhs

function execute_assignment(context::Context, lhs::Symbol, rhs::Symbol)
    # straight assignment: just store in symbol table
    context.symbols[lhs] = SymEntry(rhs, :local)
    rhs
end
function execute_assignment(context::Context, lhs::Expr, rhs::Symbol)
    # indexed assignment to output
    if length(lhs.args) == 1
        lhs = expr(:ref, lhs.args[1], expr(:(...), :indvars))
    end
    emit(context, expr(:(=), lhs, rhs))
    rhs
end

# == Some printing ============================================================

function print_code(flat_code::Vector)
    println("code:")
    for ex in flat_code; println("\t", ex); end
end
function print_context(context::Context)
    println("inputs  = $(context.inputs)")
    println("outputs = $(context.outputs)")

    println("symbols at end:")
    for (k, v) in context.symbols; println("\t$k = $v"); end
end

max_stars_repo_name: toivoh/julia-kernels

max_issues_repo_name: toivoh/julia-kernels

max_forks_repo_name: toivoh/julia-kernels


text:
function test_argmax_layer(backend::Backend, n_input, tensor_dim, T, eps)
  println("-- Testing ArgmaxLayer on $(typeof(backend)){$T}...")

  println("    > $tensor_dim-dimensional tensor")

  dims = [rand(1:6, tensor_dim) for i = 1:n_input]
  op_dim = max(abs(rand(Int)) % tensor_dim, 1)
  inputs = [rand(T, dims[i]...) for i = 1:n_input]
  input_blob = Blob[make_blob(backend, x) for x in inputs]
  diff_blob = Blob[NullBlob() for i = 1:n_input]

  println("    > Setup")
  layer = ArgmaxLayer(bottoms=Array{Symbol}(n_input),tops=Array{Symbol}(n_input),dim=op_dim)
  state = setup(backend, layer, input_blob, diff_blob)

  println("    > Forward")
  forward(backend, state, input_blob)
  for i = 1:n_input
    outdim = [size(inputs[i])...]
    outdim[op_dim] = 1
    got_output = zeros(T, outdim...)
    expected_output = zeros(T, outdim...)

    pre_dim, mid_dim, post_dim = split_dims(inputs[i], op_dim)
    input = reshape(inputs[i], pre_dim, mid_dim, post_dim)
    output = reshape(expected_output, pre_dim, 1, post_dim)
    for x = 1:pre_dim
      for z = 1:post_dim
        output[x,1,z] = indmax(input[x,:,z])-1
      end
    end

    copy!(got_output, state.blobs[i])
    @test all(abs.(got_output - expected_output) .< eps)
  end

  shutdown(backend, state)
end
function test_argmax_layer(backend::Backend, n_input, T, eps)
  for i in [2,4,5]
    test_argmax_layer(backend, n_input, i, T, eps)
  end
end
function test_argmax_layer(backend::Backend)
  test_argmax_layer(backend, 3, Float64, 1e-10)
  test_argmax_layer(backend, 3, Float32, 1e-10)
end

if test_cpu
  test_argmax_layer(backend_cpu)
end
if test_gpu
  test_argmax_layer(backend_gpu)
end


text:
cell_to_vtkcell(::Type{Line}) = VTKCellTypes.VTK_LINE
cell_to_vtkcell(::Type{Line2D}) = VTKCellTypes.VTK_LINE
cell_to_vtkcell(::Type{Line3D}) = VTKCellTypes.VTK_LINE
cell_to_vtkcell(::Type{QuadraticLine}) = VTKCellTypes.VTK_QUADRATIC_EDGE

cell_to_vtkcell(::Type{Quadrilateral}) = VTKCellTypes.VTK_QUAD
cell_to_vtkcell(::Type{Quadrilateral3D}) = VTKCellTypes.VTK_QUAD
cell_to_vtkcell(::Type{QuadraticQuadrilateral}) = VTKCellTypes.VTK_BIQUADRATIC_QUAD
cell_to_vtkcell(::Type{Triangle}) = VTKCellTypes.VTK_TRIANGLE
cell_to_vtkcell(::Type{QuadraticTriangle}) = VTKCellTypes.VTK_QUADRATIC_TRIANGLE
cell_to_vtkcell(::Type{Cell{2,8,4}}) = VTKCellTypes.VTK_QUADRATIC_QUAD

cell_to_vtkcell(::Type{Hexahedron}) = VTKCellTypes.VTK_HEXAHEDRON
cell_to_vtkcell(::Type{Cell{3,20,6}}) = VTKCellTypes.VTK_QUADRATIC_HEXAHEDRON
cell_to_vtkcell(::Type{Tetrahedron}) = VTKCellTypes.VTK_TETRA
cell_to_vtkcell(::Type{QuadraticTetrahedron}) = VTKCellTypes.VTK_QUADRATIC_TETRA

nodes_to_vtkorder(cell::AbstractCell) = collect(cell.nodes)

"""
    vtk_grid(filename::AbstractString, grid::Grid)

Create a unstructured VTK grid from a `Grid`. Return a `DatasetFile`
which data can be appended to, see `vtk_point_data` and `vtk_cell_data`.
"""
function WriteVTK.vtk_grid(filename::AbstractString, grid::Grid{dim,C,T}; compress::Bool=true) where {dim,C,T}
    cls = MeshCell[]
    for cell in grid.cells
        celltype = Ferrite.cell_to_vtkcell(typeof(cell))
        push!(cls, MeshCell(celltype, nodes_to_vtkorder(cell)))
    end
    coords = reshape(reinterpret(T, getnodes(grid)), (dim, getnnodes(grid)))
    return vtk_grid(filename, coords, cls; compress=compress)
end

function toparaview!(v, x::Vec{D}) where D
    v[1:D] .= x
end
function toparaview!(v, x::SecondOrderTensor{D}) where D
    tovoigt!(v, x)
end

"""
    vtk_point_data(vtk, data::Vector{<:AbstractTensor}, name)

Write the tensor field `data` to the vtk file. Two-dimensional tensors are padded with zeros.

For second order tensors the following indexing ordering is used:
`[11, 22, 33, 23, 13, 12, 32, 31, 21]`. This is the default Voigt order in Tensors.jl.
"""
function WriteVTK.vtk_point_data(
    vtk::WriteVTK.DatasetFile,
    data::Vector{S},
    name::AbstractString
    ) where {O, D, T, M, S <: Union{Tensor{O, D, T, M}, SymmetricTensor{O, D, T, M}}}
    noutputs = S <: Vec{2} ? 3 : M # Pad 2D Vec to 3D
    npoints = length(data)
    out = zeros(T, noutputs, npoints)
    for i in 1:npoints
        toparaview!(@view(out[:, i]), data[i])
    end
    return vtk_point_data(vtk, out, name; component_names=component_names(S))
end

function component_names(::Type{S}) where S
    names =
        S <:             Vec{1}   ? ["x"] :
        S <:             Vec      ? ["x", "y", "z"] : # Pad 2D Vec to 3D
        S <:          Tensor{2,1} ? ["xx"] :
        S <: SymmetricTensor{2,1} ? ["xx"] :
        S <:          Tensor{2,2} ? ["xx", "yy", "xy", "yx"] :
        S <: SymmetricTensor{2,2} ? ["xx", "yy", "xy"] :
        S <:          Tensor{2,3} ? ["xx", "yy", "zz", "yz", "xz", "xy", "zy", "zx", "yx"] :
        S <: SymmetricTensor{2,3} ? ["xx", "yy", "zz", "yz", "xz", "xy"] :
                                    nothing
    return names
end

function vtk_nodeset(vtk::WriteVTK.DatasetFile, grid::Grid{dim}, nodeset::String) where {dim}
    z = zeros(getnnodes(grid))
    z[collect(getnodeset(grid, nodeset))] .= 1.0
    vtk_point_data(vtk, z, nodeset)
end

"""
    vtk_cellset(vtk, grid::Grid)

Export all cell sets in the grid. Each cell set is exported with
`vtk_cell_data` with value 1 if the cell is in the set, and 0 otherwise.
"""
function vtk_cellset(vtk::WriteVTK.DatasetFile, grid::AbstractGrid, cellsets=keys(grid.cellsets))
    z = zeros(getncells(grid))
    for cellset in cellsets
        z .= 0.0
        z[collect(getcellset(grid, cellset))] .= 1.0
        vtk_cell_data(vtk, z, cellset)
    end
    return vtk
end

"""
    vtk_cellset(vtk, grid::Grid, cellset::String)

Export the cell set specified by `cellset` as cell data with value 1 if
the cell is in the set and 0 otherwise.
"""
vtk_cellset(vtk::WriteVTK.DatasetFile, grid::AbstractGrid, cellset::String) =
    vtk_cellset(vtk, grid, [cellset])

function WriteVTK.vtk_point_data(vtkfile, dh::AbstractDofHandler, u::Vector, suffix="")

    fieldnames = Ferrite.getfieldnames(dh)  # all primary fields

    for name in fieldnames
        data = reshape_to_nodes(dh, u, name)
        vtk_point_data(vtkfile, data, string(name, suffix))
    end

    return vtkfile
end


text:
# ---
# title: 1330. Reverse Subarray To Maximize Array Value
# id: problem1330
# author: Tian Jun
# date: 2020-10-31
# difficulty: Hard
# categories: Array, Math
# link: <https://leetcode.com/problems/reverse-subarray-to-maximize-array-value/description/>
# hidden: true
# ---
#
# You are given an integer array `nums`. The _value_ of this array is defined as
# the sum of `|nums[i]-nums[i+1]|` for all `0 <= i < nums.length-1`.
#
# You are allowed to select any subarray of the given array and reverse it. You
# can perform this operation **only once**.
#
# Find maximum possible value of the final array.
#
#
#
# **Example 1:**
#
#
#
#     Input: nums = [2,3,1,5,4]
#     Output: 10
#     Explanation: By reversing the subarray [3,1,5] the array becomes [2,5,1,3,4] whose value is 10.
#
#
# **Example 2:**
#
#
#
#     Input: nums = [2,4,9,24,2,1,10]
#     Output: 68
#
#
#
#
# **Constraints:**
#
#   * `1 <= nums.length <= 3*10^4`
#   * `-10^5 <= nums[i] <= 10^5`
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
@safetestset "basic rendering" begin
  using Genie
  using Genie.Renderer.Html
  using Genie.Requests
  import Genie.Util: fws

  content = "abcd"
  content2 = "efgh"

  @testset "Basic rendering" begin
    r = Requests.HTTP.Response()

    @testset "Empty string" begin
      r = html("")

      @test String(r.body) == ""
    end;

    # @testset "Empty string force parse" begin
    #   @test_throws ArgumentError html("", forceparse = true)
    # end;

    @testset "String no spaces" begin
      r = html(content)

      @test String(r.body) == "$content"
    end;

    @testset "String no spaces force parse" begin
      r = html(content, forceparse = true)

      @test String(r.body) |> fws  == "<!DOCTYPE html>
abcd
" |> fws
    end;

    @testset "String with 2 spaces" begin
      r = html("  $content  ")

      @test String(r.body) == "  abcd  "
    end;

    @testset "String with 2 spaces force parse" begin
      r = html("  $content  ", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
abcd
" |> fws
    end;

    @testset "String with  " begin
      r = html("      ")

      @test String(r.body) == "      "
    end;

    @testset "String with   force parse" begin
      r = html("      ", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>

" |> fws
    end;

    @testset "String with 2   and 2 spaces" begin
      r = html("  $content  ")

      @test String(r.body) == "  abcd  "
    end;

    @testset "String with 2   and 2 spaces force parse" begin
      r = html("  $content  ", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
  abcd
" |> fws
    end;

    @testset "String with newline" begin
      r = html("$content  \n    $content2")

      @test String(r.body) == "abcd  \n    efgh"
    end;

    @testset "String with newline force parse" begin
      r = html("$content  \n    $content2", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
abcd  \n  efgh
" |> fws
    end;

    @testset "String with quotes" begin
      r = html("He said \"wow!\"")

      @test String(r.body) == "He said \"wow!\""
    end;

    @testset "String with quotes force parse" begin
      r = html("He said \"wow!\"", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
He said \"wow!\"\0
" |> fws
    end;

    @testset "String with quotes" begin
      r = html(""" "" """)

      @test String(r.body) == " \"\" "
    end;

    @testset "String with quotes force parse" begin
      r = html(""" "" """, forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
\"\"
" |> fws
    end;

    @testset "String with quotes" begin
      r = html("\"\"")

      @test String(r.body) == "\"\""
    end;

    @testset "String with quotes force parse" begin
      r = html("\"\"", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
\"\"\0
" |> fws
    end;

    @testset "String with interpolated vars" begin
      r = html("$(reverse(content))")

      @test String(r.body) == "dcba"
    end;

    @testset "String with interpolated vars force parse" begin
      r = html("$(reverse(content))", forceparse = true)

      @test String(r.body) |> fws == "<!DOCTYPE html>
dcba
" |> fws
    end;

    @test r.status == 200
    @test r.headers[1]["Content-Type"] == "text/html; charset=utf-8"
  end;
end


text:
#Set default color scheme to use ColorBrewer scales
#Not all functions use default_scales, so need to set default using colorscheme!
#ordinal, time, utc,
#quantitative: linear, log, pow, sqrt, quantile, quantize, threshold
function default_scales!(v::VegaVisualization;
                        typeXaxis::AbstractString = "linear",
                        typeYaxis::AbstractString = "linear")

    table = v.data[1].name

    v.scales = Array{VegaScale}(3)

    v.scales[1] = VegaScale(name = "x",
                            _type = typeXaxis,
                            range = "width",
                            domain = VegaDataRef(data = table, field = "x", sort = true))
    v.scales[2] = VegaScale(name = "y",
                            _type = typeYaxis,
                            range = "height",
                            domain = VegaDataRef(data = table, field = "y"))

    v.scales[3] = VegaScale(name = "group",
                            _type = "ordinal",
                            range = colorpalettes["Paired"]["12"],
                            domain = VegaDataRef(data = table, field = "group"))
    return v
end

function default_axes!(v::VegaVisualization)

    v.axes = Array{VegaAxis}(2)

    v.axes[1] = VegaAxis(_type = "x", scale = "x", title = "x",
                            properties = Dict{Any, Any}("title" => Dict{Any, Any}("fontSize" => Dict{Any, Any}("value" => 14))))

    v.axes[2] = VegaAxis(_type = "y", scale = "y", title = "y",
                            properties = Dict{Any, Any}("title" => Dict{Any, Any}("fontSize" => Dict{Any, Any}("value" => 14))))

    return v
end


text:
import Plots.plot

"""
    plot(s1::Schumaker, interval::Tuple{R,R} = (s1.IntStarts_[1], s1.IntStarts_[length(s1.IntStarts_)]); derivs::Bool = false, grid_len::Integer = 200, plot_options::NamedTuple = (label = "Spline",), deriv_plot_options::NamedTuple = (label = "Spline - 1st deriv",),
              deriv2_plot_options::NamedTuple = (label = "Spline - 2nd deriv",), plt = missing) where R<:Real
    plot(s1::Schumaker, grid::AbstractArray{R,1}; derivs::Bool = false, plot_options::NamedTuple = (label = "Spline",), deriv_plot_options::NamedTuple = (label = "Spline - 1st deriv",),
              deriv2_plot_options::NamedTuple = (label = "Spline - 2nd deriv",), plt = missing) where R<:Real

### Inputs
* `s1` - The Schumaker spline to chart
* `interval` - The interval over which to chart it.
* `grid_len` - The number of grid points to be used in plotting.
* `grid` - The grid. If used this is instead of the `interval` and `grid_len`
* `derivs` - Should the derivative splines also be plotted
* `plot_options` - The options to use in plotting
* `deriv_plot_options` - The options to use in the first derivative plot.
* `deriv2_plot_options`- The options to use in the second derivative plot.
* `plt` - A plot object. Feed this in if you want to add to a plot (rather than make a new one.)
### Returns
* A plot
"""
function plot(s1::Schumaker, interval::Tuple{R,R} = (s1.IntStarts_[1], s1.IntStarts_[length(s1.IntStarts_)]); derivs::Bool = false, grid_len::Integer = 200, plot_options::NamedTuple = (label = "Spline",), deriv_plot_options::NamedTuple = (label = "Spline - 1st deriv",),
              deriv2_plot_options::NamedTuple = (label = "Spline - 2nd deriv",), plt = missing) where R<:Real
    grid = collect(range(interval[1], interval[2], length=grid_len))
    return plot(s1, grid;  derivs = derivs, plot_options = plot_options, deriv_plot_options = deriv_plot_options, deriv2_plot_options = deriv2_plot_options, plt = plt)
end
function plot(s1::Schumaker, grid::AbstractArray{R,1}; derivs::Bool = false, plot_options::NamedTuple = (label = "Spline",), deriv_plot_options::NamedTuple = (label = "Spline - 1st deriv",),
              deriv2_plot_options::NamedTuple = (label = "Spline - 2nd deriv",), plt = missing) where R<:Real
    evals = s1.(grid)
    plt = ismissing(plt) ? plot(grid, evals; plot_options...) : plot!(plt, grid, evals; plot_options...)
    if derivs
        evals_1 = evaluate.(s1,grid, 1)
        plt = plot!(plt, grid, evals_1; deriv_plot_options...)
        evals_2 = evaluate.(s1,grid, 2)
        plt = plot!(plt, grid, evals_2; deriv2_plot_options...)
        return plt
    else
        return plt
    end
end

"""
    plot(ss::Vector{Schumaker}, interval::Tuple{R,R} = (ss[1].IntStarts_[1], ss[1].IntStarts_[length(ss[1].IntStarts_)]); derivs::Bool = false, grid_len::Integer = 200, plot_options::Union{AbstractArray{Tuple,1},Missing} = missing,
         deriv_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, deriv2_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, plt = missing)  where R<:Real
    plot(ss::Vector{Schumaker}, grid::Vector{R}; derivs::Bool = false, plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, deriv_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing,
         deriv2_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, plt = missing) where R<:Real
### Inputs
* `ss` - a vector of Schumaker splines to chart
* `interval` - The interval over which to chart it.
* `grid_len` - The number of grid points to be used in plotting.
* `grid` - The grid. If used this is instead of the `interval` and `grid_len`
* `derivs` - Should the derivative splines also be plotted
* `plot_options` - The options to use in plotting
* `deriv_plot_options` - The options to use in the first derivative plot.
* `deriv2_plot_options`- The options to use in the second derivative plot.
* `plt` - A plot object. Feed this in if you want to add to a plot (rather than make a new one.)
### Returns
* A plot
"""
function plot(ss::Vector{Schumaker}, interval::Tuple{R,R} = (ss[1].IntStarts_[1], ss[1].IntStarts_[length(ss[1].IntStarts_)]); derivs::Bool = false, grid_len::Integer = 200, plot_options::Union{AbstractArray{Tuple,1},Missing} = missing,
              deriv_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, deriv2_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, plt = missing)  where R<:Real
    grid = collect(range(interval[1], interval[2], length=grid_len))
    return plot(ss, grid; derivs = derivs, plot_options = plot_options, deriv_plot_options = deriv_plot_options, deriv2_plot_options = deriv2_plot_options, plt = plt)
end

function plot(ss::Vector{Schumaker}, grid::Vector{R}; derivs::Bool = false, plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, deriv_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing,
               deriv2_plot_options::Union{AbstractArray{Tuple,1},Missing} = missing, plt = missing) where R<:Real
    plt = ismissing(plt) ? plot() : plt
    for i in 1:length(ss)
        plot_options_i = ismissing(plot_options) ? (label = string("Spline ", i),) : plot_options[i]
        deriv_plot_options_i = ismissing(deriv_plot_options) ? (label = string("Spline ", i, " - 1st deriv"),) : deriv_plot_options[i]
        deriv2_plot_options_i = ismissing(deriv2_plot_options) ? (label = string("Spline ", i, " - 2nd deriv"),) : deriv2_plot_options[i]
        plt = plot(ss[i], grid; derivs = derivs, plot_options = plot_options_i, deriv_plot_options = deriv_plot_options_i, deriv2_plot_options = deriv2_plot_options_i, plt = plt)
    end
    return plt
end


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: data_pipeline

using AWS.Compat
using AWS.UUIDs
"""
    ActivatePipeline()

Validates the specified pipeline and starts processing pipeline tasks. If the pipeline does not pass validation, activation fails. If you need to pause the pipeline to investigate an issue with a component, such as a data source or script, call DeactivatePipeline. To activate a finished pipeline, modify the end date for the pipeline and then activate it.

# Required Parameters
- `pipelineId`: The ID of the pipeline.

# Optional Parameters
- `parameterValues`: A list of parameter values to pass to the pipeline at activation.
- `startTimestamp`: The date and time to resume the pipeline. By default, the pipeline resumes from the last completed execution.
"""

activate_pipeline(pipelineId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ActivatePipeline", Dict{String, Any}("pipelineId"=>pipelineId); aws_config=aws_config)
activate_pipeline(pipelineId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ActivatePipeline", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId), args)); aws_config=aws_config)

"""
    AddTags()

Adds or modifies tags for the specified pipeline.

# Required Parameters
- `pipelineId`: The ID of the pipeline.
- `tags`: The tags to add, as key/value pairs.

"""

add_tags(pipelineId, tags; aws_config::AWSConfig=global_aws_config()) = data_pipeline("AddTags", Dict{String, Any}("pipelineId"=>pipelineId, "tags"=>tags); aws_config=aws_config)
add_tags(pipelineId, tags, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("AddTags", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId, "tags"=>tags), args)); aws_config=aws_config)

"""
    CreatePipeline()

Creates a new, empty pipeline. Use PutPipelineDefinition to populate the pipeline.

# Required Parameters
- `name`: The name for the pipeline. You can use the same name for multiple pipelines associated with your AWS account, because AWS Data Pipeline assigns each pipeline a unique pipeline identifier.
- `uniqueId`: A unique identifier. This identifier is not the same as the pipeline identifier assigned by AWS Data Pipeline. You are responsible for defining the format and ensuring the uniqueness of this identifier. You use this parameter to ensure idempotency during repeated calls to CreatePipeline. For example, if the first call to CreatePipeline does not succeed, you can pass in the same unique identifier and pipeline name combination on a subsequent call to CreatePipeline. CreatePipeline ensures that if a pipeline already exists with the same name and unique identifier, a new pipeline is not created. Instead, you'll receive the pipeline identifier from the previous attempt. The uniqueness of the name and unique identifier combination is scoped to the AWS account or IAM user credentials.

# Optional Parameters
- `description`: The description for the pipeline.
- `tags`: A list of tags to associate with the pipeline at creation. Tags let you control access to pipelines. For more information, see Controlling User Access to Pipelines in the AWS Data Pipeline Developer Guide.
"""

create_pipeline(name, uniqueId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("CreatePipeline", Dict{String, Any}("name"=>name, "uniqueId"=>uniqueId); aws_config=aws_config)
create_pipeline(name, uniqueId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("CreatePipeline", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name, "uniqueId"=>uniqueId), args)); aws_config=aws_config)

"""
    DeactivatePipeline()

Deactivates the specified running pipeline. The pipeline is set to the DEACTIVATING state until the deactivation process completes. To resume a deactivated pipeline, use ActivatePipeline. By default, the pipeline resumes from the last completed execution. Optionally, you can specify the date and time to resume the pipeline.

# Required Parameters
- `pipelineId`: The ID of the pipeline.

# Optional Parameters
- `cancelActive`: Indicates whether to cancel any running objects. The default is true, which sets the state of any running objects to CANCELED. If this value is false, the pipeline is deactivated after all running objects finish.
"""

deactivate_pipeline(pipelineId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DeactivatePipeline", Dict{String, Any}("pipelineId"=>pipelineId); aws_config=aws_config)
deactivate_pipeline(pipelineId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DeactivatePipeline", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId), args)); aws_config=aws_config)

"""
    DeletePipeline()

Deletes a pipeline, its pipeline definition, and its run history. AWS Data Pipeline attempts to cancel instances associated with the pipeline that are currently being processed by task runners. Deleting a pipeline cannot be undone. You cannot query or restore a deleted pipeline. To temporarily pause a pipeline instead of deleting it, call SetStatus with the status set to PAUSE on individual components. Components that are paused by SetStatus can be resumed.

# Required Parameters
- `pipelineId`: The ID of the pipeline.

"""

delete_pipeline(pipelineId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DeletePipeline", Dict{String, Any}("pipelineId"=>pipelineId); aws_config=aws_config)
delete_pipeline(pipelineId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DeletePipeline", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId), args)); aws_config=aws_config)

"""
    DescribeObjects()

Gets the object definitions for a set of objects associated with the pipeline. Object definitions are composed of a set of fields that define the properties of the object.

# Required Parameters
- `objectIds`: The IDs of the pipeline objects that contain the definitions to be described. You can pass as many as 25 identifiers in a single call to DescribeObjects.
- `pipelineId`: The ID of the pipeline that contains the object definitions.

# Optional Parameters
- `evaluateExpressions`: Indicates whether any expressions in the object should be evaluated when the object descriptions are returned.
- `marker`: The starting point for the results to be returned. For the first call, this value should be empty. As long as there are more results, continue to call DescribeObjects with the marker value from the previous call to retrieve the next set of results.
"""

describe_objects(objectIds, pipelineId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DescribeObjects", Dict{String, Any}("objectIds"=>objectIds, "pipelineId"=>pipelineId); aws_config=aws_config)
describe_objects(objectIds, pipelineId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DescribeObjects", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("objectIds"=>objectIds, "pipelineId"=>pipelineId), args)); aws_config=aws_config)

"""
    DescribePipelines()

Retrieves metadata about one or more pipelines. The information retrieved includes the name of the pipeline, the pipeline identifier, its current state, and the user account that owns the pipeline. Using account credentials, you can retrieve metadata about pipelines that you or your IAM users have created. If you are using an IAM user account, you can retrieve metadata about only those pipelines for which you have read permissions. To retrieve the full pipeline definition instead of metadata about the pipeline, call GetPipelineDefinition.

# Required Parameters
- `pipelineIds`: The IDs of the pipelines to describe. You can pass as many as 25 identifiers in a single call. To obtain pipeline IDs, call ListPipelines.

"""

describe_pipelines(pipelineIds; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DescribePipelines", Dict{String, Any}("pipelineIds"=>pipelineIds); aws_config=aws_config)
describe_pipelines(pipelineIds, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("DescribePipelines", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineIds"=>pipelineIds), args)); aws_config=aws_config)

"""
    EvaluateExpression()

Task runners call EvaluateExpression to evaluate a string in the context of the specified object. For example, a task runner can evaluate SQL queries stored in Amazon S3.

# Required Parameters
- `expression`: The expression to evaluate.
- `objectId`: The ID of the object.
- `pipelineId`: The ID of the pipeline.

"""

evaluate_expression(expression, objectId, pipelineId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("EvaluateExpression", Dict{String, Any}("expression"=>expression, "objectId"=>objectId, "pipelineId"=>pipelineId); aws_config=aws_config)
evaluate_expression(expression, objectId, pipelineId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("EvaluateExpression", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("expression"=>expression, "objectId"=>objectId, "pipelineId"=>pipelineId), args)); aws_config=aws_config)

"""
    GetPipelineDefinition()

Gets the definition of the specified pipeline. You can call GetPipelineDefinition to retrieve the pipeline definition that you provided using PutPipelineDefinition.

# Required Parameters
- `pipelineId`: The ID of the pipeline.

# Optional Parameters
- `version`: The version of the pipeline definition to retrieve. Set this parameter to latest (default) to use the last definition saved to the pipeline or active to use the last definition that was activated.
"""

get_pipeline_definition(pipelineId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("GetPipelineDefinition", Dict{String, Any}("pipelineId"=>pipelineId); aws_config=aws_config)
get_pipeline_definition(pipelineId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("GetPipelineDefinition", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId), args)); aws_config=aws_config)

"""
    ListPipelines()

Lists the pipeline identifiers for all active pipelines that you have permission to access.

# Optional Parameters
- `marker`: The starting point for the results to be returned. For the first call, this value should be empty. As long as there are more results, continue to call ListPipelines with the marker value from the previous call to retrieve the next set of results.
"""

list_pipelines(; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ListPipelines"; aws_config=aws_config)
list_pipelines(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ListPipelines", args; aws_config=aws_config)

"""
    PollForTask()

Task runners call PollForTask to receive a task to perform from AWS Data Pipeline. The task runner specifies which tasks it can perform by setting a value for the workerGroup parameter. The task returned can come from any of the pipelines that match the workerGroup value passed in by the task runner and that was launched using the IAM user credentials specified by the task runner. If tasks are ready in the work queue, PollForTask returns a response immediately. If no tasks are available in the queue, PollForTask uses long-polling and holds on to a poll connection for up to a 90 seconds, during which time the first newly scheduled task is handed to the task runner. To accomodate this, set the socket timeout in your task runner to 90 seconds. The task runner should not call PollForTask again on the same workerGroup until it receives a response, and this can take up to 90 seconds.

# Required Parameters
- `workerGroup`: The type of task the task runner is configured to accept and process. The worker group is set as a field on objects in the pipeline when they are created. You can only specify a single value for workerGroup in the call to PollForTask. There are no wildcard values permitted in workerGroup; the string must be an exact, case-sensitive, match.

# Optional Parameters
- `hostname`: The public DNS name of the calling task runner.
- `instanceIdentity`: Identity information for the EC2 instance that is hosting the task runner. You can get this value from the instance using http://169.254.169.254/latest/meta-data/instance-id. For more information, see Instance Metadata in the Amazon Elastic Compute Cloud User Guide. Passing in this value proves that your task runner is running on an EC2 instance, and ensures the proper AWS Data Pipeline service charges are applied to your pipeline.
"""

poll_for_task(workerGroup; aws_config::AWSConfig=global_aws_config()) = data_pipeline("PollForTask", Dict{String, Any}("workerGroup"=>workerGroup); aws_config=aws_config)
poll_for_task(workerGroup, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("PollForTask", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("workerGroup"=>workerGroup), args)); aws_config=aws_config)

"""
    PutPipelineDefinition()

Adds tasks, schedules, and preconditions to the specified pipeline. You can use PutPipelineDefinition to populate a new pipeline.  PutPipelineDefinition also validates the configuration as it adds it to the pipeline. Changes to the pipeline are saved unless one of the following three validation errors exists in the pipeline.   An object is missing a name or identifier field. A string or reference field is empty. The number of objects in the pipeline exceeds the maximum allowed objects. The pipeline is in a FINISHED state.   Pipeline object definitions are passed to the PutPipelineDefinition action and returned by the GetPipelineDefinition action.

# Required Parameters
- `pipelineId`: The ID of the pipeline.
- `pipelineObjects`: The objects that define the pipeline. These objects overwrite the existing pipeline definition.

# Optional Parameters
- `parameterObjects`: The parameter objects used with the pipeline.
- `parameterValues`: The parameter values used with the pipeline.
"""

put_pipeline_definition(pipelineId, pipelineObjects; aws_config::AWSConfig=global_aws_config()) = data_pipeline("PutPipelineDefinition", Dict{String, Any}("pipelineId"=>pipelineId, "pipelineObjects"=>pipelineObjects); aws_config=aws_config)
put_pipeline_definition(pipelineId, pipelineObjects, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("PutPipelineDefinition", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId, "pipelineObjects"=>pipelineObjects), args)); aws_config=aws_config)

"""
    QueryObjects()

Queries the specified pipeline for the names of objects that match the specified set of conditions.

# Required Parameters
- `pipelineId`: The ID of the pipeline.
- `sphere`: Indicates whether the query applies to components or instances. The possible values are: COMPONENT, INSTANCE, and ATTEMPT.

# Optional Parameters
- `limit`: The maximum number of object names that QueryObjects will return in a single call. The default value is 100.
- `marker`: The starting point for the results to be returned. For the first call, this value should be empty. As long as there are more results, continue to call QueryObjects with the marker value from the previous call to retrieve the next set of results.
- `query`: The query that defines the objects to be returned. The Query object can contain a maximum of ten selectors. The conditions in the query are limited to top-level String fields in the object. These filters can be applied to components, instances, and attempts.
"""

query_objects(pipelineId, sphere; aws_config::AWSConfig=global_aws_config()) = data_pipeline("QueryObjects", Dict{String, Any}("pipelineId"=>pipelineId, "sphere"=>sphere); aws_config=aws_config)
query_objects(pipelineId, sphere, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("QueryObjects", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId, "sphere"=>sphere), args)); aws_config=aws_config)

"""
    RemoveTags()

Removes existing tags from the specified pipeline.

# Required Parameters
- `pipelineId`: The ID of the pipeline.
- `tagKeys`: The keys of the tags to remove.

"""

remove_tags(pipelineId, tagKeys; aws_config::AWSConfig=global_aws_config()) = data_pipeline("RemoveTags", Dict{String, Any}("pipelineId"=>pipelineId, "tagKeys"=>tagKeys); aws_config=aws_config)
remove_tags(pipelineId, tagKeys, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("RemoveTags", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId, "tagKeys"=>tagKeys), args)); aws_config=aws_config)

"""
    ReportTaskProgress()

Task runners call ReportTaskProgress when assigned a task to acknowledge that it has the task. If the web service does not receive this acknowledgement within 2 minutes, it assigns the task in a subsequent PollForTask call. After this initial acknowledgement, the task runner only needs to report progress every 15 minutes to maintain its ownership of the task. You can change this reporting time from 15 minutes by specifying a reportProgressTimeout field in your pipeline. If a task runner does not report its status after 5 minutes, AWS Data Pipeline assumes that the task runner is unable to process the task and reassigns the task in a subsequent response to PollForTask. Task runners should call ReportTaskProgress every 60 seconds.

# Required Parameters
- `taskId`: The ID of the task assigned to the task runner. This value is provided in the response for PollForTask.

# Optional Parameters
- `fields`: Key-value pairs that define the properties of the ReportTaskProgressInput object.
"""

report_task_progress(taskId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ReportTaskProgress", Dict{String, Any}("taskId"=>taskId); aws_config=aws_config)
report_task_progress(taskId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ReportTaskProgress", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("taskId"=>taskId), args)); aws_config=aws_config)

"""
    ReportTaskRunnerHeartbeat()

Task runners call ReportTaskRunnerHeartbeat every 15 minutes to indicate that they are operational. If the AWS Data Pipeline Task Runner is launched on a resource managed by AWS Data Pipeline, the web service can use this call to detect when the task runner application has failed and restart a new instance.

# Required Parameters
- `taskrunnerId`: The ID of the task runner. This value should be unique across your AWS account. In the case of AWS Data Pipeline Task Runner launched on a resource managed by AWS Data Pipeline, the web service provides a unique identifier when it launches the application. If you have written a custom task runner, you should assign a unique identifier for the task runner.

# Optional Parameters
- `hostname`: The public DNS name of the task runner.
- `workerGroup`: The type of task the task runner is configured to accept and process. The worker group is set as a field on objects in the pipeline when they are created. You can only specify a single value for workerGroup. There are no wildcard values permitted in workerGroup; the string must be an exact, case-sensitive, match.
"""

report_task_runner_heartbeat(taskrunnerId; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ReportTaskRunnerHeartbeat", Dict{String, Any}("taskrunnerId"=>taskrunnerId); aws_config=aws_config)
report_task_runner_heartbeat(taskrunnerId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ReportTaskRunnerHeartbeat", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("taskrunnerId"=>taskrunnerId), args)); aws_config=aws_config)

"""
    SetStatus()

Requests that the status of the specified physical or logical pipeline objects be updated in the specified pipeline. This update might not occur immediately, but is eventually consistent. The status that can be set depends on the type of object (for example, DataNode or Activity). You cannot perform this operation on FINISHED pipelines and attempting to do so returns InvalidRequestException.

# Required Parameters
- `objectIds`: The IDs of the objects. The corresponding objects can be either physical or components, but not a mix of both types.
- `pipelineId`: The ID of the pipeline that contains the objects.
- `status`: The status to be set on all the objects specified in objectIds. For components, use PAUSE or RESUME. For instances, use TRY_CANCEL, RERUN, or MARK_FINISHED.

"""

set_status(objectIds, pipelineId, status; aws_config::AWSConfig=global_aws_config()) = data_pipeline("SetStatus", Dict{String, Any}("objectIds"=>objectIds, "pipelineId"=>pipelineId, "status"=>status); aws_config=aws_config)
set_status(objectIds, pipelineId, status, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("SetStatus", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("objectIds"=>objectIds, "pipelineId"=>pipelineId, "status"=>status), args)); aws_config=aws_config)

"""
    SetTaskStatus()

Task runners call SetTaskStatus to notify AWS Data Pipeline that a task is completed and provide information about the final status. A task runner makes this call regardless of whether the task was sucessful. A task runner does not need to call SetTaskStatus for tasks that are canceled by the web service during a call to ReportTaskProgress.

# Required Parameters
- `taskId`: The ID of the task assigned to the task runner. This value is provided in the response for PollForTask.
- `taskStatus`: If FINISHED, the task successfully completed. If FAILED, the task ended unsuccessfully. Preconditions use false.

# Optional Parameters
- `errorId`: If an error occurred during the task, this value specifies the error code. This value is set on the physical attempt object. It is used to display error information to the user. It should not start with string \"Service_\" which is reserved by the system.
- `errorMessage`: If an error occurred during the task, this value specifies a text description of the error. This value is set on the physical attempt object. It is used to display error information to the user. The web service does not parse this value.
- `errorStackTrace`: If an error occurred during the task, this value specifies the stack trace associated with the error. This value is set on the physical attempt object. It is used to display error information to the user. The web service does not parse this value.
"""

set_task_status(taskId, taskStatus; aws_config::AWSConfig=global_aws_config()) = data_pipeline("SetTaskStatus", Dict{String, Any}("taskId"=>taskId, "taskStatus"=>taskStatus); aws_config=aws_config)
set_task_status(taskId, taskStatus, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("SetTaskStatus", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("taskId"=>taskId, "taskStatus"=>taskStatus), args)); aws_config=aws_config)

"""
    ValidatePipelineDefinition()

Validates the specified pipeline definition to ensure that it is well formed and can be run without error.

# Required Parameters
- `pipelineId`: The ID of the pipeline.
- `pipelineObjects`: The objects that define the pipeline changes to validate against the pipeline.

# Optional Parameters
- `parameterObjects`: The parameter objects used with the pipeline.
- `parameterValues`: The parameter values used with the pipeline.
"""

validate_pipeline_definition(pipelineId, pipelineObjects; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ValidatePipelineDefinition", Dict{String, Any}("pipelineId"=>pipelineId, "pipelineObjects"=>pipelineObjects); aws_config=aws_config)
validate_pipeline_definition(pipelineId, pipelineObjects, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = data_pipeline("ValidatePipelineDefinition", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("pipelineId"=>pipelineId, "pipelineObjects"=>pipelineObjects), args)); aws_config=aws_config)


text:
using Documenter
using LightGraphsFlows
import LightGraphs
const lg = LightGraphs

makedocs(
    modules = [LightGraphsFlows],
    format = :html,
    sitename = "LightGraphsFlows",
	pages = Any[
		"Getting started"    => "index.md",
        "Maxflow algorithms" => "maxflow.md",
        "Multiroute flows"   => "multiroute.md",
        "Min-cost flows"   => "mincost.md",
        "Min-cut"   => "mincut.md",
    ]
)

deploydocs(
    deps        = nothing,
    make        = nothing,
    repo        = "github.com/JuliaGraphs/LightGraphsFlows.jl.git",
    target      = "build",
    julia       = "0.6",
    osname      = "linux"
)


text:
 ##############################################################################
##
## Non Linear Least Squares
##
##############################################################################
type LeastSquaresProblem{Tx, Ty, Tf, TJ, Tg}
    x::Tx
    y::Ty
    f!::Tf
    J::TJ
    g!::Tg
    function LeastSquaresProblem(x, y, f!, J, g!)
        length(x) == size(J, 2) || throw(DimensionMismatch("x must have length size(J, 2)"))
        length(y) == size(J, 1) || throw(DimensionMismatch("y must have length size(J, 1)"))
        size(J, 1) >= size(J, 2) || throw(DimensionMismatch("size(J, 1) must be greater than size(J, 2)"))
        new(x, y, f!, J, g!)
    end
end

LeastSquaresProblem{Tx, Ty, Tf, TJ, Tg}(x::Tx, y::Ty, f!::Tf, J::TJ, g!::Tg) = LeastSquaresProblem{Tx, Ty, Tf, TJ, Tg}(x, y, f!, J, g!)

function LeastSquaresProblem(;x = error("initial x required"), y = nothing, f! = error("initial f! required"), g! = nothing, J = nothing, output_length = 0, chunk_size = 1)
    if typeof(y) == Void
        if output_length == 0
            output_length = size(J, 2)
        end
        y = zeros(eltype(x), output_length)
    end
    if typeof(J) == Void
        J = zeros(eltype(x), length(y), length(x))
    end
    newg! = g!
    if typeof(g!) == Void
        permf!(yp::Vector, xp::Vector) = f!(xp, yp)
        y0 = deepcopy(y)
        newg! = (xp::Vector, Jp::Matrix) -> ForwardDiff.jacobian!(Jp, permf!, y0, x, Chunk{chunk_size}())
    end
    LeastSquaresProblem(x, y , f!, J, newg!)
end

###############################################################################
##
## Non Linear Least Squares Allocated
## groups a LeastSquaresProblem with allocations
##
##############################################################################
# optimizer
abstract AbstractOptimizer
immutable Dogleg <: AbstractOptimizer end
immutable LevenbergMarquardt <: AbstractOptimizer end

# solver
abstract AbstractSolver
immutable QR <: AbstractSolver end
immutable Cholesky <: AbstractSolver end
type LSMR{T1, T2} <: AbstractSolver
    preconditioner!::T1
    preconditioner::T2
end
LSMR() = LSMR(nothing, nothing)

## for dense matrices, default to cholesky ; otherwise LSMR
function default_solver(x::AbstractSolver, J)
    if (typeof(x) <: QR) && (typeof(J) <: SparseMatrixCSC)
        throw("solver QR() is not available for sparse Jacobians. Choose between Cholesky() and LSMR()")
    end
    x
end
default_solver(::Void, J::StridedVecOrMat) = QR()
default_solver(::Void, J) = LSMR()

## for LSMR, default to levenberg_marquardt ; otherwise dogleg
default_optimizer(x::AbstractOptimizer, y) = x
default_optimizer(::Void, ::LSMR) = LevenbergMarquardt()
default_optimizer(::Void, ::AbstractSolver) = Dogleg()

abstract AbstractAllocatedOptimizer
abstract AbstractAllocatedSolver

type LeastSquaresProblemAllocated{Tx, Ty, Tf, TJ, Tg, Toptimizer <: AbstractAllocatedOptimizer, Tsolver <: AbstractAllocatedSolver}
    x::Tx
    y::Ty
    f!::Tf
    J::TJ
    g!::Tg
    optimizer::Toptimizer
    solver::Tsolver
end

# Constructor
function LeastSquaresProblemAllocated(nls::LeastSquaresProblem, optimizer::Union{Void, AbstractOptimizer}, solver::Union{Void, AbstractSolver})
    solver = default_solver(solver, nls.J)
    optimizer = default_optimizer(optimizer, solver)
    LeastSquaresProblemAllocated(
        nls.x, nls.y, nls.f!, nls.J, nls.g!, AbstractAllocatedOptimizer(nls, optimizer), AbstractAllocatedSolver(nls, optimizer, solver))
end
function LeastSquaresProblemAllocated(args...; kwargs...)
    LeastSquaresProblemAllocated(LeastSquaresProblem(args...); kwargs...)
end

# optimize
function optimize!(nls::LeastSquaresProblem, optimizer::Union{Void, AbstractOptimizer} = nothing, solver::Union{Void, AbstractSolver} = nothing; kwargs...)
    nlsp = LeastSquaresProblemAllocated(nls, optimizer, solver)
    optimize!(nlsp; kwargs...)
end

###############################################################################
##
## Result of Non Linear Least Squares
##
##############################################################################

type LeastSquaresResult{Tx}
    optimizer::String
    minimizer::Tx
    ssr::Float64
    iterations::Int
    converged::Bool
    x_converged::Bool
    xtol::Real
    f_converged::Bool
    ftol::Real
    gr_converged::Bool
    grtol::Real
    tr::OptimizationTrace
    f_calls::Int
    g_calls::Int
    mul_calls::Int
end

function LeastSquaresResult(optimizer::String, minimizer, ssr::Real, iterations::Int, converged::Bool, x_converged::Bool, xtol::Real, f_converged::Bool, ftol::Real, gr_converged::Bool, grtol::Real, tr::OptimizationTrace, f_calls::Int, g_calls::Int, mul_calls::Int)
    LeastSquaresResult(optimizer, minimizer, convert(Float64, ssr), iterations, converged, x_converged, convert(Float64, xtol), f_converged, convert(Float64, ftol), gr_converged, convert(Float64, grtol), tr, f_calls, g_calls, mul_calls)
end

function converged(r::LeastSquaresResult)
    return r.x_converged || r.f_converged || r.gr_converged
end

function Base.show(io::IO, r::LeastSquaresResult)
    @printf io "Results of Optimization Algorithm\n"
    @printf io " * Algorithm: %s\n" r.optimizer
    @printf io " * Minimizer: [%s]\n" join(r.minimizer, ",")
    @printf io " * Sum of squares at Minimum: %f\n" r.ssr
    @printf io " * Iterations: %d\n" r.iterations
    @printf io " * Convergence: %s\n" converged(r)
    @printf io " * |x - x'| < %.1e: %s\n" r.xtol r.x_converged
    @printf io " * |f(x) - f(x')| / |f(x)| < %.1e: %s\n" r.ftol r.f_converged
    @printf io " * |g(x)| < %.1e: %s\n" r.grtol r.gr_converged
    @printf io " * Function Calls: %d\n" r.f_calls
    @printf io " * Gradient Calls: %d\n" r.g_calls
    @printf io " * Multiplication Calls: %d\n" r.mul_calls
    return
end


text:
"""
    JSON3.@pretty json_str

Pretty print a JSON string or an object as JSON.
"""
macro pretty(json)
    return esc(:(JSON3.pretty($json)))
end

"""
    JSON3.pretty(x; kw...)
    JSON3.pretty(io, x; kw...)

Pretty print a JSON string.

## Args

* `x`: A JSON string, or an object to write to JSON then pretty print.
* `io`: The `IO` object to write the pretty printed string to. [default `stdout`]

## Keyword Args

See [`JSON3.write`](@ref) and [`JSON3.read`](@ref).
"""
pretty(str; kw...) = pretty(stdout, str; kw...)
pretty(out::IO, x; kw...) = pretty(out, JSON3.write(x; kw...); kw...)
function pretty(out::IO, str::String, indent=0, offset=0; kw...)
    buf = codeunits(str)
    len = length(buf)
    if len == 0
        return
    end
    pos = 1
    b = getbyte(buf, pos)
    @wh
    # printing object?
    if b == UInt8('{')
        Base.write(out, b)
        pos += 1
        @eof
        b = getbyte(buf, pos)
        @wh
        if b == UInt8('}')
            Base.write(out, b)
            return
        end
        Base.write(out, '\n')
        indent += 1
        keys = []
        vals = []
        # loop thru all key-value pairs, keeping track of longest key to pad others
        while b != UInt8('}')
            pos, str = JSON3.read(StructTypes.StringType(), buf, pos, len, b, String; kw...)
            push!(keys, str)
            @eof
            b = getbyte(buf, pos) # ':'
            @wh
            pos += 1
            @eof
            b = getbyte(buf, pos)
            @wh
            pos, x = JSON3.read(StructTypes.Struct(), buf, pos, len, b, Any; kw...)
            push!(vals, x)
            @eof
            b = getbyte(buf, pos) # ',' or '}'
            @wh
            if b == UInt8('}')
                break
            end
            pos += 1
            @eof
            b = getbyte(buf, pos)
            @wh
        end
        maxlen = maximum(map(sizeof, keys)) + 5
        # @show maxlen
        for i = 1:length(keys)
            Base.write(out, "  "^indent)
            Base.write(out, lpad("\"$(keys[i])\"" * ": ", maxlen + offset, ' '))
            pretty(out, JSON3.write(vals[i]; kw...), indent, maxlen + offset; kw...)
            if i == length(keys)
                indent -= 1
                Base.write(out, "\n" * ("  "^indent * " "^offset) * "}")
            else
                Base.write(out, ",\n")
            end
        end

    # printing array?
    elseif b == UInt8('[')
        Base.write(out, b)
        pos += 1
        @eof
        b = getbyte(buf, pos)
        @wh
        if b == UInt8(']')
            Base.write(out, b)
            return
        end
        Base.write(out, '\n')
        indent += 1
        vals = []
        while b != UInt8(']')
            pos, x = JSON3.read(StructTypes.Struct(), buf, pos, len, b, Any; kw...)
            push!(vals, x)
            @eof
            b = getbyte(buf, pos) # ',' or ']'
            @wh
            if b == UInt8(']')
                break
            end
            pos += 1
            @eof
            b = getbyte(buf, pos)
            @wh
        end
        for (i, val) in enumerate(vals)
            Base.write(out, "  "^indent * " "^offset)
            pretty(out, JSON3.write(vals[i]; kw...), indent, offset; kw...)
            if i == length(vals)
                indent -= 1
                Base.write(out, "\n" * ("  "^indent * " "^offset) * "]")
            else
                Base.write(out, ",\n")
            end
        end

    # printing constant?
    else
        Base.write(out, str)
    end
    return
@label invalid
    Base.error("error pretty-fying json: $error")
end


text:
using ArrayInterface, Test
import ArrayInterface: has_sparsestruct, findstructralnz
@test ArrayInterface.ismutable(rand(3))

using StaticArrays
@test ArrayInterface.ismutable(@SVector [1,2,3]) == false
@test ArrayInterface.ismutable(@MVector [1,2,3]) == true

using LinearAlgebra, SparseArrays

D=Diagonal([1,2,3,4])
@test has_sparsestruct(D)
rowind,colind=findstructralnz(D)
@test [D[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,2,3,4]
@test length(rowind)==4
@test length(rowind)==length(colind)

Bu = Bidiagonal([1,2,3,4], [7,8,9], :U)
@test has_sparsestruct(Bu)
rowind,colind=findstructralnz(Bu)
@test [Bu[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,7,2,8,3,9,4]
Bl = Bidiagonal([1,2,3,4], [7,8,9], :L)
@test has_sparsestruct(Bl)
rowind,colind=findstructralnz(Bl)
@test [Bl[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,7,2,8,3,9,4]

Tri=Tridiagonal([1,2,3],[1,2,3,4],[4,5,6])
@test has_sparsestruct(Tri)
rowind,colind=findstructralnz(Tri)
@test [Tri[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,2,3,4,4,5,6,1,2,3]
STri=SymTridiagonal([1,2,3,4],[5,6,7])
@test has_sparsestruct(STri)
rowind,colind=findstructralnz(STri)
@test [STri[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,2,3,4,5,6,7,5,6,7]

Sp=sparse([1,2,3],[1,2,3],[1,2,3])
@test has_sparsestruct(Sp)
rowind,colind=findstructralnz(Sp)
@test [Tri[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,2,3]


text:
using Abaco
using Test
using SafeTestsets

#DEBUG = get(ENV, "ABACO_DEBUG", "0")
#Abaco.logging(debug = DEBUG=="0" ? [] : [Abaco])

@testset "Abaco.jl" begin
    @testset "unit" begin
        @time @safetestset "get_values" begin include("test_get_values.jl") end
        @time @safetestset "push_value" begin include("test_push_value.jl") end
        @time @safetestset "too_old" begin include("test_too_old.jl") end
        @time @safetestset "push_msg" begin include("test_push_msg.jl") end
        @time @safetestset "push_ages" begin include("test_push_ages.jl") end
        @time @safetestset "multiverse" begin include("test_multiverse.jl") end
        @time @safetestset "operators" begin include("test_operators.jl") end
        @time @safetestset "invalid_formula" begin include("test_invalid_formula.jl") end
        @time @safetestset "if" begin include("test_if.jl") end
        @time @safetestset "csv_formulas" begin include("test_csv_formulas.jl") end
        @time @safetestset "co2" begin include("test_co2.jl") end
        @time @safetestset "progressive" begin include("test_progressive.jl") end
        @time @safetestset "deep_progressive" begin include("test_deep_progressive.jl") end
        @time @safetestset "deep_count" begin include("test_deep_count.jl") end
    end
end