text:
using Korg, Test, HDF5

@testset "atomic data" begin
    @test Korg.Natoms == length(Korg.atomic_masses) == length(Korg.solar_abundances)
    @test (Korg.get_mass(Korg.Formula("CO")) ≈
           Korg.get_mass(Korg.Formula("C")) + Korg.get_mass(Korg.Formula("O")))
    @test Korg.get_mass(Korg.Formula("C2")) ≈ 2Korg.get_mass(Korg.Formula("C"))
end

@testset "ionization energies" begin
    @test length(Korg.ionization_energies) == 92
    @test Korg.ionization_energies[Korg.atomic_numbers["H"]] == [13.5984, -1.000, -1.000]
    @test Korg.ionization_energies[Korg.atomic_numbers["Ru"]] == [7.3605, 16.760, 28.470]
    @test Korg.ionization_energies[Korg.atomic_numbers["U"]] == [6.1940, 11.590, 19.800]
end

function _test_contained_slice(vals::AbstractVector, interval::Korg.Interval)

    idx = Korg.contained_slice(vals, interval)
    first_ind, last_ind = first(idx), last(idx)

    @assert first_ind >= 1 && last_ind <= length(vals)

    result = Korg.contained.(vals, Ref(interval))

    if all(result)
        @test (first_ind == 1) && (last_ind == length(vals))
    elseif any(result)
        @test last_ind >= first_ind
        @test all(.!result[1:first_ind-1])
        @test all(result[first_ind:last_ind])
        @test all(.!result[last_ind+1:length(vals)])
    else
        @test first_ind == last_ind+1
    end

end

@testset "Interval" begin

    # first make sure that the following cases are caught by the constructor:
    @test_throws AssertionError Korg.Interval(5,5)
    @test_throws AssertionError Korg.Interval(3,2)
    @test_throws AssertionError Korg.Interval(Inf,Inf)
    @test_throws AssertionError Korg.Interval(-Inf,-Inf)

    # check contained
    sample = Korg.Interval(3,10)
    @test !Korg.contained(3, sample)
    @test !Korg.contained(10, sample)
    @test Korg.contained(5.0, sample)
    @test Korg.contained(nextfloat(3.0), sample)
    @test Korg.contained(prevfloat(10.0), sample)

    # check contained_slice
    @testset "contained_slice" begin
        # we consider cases where the slice contains just a single element or multiple elements

        # first, try cases where everything is in-bounds
        _test_contained_slice([6.0], sample) # slice of 1 element
        _test_contained_slice([4.0, 5.0, 6.0, 7.0, 8.0, 9.0], sample) # slice of multiple elements

        # next, try cases where some values are out-of bounds
        _test_contained_slice([1.0, 6.0], sample) # slice of 1 element
        _test_contained_slice([1.0, 6.0, 12.0], sample)
        _test_contained_slice([6.0, 12.0], sample)

        _test_contained_slice([1.0, 2.5, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], sample)
        _test_contained_slice([4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.5, 12.0], sample)
        _test_contained_slice([1.0, 2.5, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.5, 12.0], sample)

        # lastly, consider cases where all values are out of bounds
        _test_contained_slice([1.0], sample)
        _test_contained_slice([100.0], sample)

        _test_contained_slice([1.0, 2.0, 2.5], sample)
        _test_contained_slice([10.5, 12.5, 100.0], sample)
    end
end

include("continuum_absorption.jl") # test this after the "Interval" testset

"""
Compute nₑ (number density of free electrons) in a pure Hydrogen atmosphere, where `nH_tot` is the
total number density of H I and H II (in cm⁻³), the temperature is `T`, and `HI_partition_val` is
the the value of the H I partition function.

This is a relatively naive implementation. More numerically stable solutions exist.
"""
function electron_ndens_Hplasma(nH_tot, T, H_I_partition_val = 2.0)
    # Define the Saha equation as: nₑ*n_{H II} / n_{H I} = RHS
    # coef ∼ 4.829e15
    coef = 2.0 * (2.0*π*Korg.electron_mass_cgs*Korg.kboltz_cgs / Korg.hplanck_cgs^2)^1.5
    RHS = coef * T^1.5 * exp(-Korg.RydbergH_eV/(Korg.kboltz_eV*T))/H_I_partition_val
    # In a pure Hydrogen atmosphere: nₑ = n_{H II}. The Saha eqn becomes:  nₑ²/(nH_tot - ne) = RHS
    # We recast the Saha eqn as: a*nₑ² + b*nₑ + c = 0 and compute the coefficients
    a, b, c = (1.0, RHS, -1*RHS*nH_tot)
    # solve quadratic equation. Since b is always positive and c is always negative:
    #    (-b + sqrt(b²-4*a*c))/(2*a) is always ≥ 0
    #    (-b - sqrt(b²-4*a*c))/(2*a) is always negative
    nₑ = (-b + sqrt(b*b-4*a*c))/(2*a)
    nₑ
end

@testset "O I-III and CN partition functions are monotonic in T" begin
    Ts = 1:100:10000
    @test issorted(Korg.partition_funcs[Korg.species"O_I"].(Ts))
    @test issorted(Korg.partition_funcs[Korg.species"O_II"].(Ts))
    @test issorted(Korg.partition_funcs[Korg.species"O_III"].(Ts))
    @test issorted(Korg.partition_funcs[Korg.species"CN_I"].(Ts))
end

@testset "stat mech" begin
    @testset "pure Hydrogen atmosphere" begin
        nH_tot = 1e15
        # specify χs and Us to decouple this testset from other parts of the code
        χs = [(Korg.RydbergH_eV, -1.0, -1.0)]
        Us = Dict([Korg.species"H_I"=>(T -> 2.0), Korg.species"H_II"=>(T -> 1.0)])
        # iterate from less than 1% ionized to more than 99% ionized
        for T in [3e3, 4e3, 5e3, 6e3, 7e3, 8e3, 9e3, 1e4, 1.1e4, 1.2e4, 1.3e4, 1.4e4, 1.5e5]
            nₑ = electron_ndens_Hplasma(nH_tot, T, 2.0)
            wII, wIII = Korg.saha_ion_weights(T, nₑ, 1, χs, Us)
            @test wIII ≈ 0.0 rtol = 1e-15
            rtol = (T == 1.5e5) ? 1e-9 : 1e-14
            @test wII/(1 + wII + wIII) ≈ (nₑ/nH_tot) rtol= rtol
        end
    end

    @testset "monotonic N ions Temperature dependence" begin
        weights = [Korg.saha_ion_weights(T, 1.0, 7, Korg.ionization_energies,
                                            Korg.partition_funcs) for T in 1:100:10000]
        #N II + NIII grows with T === N I shrinks with T
        @test issorted(first.(weights) + last.(weights))

        # NIII grows with T
        @test issorted(last.(weights))
    end

    @testset "molecular equilibrium" begin
        #solar abundances
        abundances = Korg.get_absolute_abundances(0.0, Dict())
        nₜ = 1e15
        nₑ = 1e-3 * nₜ #arbitrary

        MEQs = Korg.molecular_equilibrium_equations(abundances, Korg.ionization_energies,
                                                       Korg.partition_funcs,
                                                       Korg.equilibrium_constants)
        @test MEQs.atoms == 0x01:Korg.Natoms

        n = Korg.molecular_equilibrium(MEQs, 5700.0, nₜ, nₑ)
        #make sure number densities are sensible
        @test (n[Korg.species"C_III"] < n[Korg.species"C_II"] < n[Korg.species"C_I"] <
               n[Korg.species"H_II"] < n[Korg.species"H_I"])

        #total number of carbons is correct
        total_C = map(collect(keys(n))) do species
            if species == Korg.species"C2"
                n[species] * 2
            elseif 0x06 in Korg.get_atoms(species.formula)
                n[species]
            else
                0.0
            end
        end |> sum
        @test total_C ≈ abundances[Korg.atomic_numbers["C"]] * nₜ
    end
end

@testset "lines" begin
    @testset "linelists" begin
        @testset "species codes" begin
            @test Korg.species"01.00"   == Korg.species"H"
            @test Korg.species"101.0"   == Korg.species"H2 I"
            @test Korg.species"01.0000" == Korg.species"H I"
            @test Korg.species"02.01"   == Korg.species"He II"
            @test Korg.species"02.1000" == Korg.species"He II"
            @test Korg.species"0608"    == Korg.species"CO"
            @test Korg.species"0606"    == Korg.species"C2 I"
            @test Korg.species"606"     == Korg.species"C2 I"
            @test Korg.species"0608.00" == Korg.species"CO I"
            @test Korg.species"OOO"     == Korg.species"O3"

            @test_throws ArgumentError Korg.Species("06.05.04")
            @test_throws Exception Korg.Species("99.01")
        end

        @testset "distinguish atoms from molecules" begin
            @test Korg.ismolecule(Korg.Formula("H2"))
            @test Korg.ismolecule(Korg.Formula("CO"))
            @test !Korg.ismolecule(Korg.Formula("H"))
            @test !Korg.ismolecule(Korg.Formula("Li"))
        end

        @testset "break molecules into atoms" begin
            @test Korg.get_atoms(Korg.Formula("CO")) == [0x06, 0x08]
            @test Korg.get_atoms(Korg.Formula("C2")) == [0x06, 0x06]
            @test Korg.get_atoms(Korg.Formula("MgO")) == [0x08, 0x0c]
        end

        @test_throws ArgumentError read_linelist("data/linelists/gfallvac08oct17.stub.dat";
                                                          format="abc")

        @testset "kurucz linelist parsing" begin
            for fname in ["gfallvac08oct17.stub.dat", "gfallvac08oct17-missing-col.stub.dat"]
                kurucz_ll = read_linelist("data/linelists/"*fname, format="kurucz")
                @test issorted(kurucz_ll, by=l->l.wl)
                @test length(kurucz_ll) == 987
                @test kurucz_ll[1].wl ≈ 0.0007234041763337705
                @test kurucz_ll[1].log_gf == -0.826
                @test kurucz_ll[1].species == Korg.species"Be_II"
                @test kurucz_ll[1].E_lower ≈ 17.360339371573698
                @test kurucz_ll[1].gamma_rad ≈ 8.511380382023759e7
                @test kurucz_ll[1].gamma_stark ≈ 0.003890451449942805
                @test kurucz_ll[1].vdW ≈ 1.2302687708123812e-7
            end
        end

        @testset "vald short format, ABO, missing params" begin
            linelist = read_linelist("data/linelists/linelist.vald")
            @test length(linelist) == 6
            @test linelist[1].wl ≈ 3000.0414 * 1e-8
            @test linelist[1].log_gf == -2.957
            @test linelist[1].species == Korg.species"Fe_I"
            @test linelist[1].E_lower ≈ 3.3014
            @test linelist[1].gamma_rad ≈ 1.905460717963248e7
            @test linelist[1].gamma_stark ≈ 0.0001230268770812381
            @test linelist[1].vdW ≈ 4.6773514128719815e-8

            #test imputation of missing broadening parameters
            @test linelist[2].gamma_rad ≈ 818252.5391161365
            @test linelist[2].gamma_stark == linelist[1].gamma_stark
            @test linelist[2].vdW == linelist[1].vdW

            @test linelist[3].gamma_rad == linelist[2].gamma_rad
            @test linelist[3].gamma_stark == 0.0001903497656604677
            @test linelist[3].vdW == linelist[1].vdW

            @test linelist[4].gamma_rad == linelist[1].gamma_rad
            @test linelist[4].gamma_stark == linelist[3].gamma_stark
            #this is failing on windows (due to https://github.com/JuliaLang/julia/issues/43088 ?)
            @test_skip linelist[4].vdW == 9.953360714197118e-8

            @test linelist[5].gamma_rad == linelist[1].gamma_rad
            @test linelist[5].gamma_stark == linelist[1].gamma_stark
            @test linelist[5].vdW == linelist[4].vdW

            #ABO params
            @test linelist[6].vdW[1] ≈ 1.3917417470792187e-14
            @test linelist[6].vdW[2] ≈ 0.227
        end

        @testset "vald various formats" begin
            short_all = read_linelist("data/linelists/short-extract-all.vald")
            long_all_cm_air = read_linelist("data/linelists/long-extract-all-air-wavenumber.vald")
            long_all_cm_air_noquotes = read_linelist("data/linelists/long-extract-all-air-wavenumber-noquotes.vald")
            short_stellar = read_linelist("data/linelists/short-extract-stellar.vald")
            long_stellar = read_linelist("data/linelists/long-extract-stellar.vald")

            @test (length(short_all) == length(short_stellar) == length(long_all_cm_air) ==
                   length(long_all_cm_air_noquotes) == length(long_stellar) == 2)

            #these should be identical since there was no unit conversion
            @test long_all_cm_air[1] == long_all_cm_air_noquotes[1]
            @test short_all[1] == short_stellar[1] == long_stellar[1]

            #when there was unit conversion, they should be approximately equal
            @test short_all[1].wl ≈ long_all_cm_air[1].wl
            @test short_all[1].log_gf == long_all_cm_air[1].log_gf
            @test short_all[1].species == long_all_cm_air[1].species
            @test short_all[1].E_lower ≈ long_all_cm_air[1].E_lower     atol=1e-3
            @test short_all[1].gamma_rad == long_all_cm_air[1].gamma_rad
            @test short_all[1].gamma_stark == long_all_cm_air[1].gamma_stark
            @test short_all[1].vdW == long_all_cm_air[1].vdW
        end

        @testset "vald isotopic scaling" begin
            short_all = read_linelist("data/linelists/isotopic_scaling/short-all-unscaled.vald")
            long_all = read_linelist("data/linelists/isotopic_scaling/long-all-unscaled.vald")
            short_stellar = read_linelist("data/linelists/isotopic_scaling/short-stellar-unscaled.vald")
            long_stellar = read_linelist("data/linelists/isotopic_scaling/long-stellar-unscaled.vald")
            scaled = read_linelist("data/linelists/isotopic_scaling/scaled.vald")
            unscaled_lists = [short_all, long_all, short_stellar, long_stellar]

            for list in unscaled_lists
                for field in [:wl, :species, :E_lower, :gamma_rad, :gamma_stark, :vdW]
                    @test getfield.(scaled, field) == getfield.(list, field)
                end
                for (line1, line2) in zip(scaled, list)
                    @test line1.log_gf .≈ line2.log_gf rtol=1e-2
                end
            end

            #make sure the default isotopic abundances sum to 1.
            isotopes = keys(Korg.isotopic_abundances)
            for Z in sort(collect(Set(first.(isotopes))))
                isos = filter(==(Z) ∘ first, isotopes)
                @assert sum([Korg.isotopic_abundances[iso] for iso in isos]) ≈ 1
            end
        end

        moog_linelist = read_linelist("data/linelists/s5eqw_short.moog"; format="moog")
        @testset "moog linelist parsing" begin
            @test issorted(moog_linelist, by=l->l.wl)
            @test moog_linelist[1].wl ≈ 3729.807 * 1e-8
            @test moog_linelist[1].log_gf ≈ -0.280
            @test moog_linelist[1].species == Korg.species"Ti_I"
            @test moog_linelist[2].E_lower ≈ 3.265
        end
    end

    @testset "move_bounds" begin
        a = 0.5 .+ (1:9)
        for lb in [1, 3, 9], ub in [1, 5, 9]
            @test Korg.move_bounds(a, lb, ub, 5., 2.) == (3, 6)
            @test Korg.move_bounds(a, lb, ub, 0., 3.) == (1, 2)
            @test Korg.move_bounds(a, lb, ub, 6., 4.) == (2, 9)
            @test Korg.move_bounds(collect(a), lb, ub, 5., 2.) == (3, 6)
            @test Korg.move_bounds(collect(a), lb, ub, 0., 3.) == (1, 2)
            @test Korg.move_bounds(collect(a), lb, ub, 6., 4.) == (2, 9)
        end
    end

    @testset "line profile" begin
        Δ = 0.01
        wls = (4955 : Δ : 5045) * 1e-8
        Δ *= 1e-8
        amplitude = 7.0
        for Δλ_D in [1e-7, 1e-8, 1e-9], Δλ_L in [1e-8, 1e-9]
            ϕ = Korg.line_profile.(5e-5, 1/Δλ_D, Δλ_L, amplitude, wls)
            @test issorted(ϕ[1 : Int(ceil(end/2))])
            @test issorted(ϕ[Int(ceil(end/2)) : end], rev=true)
            @test 0.99 < sum(ϕ .* Δ)/amplitude < 1
        end
    end

    @testset "hydrogen stark profiles" begin
        # This test data was generated with Korg.hydrogen_line_absorption shortly
        # after writing the function. This data is consistent with the results
        # produced by the Fortran code distributed with Stehle & Hutcheon 1999
        fname = "data/lyman_absorption.h5"
        αs_ref = h5read(fname,  "profile")

        fid = h5open("data/lyman_absorption.h5")
        T = HDF5.read_attribute(fid["profile"], "T")
        ne = HDF5.read_attribute(fid["profile"], "ne")
        nH_I = HDF5.read_attribute(fid["profile"], "nH_I")
        wls = (HDF5.read_attribute(fid["profile"], "start_wl") :
               HDF5.read_attribute(fid["profile"], "wl_step") :
               HDF5.read_attribute(fid["profile"], "stop_wl") )
        close(fid)

        αs = Korg.hydrogen_line_absorption(wls, 9000.0, 1e11, 1e13,
                                           Korg.partition_funcs[Korg.species"H_I"],
                                           Korg.hline_stark_profiles, 0.0)
        @test αs_ref ≈ αs rtol=1e-5
    end
end

@testset "atmosphere" begin
    @testset "plane-parallel atmosphere" begin
        #the MARCS solar model atmosphere
        atm = Korg.read_model_atmosphere("data/sun.mod")
        @test atm isa Korg.PlanarAtmosphere
        @test length(atm.layers) == 56
        @test issorted([l.temp for l in atm.layers])
        @test atm.layers[1].tau_5000 ≈ 0.00001209483645
        @test atm.layers[1].z == 6.931E+07
        @test atm.layers[1].temp == 4066.8
        @test atm.layers[1].electron_number_density ≈ 3.769664452210607e10
        @test atm.layers[1].number_density ≈ 4.75509171357701e14
    end
    @testset "spherical atmosphere" begin
        atm = Korg.read_model_atmosphere(
                "data/s6000_g+1.0_m0.5_t05_st_z+0.00_a+0.00_c+0.00_n+0.00_o+0.00_r+0.00_s+0.00.mod")
        @test atm isa Korg.ShellAtmosphere
        @test length(atm.layers) == 53 #drop layers hotter than 10^4 K
        @test issorted([l.temp for l in atm.layers])
        @test atm.R == 2.5827E+12
        @test atm.layers[1].tau_5000 ≈ 4.584584692493259e-5
        @test atm.layers[1].z == 2.222e11
        @test atm.layers[1].temp == 3935.2
        @test atm.layers[1].electron_number_density ≈ 1.7336231777439526e8
        @test atm.layers[1].number_density ≈ 1.5411190391302566e12
    end

    @testset "atmosphere type conversion" begin
        atm = Korg.read_model_atmosphere("data/sun.mod")
        atm2 = Korg.PlanarAtmosphere(Korg.ShellAtmosphere(atm, 7e10)) #arbitrary radius
        @test atm.layers == atm2.layers

        atm = Korg.read_model_atmosphere(
                "data/s6000_g+1.0_m0.5_t05_st_z+0.00_a+0.00_c+0.00_n+0.00_o+0.00_r+0.00_s+0.00.mod")
        atm2 = Korg.ShellAtmosphere(Korg.PlanarAtmosphere(atm), 1.0)
        @test [l.tau_5000 for l in atm.layers]                == [l.tau_5000 for l in atm2.layers]
        @test [l.z for l in atm.layers]                       == [l.z for l in atm2.layers]
        @test [l.temp for l in atm.layers]                    == [l.temp for l in atm2.layers]
        @test [l.number_density for l in atm.layers]          == [l.number_density for l in atm2.layers]
        @test [l.electron_number_density for l in atm.layers] == [l.electron_number_density for l in atm2.layers]
    end
end

@testset "synthesis" begin

    @testset "calculate absolute abundances" begin
        @test_throws ArgumentError Korg.get_absolute_abundances(0.0, Dict("H"=>13))

        @testset for metallicity in [0.0, 1.0], A_X in [Dict(), Dict("C"=>9)]
            nxnt = Korg.get_absolute_abundances(metallicity, A_X)

            #correct absolute abundances?
            if "C" in keys(A_X)
                @test log10(nxnt[6]/nxnt[1]) + 12 ≈ 9
            end
            @test log10(nxnt[2]/nxnt[1]) + 12 ≈ Korg.solar_abundances[2]
            @test log10(nxnt[Korg.atomic_numbers["Ba"]]/nxnt[1]) + 12 ≈
                Korg.solar_abundances[Korg.atomic_numbers["Ba"]] + metallicity

            #normalized?
            @test sum(nxnt) ≈ 1
        end
    end

    @testset "trapezoid rule" begin
        #gaussian PDF should integral to 1.
        pdf(x) = exp(-1/2 * x^2) / sqrt(2π)
        xs = -10:0.1:10
        fs = pdf.(xs)

        partial_ints = similar(xs)
        Korg.cumulative_trapezoid_rule!(partial_ints, xs, fs)

        naive_partial_integrals = map(1:length(xs)) do i
            Korg.trapezoid_rule(xs[1:i], fs[1:i])
        end

        #do they match the analytic solution?
        @test Korg.trapezoid_rule(xs, fs) ≈ 1.0  atol=1e-5
        @test partial_ints[end] ≈ 1.0 atol=1e-5

        #do they match each other?
        @test naive_partial_integrals ≈ partial_ints
    end
end

@testset "LSF" begin
    wls = 5000:0.35:6000
    R = 1800.0
    flux = zeros(Float64, length(wls))
    flux[500] = 5.0

    convF = Korg.constant_R_LSF(flux, wls, R)
    #normalized?
    @test sum(flux) ≈ sum(convF)

    #preserves line center?
    @test argmax(convF) == 500
end

@testset "air <--> vacuum" begin
    wls = collect(2000.0:π:10000.0)
    @test Korg.vacuum_to_air.(Korg.air_to_vacuum.(wls)) ≈ wls rtol=1e-3
    @test Korg.air_to_vacuum.(Korg.vacuum_to_air.(wls)) ≈ wls rtol=1e-3

    #try it in cgs
    wls .*= 1e8
    @test Korg.vacuum_to_air.(Korg.air_to_vacuum.(wls)) ≈ wls rtol=1e-3
    @test Korg.air_to_vacuum.(Korg.vacuum_to_air.(wls)) ≈ wls rtol=1e-3

    #units should be automatically chosen
    @test Korg.vacuum_to_air.(Korg.air_to_vacuum.(wls*1e-8)*1e8) ≈ wls rtol=1e-3
    @test Korg.air_to_vacuum.(Korg.vacuum_to_air.(wls*1e-8)*1e8) ≈ wls rtol=1e-3
    @test Korg.vacuum_to_air.(Korg.air_to_vacuum.(wls)*1e8)*1e-8 ≈ wls rtol=1e-3
    @test Korg.air_to_vacuum.(Korg.vacuum_to_air.(wls)*1e8)*1e-8 ≈ wls rtol=1e-3
end

using SpecialFunctions: expint
@testset "transfer" begin
    xs = 2:0.01:8
    @test Korg.exponential_integral_2.(xs) ≈ expint.(2, xs) rtol=1e-3
end

@testset "synthesize wavelength handling" begin
    atm = read_model_atmosphere("data/sun.mod")
    wls = 15000:0.01:15500
    @test synthesize(atm, [], 15000, 15500).wavelengths ≈ wls
    @test synthesize(atm, [], 15000, 15500; air_wavelengths=true).wavelengths ≈ Korg.air_to_vacuum.(wls)
    @test_throws ArgumentError synthesize(atm, [], 15000, 15500; air_wavelengths=true,
                                          wavelength_conversion_warn_threshold=1e-20)
    @test_throws ArgumentError synthesize(atm, [], 2000, 8000, air_wavelengths=true)
end

@testset "autodiff" begin
    using ForwardDiff

    for atm_file in ["data/sun.mod",
             "data/s6000_g+1.0_m0.5_t05_st_z+0.00_a+0.00_c+0.00_n+0.00_o+0.00_r+0.00_s+0.00.mod"]
        atm = read_model_atmosphere(atm_file)
        linelist = read_linelist("data/linelists/5000-5005.vald")
        wls = 5000:0.01:5005
        flux(p) = synthesize(atm, linelist, wls; metallicity=p[1], abundances=Dict(["Ni"=>p[2]]),
                             vmic=p[3]).flux
        #make sure this works.
        ∇f = ForwardDiff.jacobian(flux, [0.0, 0.0, 1.5])
    end
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct IoK8sApiCoreV1ConfigMapNodeConfigSource <: SwaggerModel
    kubeletConfigKey::Any # spec type: Union{ Nothing, String } # spec name: kubeletConfigKey
    name::Any # spec type: Union{ Nothing, String } # spec name: name
    namespace::Any # spec type: Union{ Nothing, String } # spec name: namespace
    resourceVersion::Any # spec type: Union{ Nothing, String } # spec name: resourceVersion
    uid::Any # spec type: Union{ Nothing, String } # spec name: uid

    function IoK8sApiCoreV1ConfigMapNodeConfigSource(;kubeletConfigKey=nothing, name=nothing, namespace=nothing, resourceVersion=nothing, uid=nothing)
        o = new()
        validate_property(IoK8sApiCoreV1ConfigMapNodeConfigSource, Symbol("kubeletConfigKey"), kubeletConfigKey)
        setfield!(o, Symbol("kubeletConfigKey"), kubeletConfigKey)
        validate_property(IoK8sApiCoreV1ConfigMapNodeConfigSource, Symbol("name"), name)
        setfield!(o, Symbol("name"), name)
        validate_property(IoK8sApiCoreV1ConfigMapNodeConfigSource, Symbol("namespace"), namespace)
        setfield!(o, Symbol("namespace"), namespace)
        validate_property(IoK8sApiCoreV1ConfigMapNodeConfigSource, Symbol("resourceVersion"), resourceVersion)
        setfield!(o, Symbol("resourceVersion"), resourceVersion)
        validate_property(IoK8sApiCoreV1ConfigMapNodeConfigSource, Symbol("uid"), uid)
        setfield!(o, Symbol("uid"), uid)
        o
    end
end # type IoK8sApiCoreV1ConfigMapNodeConfigSource

const _property_map_IoK8sApiCoreV1ConfigMapNodeConfigSource = Dict{Symbol,Symbol}(Symbol("kubeletConfigKey")=>Symbol("kubeletConfigKey"), Symbol("name")=>Symbol("name"), Symbol("namespace")=>Symbol("namespace"), Symbol("resourceVersion")=>Symbol("resourceVersion"), Symbol("uid")=>Symbol("uid"))
const _property_types_IoK8sApiCoreV1ConfigMapNodeConfigSource = Dict{Symbol,String}(Symbol("kubeletConfigKey")=>"String", Symbol("name")=>"String", Symbol("namespace")=>"String", Symbol("resourceVersion")=>"String", Symbol("uid")=>"String")
Base.propertynames(::Type{ IoK8sApiCoreV1ConfigMapNodeConfigSource }) = collect(keys(_property_map_IoK8sApiCoreV1ConfigMapNodeConfigSource))
Swagger.property_type(::Type{ IoK8sApiCoreV1ConfigMapNodeConfigSource }, name::Symbol) = Union{Nothing,eval(Meta.parse(_property_types_IoK8sApiCoreV1ConfigMapNodeConfigSource[name]))}
Swagger.field_name(::Type{ IoK8sApiCoreV1ConfigMapNodeConfigSource }, property_name::Symbol) =  _property_map_IoK8sApiCoreV1ConfigMapNodeConfigSource[property_name]

function check_required(o::IoK8sApiCoreV1ConfigMapNodeConfigSource)
    (getproperty(o, Symbol("kubeletConfigKey")) === nothing) && (return false)
    (getproperty(o, Symbol("name")) === nothing) && (return false)
    (getproperty(o, Symbol("namespace")) === nothing) && (return false)
    true
end

function validate_property(::Type{ IoK8sApiCoreV1ConfigMapNodeConfigSource }, name::Symbol, val)
end

ext: jl


text:
module CommunalHelperSyncedZipMoverActivationController

using ..Ahorn, Maple

@mapdef Entity "CommunalHelper/SyncedZipMoverActivationController" SyncedZipMoverActivationController(x::Integer,
                                                                                y::Integer,
                                                                                colorCode::String="ff00ff",
                                                                                zipMoverSpeedMultiplier::Number=1.0)

const placements = Ahorn.PlacementDict(
    "Synced Zip Mover Activation Controller (Communal Helper)" => Ahorn.EntityPlacement(
        SyncedZipMoverActivationController,
        "point",
        Dict{String, Any}(),
    )
)

sprite = "objects/CommunalHelper/syncedZipMoverActivationController/syncedZipMoverActivationController.png"

function Ahorn.selection(entity::SyncedZipMoverActivationController)
    x, y = Ahorn.position(entity)
    return Ahorn.getSpriteRectangle(sprite, x, y)
end

function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::SyncedZipMoverActivationController, room::Maple.Room)
	Ahorn.drawSprite(ctx, sprite, 0, 0)
end

end

max_stars_repo_name: FlynnSC/CommunalHelper

max_issues_repo_name: FlynnSC/CommunalHelper

max_forks_repo_name: FlynnSC/CommunalHelper


text:
using Compat
create_rp(rt::AbstractString) = p -> joinpath(abspath(rt, p))

export Utility

"""
# generate_ssl

`taken from httpserver example`
"""
function generate_ssl(root_path)
  rp = create_rp(root_path)
  if !isfile("keys/server.crt" |> rp)
    @compat @unix_only begin
      Base.run(`mkdir -p $(rp("keys"))`)
      Base.run(`openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout
      $(rp("keys/server.key")) -out $(rp("keys/server.crt"))`)
    end
  end
end

"""
# splitquery
"""
function splitquery(req)
  uri = URI(req[:resource])
  delete!(req, :resource)
  req[:path]  = split(uri.path, "/", keep=false)
  req[:query] = uri.query
  req
end

module Utility

"""
# including all files in a folder
"""
macro include_all_in(sym_or_string)
  quote
    for file_name in readdir($(esc(sym_or_string)))
      fn_abspath = joinpath($(esc(sym_or_string)), file_name) |> abspath
      include(fn_abspath)
    end
  end
end

make_appdir(dir) = dir |> dirname |> abspath

end


text:
"""
    function calc_markov_shock_from_uniform_rv(u::Float64, Pz_cdf::Array{Float64})
"""
function calc_markov_shock_from_uniform_rv(u::Float64, Pz_cdf::Array{Float64})
    done = false
    i_zn = 0

    while done==false
        i_zn = i_zn + 1;
        done = (u < Pz_cdf[i_zn]);
    end
    return i_zn
end

"""
    function simulate_markov_shocks(N::Int64, sim_z::Array{Int64}, Pz_cdf::Array{Float64})
"""
function simulate_markov_shocks(N::Int64, sim_z::Array{Int64}, Pz_cdf::Array{Float64})
    sim_zn=zeros(Int,N)

    u=rand(N)
    for i = 1:N
        sim_zn[i] = calc_markov_shock_from_uniform_rv(u[i], Pz_cdf[sim_z[i],:]);
    end
    return sim_zn
end

function simulate_markov_shocks(N::Int64, Pz_initial_cdf::Array{Float64})
    sim_z=zeros(Int,N)
    u=rand(N)

    for i = 1:N
        sim_z[i] = calc_markov_shock_from_uniform_rv(u[i], Pz_initial_cdf);
    end
    return sim_z
end

function interpolate_params(cohort,x,range)
    y1 = interpolate((cohort,),x,Gridded(Linear()))
    y2 = extrapolate(y1,Line())
    z=y2(range)
    return z
end


text:
using KernelFunctions, Test, Distances
#TODO Test metric weights for ARD, test equivalency for different constructors,
# test type conversion
l = 2.0
vl = [l,l]
s = ScaleTransform(l)

## SqExponentialKernel
@testset "SqExponentialKernel" begin
    @test KernelFunctions.metric(SqExponentialKernel(l)) == SqEuclidean()
    @test isequal(transform(SqExponentialKernel(l)),s)
    @test KernelFunctions.transform(SqExponentialKernel(vl)) == ARDTransform(vl)
    @test isequal(KernelFunctions.transform(SqExponentialKernel(s)),s)
end

## MaternKernel
@testset "MaternKernel" begin
    @test KernelFunctions.metric(MaternKernel(l)) == Euclidean()
    @test KernelFunctions.metric(Matern32Kernel(l)) == Euclidean()
    @test KernelFunctions.metric(Matern52Kernel(l)) == Euclidean()
    @test isequal(KernelFunctions.transform(MaternKernel(l)),s)
    @test isequal(KernelFunctions.transform(Matern32Kernel(l)),s)
    @test isequal(KernelFunctions.transform(Matern52Kernel(l)),s)
    @test KernelFunctions.transform(MaternKernel(vl)) == ARDTransform(vl)
    @test KernelFunctions.transform(Matern32Kernel(vl)) == ARDTransform(vl)
    @test KernelFunctions.transform(Matern52Kernel(vl)) == ARDTransform(vl)
    @test KernelFunctions.transform(MaternKernel(s)) == s
    @test KernelFunctions.transform(Matern32Kernel(s)) == s
    @test KernelFunctions.transform(Matern52Kernel(s)) == s
end


text:
using ADFPEPS
using ADFPEPS:double_ipeps_energy
using CUDA
using Random

CUDA.allowscalar(false)
Random.seed!(100)
model = THubbard(1.0,12.0,6.0)
folder = "E:/1 - research/4.9 - AutoDiff/data/ADFPEPS/Hubbard/"
ipeps, key = init_ipeps(model; Ni = 2, Nj = 2, atype = Array, folder = folder, D=2, χ=20, tol=1e-10, maxiter=10)
folder, model, Ni, Nj, atype, D, χ, tol, maxiter = key
double_ipeps_energy(atype(ipeps), model; Ni=Ni,Nj=Nj,χ=χ,maxiter=maxiter,infolder=folder,outfolder=folder)
# optimiseipeps(ipeps, key; f_tol = 1e-6, opiter = 100, verbose = true)


text:
"""
    total_variation(u)

Compute the discrete total variation
```math
    \\sum_{k} |u_{k+1} - u_{k}|.
```
"""
function total_variation(u)
  uprev = first(u)
  res = zero(uprev)
  @inbounds @simd for i in eachindex(u)[2:end]
    unext = u[i]
    res += abs(uprev - unext)
    uprev = unext
  end
  res
end

"""
    total_variation_denoising(y::AbstractVector, λ::Number)

Compute the solution of the total variation regularized least square problem
```math
    \\min_x \\frac{1}{2} \\sum_{k} |y_k - x_k|^2 + \\lambda \\sum_{k} |x_{k+1} - x_{k}|
```
using the explicit algorithm of
Condat (2013) A Direct Algorithm for 1-D Total Variation Denoising,
doi: 10.1109/LSP.2013.2278339.
"""
function total_variation_denoising(source::AbstractVector, λ::Number)
  T = promote_type(eltype(source), typeof(λ))
  dest = similar(source, T)
  total_variation_denoising!(dest, source, convert(T, λ))
end

"""
    total_variation_denoising!(dest::AbstractVector, source::AbstractVector, λ::Number)

In-place version of `total_variation_denoising(source, λ)` storing the result in `dest`.
"""
function total_variation_denoising!(dest::AbstractVector, source::AbstractVector, λ::Number)
  if λ < 0
    throw(ArgumentError("The regularization parameter λ must be non-negative: λ = $λ"))
  end

  idx = eachindex(dest, source)
  k = k₀ = k₋ = k₊ = first(idx)
  vmin = source[k] - λ
  vmax = source[k] + λ
  umin = λ
  umax = -λ

  if length(idx) == 1
    dest .= source
    return dest
  end

  @inbounds while true
    if k == length(idx)
      dest[idx[k]] = vmin + umin
      break
    end
    nextval = source[idx[k+1]]
    if nextval + umin < vmin - λ
      @simd for ki in k₀:k₋
        dest[idx[ki]] = vmin
      end
      k = k₀ = k₋ = k₊ = k₋ + 1
      thisval = source[idx[k]]
      vmin = thisval
      vmax = thisval + 2λ
      umin = λ
      umax = -λ
    elseif nextval + umax > vmax + λ
      @simd for ki in k₀:k₊
        dest[idx[ki]] = vmax
      end
      k = k₀ = k₋ = k₊ = k₊ + 1
      thisval = source[idx[k]]
      vmin = thisval - 2λ
      vmax = thisval
      umin = λ
      umax = -λ
    else
      k += 1
      umin += nextval - vmin
      umax += nextval - vmax
      if umin >= λ
        vmin += (umin - λ) / (k - k₀ + 1)
        umin = λ
        k₋ = k
      end
      if umax <= -λ
        vmax += (umax + λ) / (k - k₀ + 1)
        umax = -λ
        k₊ = k
      end
    end

    if k < length(idx)
      continue
    elseif umin < 0
      @simd for ki in k₀:k₋
        dest[idx[ki]] = vmin
      end
      k = k₀ = k₋ = k₋ + 1
      thisval = source[idx[k]]
      vmin = thisval
      umin = λ
      umax = thisval + λ - vmax
    elseif umax > 0
      @simd for ki in k₀:k₊
        dest[idx[ki]] = vmax
      end
      k = k₀ = k₊ = k₊ + 1
      thisval = source[idx[k]]
      vmax = thisval
      umin = thisval - λ - vmin
      umax = -λ
    else
      @simd for ki in k₀:length(idx)
        dest[idx[ki]] = vmin + umin / (k - k₀ + 1)
      end
      break
    end
  end

  dest
end

function reference(::Union{typeof(total_variation_denoising),
                           typeof(total_variation_denoising!)})
"""
@article{condat2013direct,
  title={A direct algorithm for 1-{D} total variation denoising},
  author={Condat, Laurent},
  journal={IEEE Signal Processing Letters},
  volume={20},
  number={11},
  pages={1054--1057},
  year={2013},
  publisher={IEEE},
  doi={10.1109/LSP.2013.2278339}
}
"""
end

"""
    group_sparse_total_variation_denoising(y::AbstractVector, λ::Number; group_size::Integer=1, max_iter::Integer=100)

Compute `max_iter` iterations of the algorithm described by
Selesnick and Chen (2013) Total variation denoising with overlapping group sparsity,
doi: 10.1109/ICASSP.2013.6638755.
"""
function group_sparse_total_variation_denoising(source::AbstractVector, λ::Number;
                                                group_size::Integer=1,
                                                max_iter::Integer=100)
  T = promote_type(eltype(source), typeof(λ))
  dest = similar(source, T)
  group_sparse_total_variation_denoising!(dest, source, convert(T, λ),
                                          group_size=group_size, max_iter=max_iter)
end

function diff!(dx, x)
  idx = eachindex(x)
  @inbounds @simd for i in idx[1:end-1]
    dx[i] = x[i+1] - x[i]
  end
  dx
end

function transpose_diff!(dx, x)
  idx = eachindex(x)
  @inbounds begin
    dx[idx[1]] = -x[idx[1]]
    @simd for i in idx[2:end-1]
      dx[i] = x[i-1] - x[i]
    end
    dx[idx[end]] = x[idx[end]]
  end
  dx
end

function group_sparse_total_variation_denoising!(dest::AbstractVector, source::AbstractVector, λ::Number;
                                                 group_size::Integer=1,
                                                 max_iter::Integer=100)
  if λ < 0
    throw(ArgumentError("The regularization parameter λ must be non-negative: λ = $λ"))
  end
  if axes(dest) !== axes(source)
    throw(DimensionMismatch("Dimensions must match: axes(dest) = $(axes(dest)) != $(axes(source)) = axes(source)"))
  end

  T = eltype(source)
  dest .= source
  b = similar(source, length(source)-1)
  diff!(b, source)
  tmp = similar(b)
  u = OffsetArray(similar(source, length(source)-1+2*(group_size-1)), 2-group_size:length(source)+group_size-2)
  u .= zero(T)
  dl = fill(-one(T), length(source)-2)
  F = Tridiagonal(dl, similar(source, length(source)-1), copy(dl))

  for iter in Base.OneTo(max_iter)
    diff!(u, dest)
    @inbounds @simd for n in eachindex(F.d)
      acc_outer = zero(T)
      for j in 0:group_size-1
        acc_inner = zero(T)
        for k in 0:group_size-1
          acc_inner += abs2(u[n - j + k])
        end
        acc_outer += inv(sqrt(acc_inner))
      end
      F.d[n] = 2 + inv(λ * acc_outer)
    end
    @. F.dl = F.du = -one(T)
    ldiv!(tmp, lu!(F), b)
    transpose_diff!(dest, tmp)
    @. dest = source - dest
  end

  dest
end

function reference(::Union{typeof(group_sparse_total_variation_denoising),
                           typeof(group_sparse_total_variation_denoising!)})
"""
@inproceedings{selesnick2013total,
  title={Total variation denoising with overlapping group sparsity},
  author={Selesnick, Ivan W and Chen, Po-Yu},
  booktitle={2013 IEEE International Conference on Acoustics,
             Speech and Signal Processing},
  pages={5696--5700},
  year={2013},
  organization={IEEE},
  doi={10.1109/ICASSP.2013.6638755}
}
"""
end


text:
using Compat
import Compat.String
import Compat.view
@compat import Base.show
using Base.Test

v = 1
@test_throws AssertionError @assert(v < 1)

type TestCustomShowType end
@compat function show(io::IO, ::MIME"text/plain", ::TestCustomShowType)
    print(io, "MyTestCustomShowType")
end
myio = IOBuffer()
display(TextDisplay(myio), MIME"text/plain"(), TestCustomShowType())
@test @compat String(myio) == "MyTestCustomShowType"

type TestCustomShowType2 end
@compat Base.show(io::IO, ::MIME"text/plain", ::TestCustomShowType2) = print(io, "MyTestCustomShowType2")
myio = IOBuffer()
display(TextDisplay(myio), MIME"text/plain"(), TestCustomShowType2())
@test @compat String(myio) == "MyTestCustomShowType2"

type TestCustomShowType3 end
@compat show(io::IO, ::TestCustomShowType3) = print(io, "2-Argument-show")
myio = IOBuffer()
display(TextDisplay(myio), TestCustomShowType3())
@test @compat String(myio) == "2-Argument-show"

immutable ParameterizedShowType{T}
    _::T
end
myio = IOBuffer()
@compat show{T}(io::IO, ::MIME"text/html", ::ParameterizedShowType{T}) =
    print(io, "::", T, "")
@compat show(myio, MIME("text/html"), ParameterizedShowType(0.0))
@test @compat String(myio) == "::Float64"

d = Dict(zip([1, 2], [3, 4]))
ns = length(d.slots)
@test length(sizehint!(d, ns + 1).slots) > ns

@test @compat split("a,b,,c", ',', limit=2) == ["a", "b,,c"]
@test @compat split("a,b,,c", ',', limit=2,keep=true) == ["a", "b,,c"]
@test @compat split("a,b,,c", ',', keep=false) == ["a", "b", "c"]
@test @compat split("a,b,,c", ',', keep=true) == ["a", "b", "", "c"]

@test @compat rsplit("a,b,,c", ',', limit=2) == ["a,b,", "c"]
@test @compat rsplit("a,b,,c", ',', limit=2,keep=true) == ["a,b,", "c"]
@test @compat rsplit("a,b,,c", ',', keep=false) == ["a", "b", "c"]
@test @compat rsplit("a,b,,c", ',', keep=true) == ["a", "b", "", "c"]

if VERSION < v"0.4.0-dev+1387"
    @test isdefined(Main, :AbstractString)
end

@test round(Int, 3//4) == 1
@test round(Int, 1) == 1
@test round(Int, 1.1) == 1
@test ceil(Int, 1) == 1
@test ceil(Int, 1.1) == 2
@test floor(Int, 1) == 1
@test floor(Int, 1.1) == 1
@test trunc(Int, 1) == 1
@test trunc(Int, 1.1) == 1

if VERSION < v"0.6.0-dev.1825"
    @test round(Int, [1, 1]) == [1, 1]
    @test round(Int, [1.1, 1.1]) == [1, 1]
    @test round(Int, [1 1]) == [1 1]
    @test round(Int, [1.1 1.1]) == [1 1]
    @test round(Int, fill(1.1, 2, 3, 4)) == fill(1, 2, 3, 4)
    @test ceil(Int, [1, 1]) == [1, 1]
    @test ceil(Int, [1.1, 1.1]) == [2, 2]
    @test ceil(Int, [1 1]) == [1 1]
    @test ceil(Int, [1.1 1.1]) == [2 2]
    @test ceil(Int, fill(1.1, 2, 3, 4)) == fill(2, 2, 3, 4)
    @test floor(Int, [1, 1]) == [1, 1]
    @test floor(Int, [1.1, 1.1]) == [1, 1]
    @test floor(Int, [1 1]) == [1 1]
    @test floor(Int, [1.1 1.1]) == [1 1]
    @test floor(Int, fill(1.1, 2, 3, 4)) == fill(1, 2, 3, 4)
    @test trunc(Int, [1, 1]) == [1, 1]
    @test trunc(Int, [1.1, 1.1]) == [1, 1]
    @test trunc(Int, [1 1]) == [1 1]
    @test trunc(Int, [1.1 1.1]) == [1 1]
    @test trunc(Int, fill(1.1, 2, 3, 4)) == fill(1, 2, 3, 4)
end

# n % Type
for T in Any[Int16, Int32, UInt32, Int64, UInt64]
    if !(T <: Unsigned)
        @test convert(T, -200) %  Int8 === @compat Int8(56)
        @test convert(T, -200) % UInt8 === 0x38
        @test convert(T, -300) %  Int8 === @compat Int8(-44)
        @test convert(T, -300) % UInt8 === 0xd4
        @test convert(T, -128) %  Int8 === @compat Int8(-128)
        @test convert(T, -128) % UInt8 === 0x80
    end
    @test convert(T,  127) %  Int8 === @compat Int8(127)
    @test convert(T,  127) % UInt8 === 0x7f
    @test convert(T,  128) %  Int8 === @compat Int8(-128)
    @test convert(T,  128) % UInt8 === 0x80
    @test convert(T,  200) %  Int8 === @compat Int8(-56)
    @test convert(T,  300) % UInt8 === 0x2c
end

@test IPv4("1.2.3.4") == ip"1.2.3.4"
@test IPv6("2001:1:2:3::1") == ip"2001:1:2:3::1"
@test isless(ip"1.2.3.4", ip"1.2.3.5")

@test startswith("abcdef","abc") == true
@test startswith("abcdef","def") == false

@test size(bitrand(3, 4)) == (3, 4)
@test size(bitrand((3, 4))) == (3, 4)
@test size(bitrand(MersenneTwister(0), 3, 4)) == (3, 4)
@test size(bitrand(MersenneTwister(0), (3, 4))) == (3, 4)
@test rand(Bool) in [false, true]

rng = MersenneTwister(0)
srand()
srand(rng, UInt32[0,0])
srand(rng)
for Tr in (Int8,UInt8,Int32,UInt32,Int64,UInt64,Int128,UInt128,Float16,Float32,Float64)
    for T in (Tr, Complex{Tr})
        @test isa(rand(rng, T), T)
        let x = rand(rng, T, 3,4)
            @test isa(x, Array{T,2})
            @test size(x) == (3,4)
            rand!(rng, x)
        end
    end
end
srand(rng, 0)
let x = rand(rng, Int64, 3,4)
    srand(rng, 0)
    @test x == rand(rng, Int64, (3,4))
end

extrapath = is_windows() ? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : ""
@compat withenv("PATH" => extrapath * ENV["PATH"]) do
    cmd1 = pipeline(`echo hello`, `sort`)
    cmd2 = pipeline(`true`, `true`)
    if is_windows()
        try # use busybox-w32
            success(`busybox`)
            cmd1 = pipeline(`busybox echo hello`, `busybox sort`)
            cmd2 = pipeline(`busybox true`, `busybox true`)
        end
    end
    @test readstring(cmd1) == "hello\n"
    @test success(cmd2)
end

let convert_funcs_and_types =
    ((:integer, :Integer), (:signed, :Signed), (:unsigned, :Unsigned),
     (:int, :Int), (:int8, :Int8), (:int16, :Int16), (:int32, :Int32),
     (:int64, :Int64), (:int128, :Int128), (:uint, :UInt),
     (:uint8, :UInt8), (:uint16, :UInt16), (:uint32, :UInt32),
     (:uint64, :UInt64), (:uint128, :UInt128),
     (:float16, :Float16), (:float32, :Float32), (:float64, :Float64),
     (:complex32,:Complex32), (:complex64,:Complex64),(:complex128,:Complex128),
     (:char,:Char))

    for (df,t) in convert_funcs_and_types
        x = @compat UInt8(10)
        r1 = eval(:(@compat($t($x))))
        ty = eval(t)
        if ty.abstract
            @test issubtype(typeof(r1),ty)
        else
            @test typeof(r1) === ty
        end
        if VERSION <  v"0.4.0-dev+3732"
            r2 = eval(df)(x)
            @test r1 === r2
            if t === :Signed || t === :Complex32
                continue
            end
            x = fill(x, 10)
            r1 = eval(:(@compat map($t, $x)))
            r2 = eval(df)(x)
            @test r1 == r2
            @test typeof(r1) === typeof(r2)
        end
    end
    @test (@compat Bool(1))
    @test !(@compat Bool(0))

    # issue #54
    c = @compat Complex128(1)
    @test c.re == 1
    @test c.im == 0

    c = @compat Complex128(1,2)
    @test c.re == 1
    @test c.im == 2

    c = @compat Complex128(1+2im)
    @test c.re == 1
    @test c.im == 2
end

type Test3609
    a
    b
end

if VERSION < v"0.4.0-dev+3609"
    let v = Test3609(1,2)
        @test fieldnames(Test3609) == fieldnames(v) == Symbol[:a, :b]
    end
end

@test fieldoffset(Complex{Float32}, 2) === @compat UInt(4)

@test parse(Int8, '9') == convert(Int8, 9)
@test parse(Int, 'a', 16) == 10
@test parse(Int, "200") == 200
@test parse(Int16, "1101", 2) == convert(Int16, 13)
@test parse(Float64, "222") == 222.0
@test parse(Float32, "1.1") == convert(Float32, 1.1)
@test parse(BigFloat, "1.125") == convert(BigFloat, 1.125)
@test isa(tryparse(Float32, "1.1"), Nullable)
@test get(tryparse(Float32, "1.1")) == 1.1f0
@test isa(tryparse(Float32, "a"), Nullable{Float32})
@test isa(tryparse(Float64, "1.1"), Nullable)
@test get(tryparse(Float64, "1.1")) == 1.1
@test isa(tryparse(Float64, "a"), Nullable{Float64})
@test get(tryparse(Int32, "1")) == 1
@test isa(tryparse(Int32, "a"), Nullable{Int32})
@test get(tryparse(Int64, "1")) == 1
@test isa(tryparse(Int64, "a"), Nullable{Int64})

@test_throws ArgumentError tryparse(Int32, "0", 1)
@test tryparse(Int32, "12345", 16) === Nullable{Int32}(@compat Int32(74565))
@test tryparse(Int64, "12345", 10) === Nullable{Int64}(@compat Int64(12345))
@test tryparse(Int64, "12345", 6) === Nullable{Int64}(@compat Int64(1865))
@test isnull(tryparse(Int64, "nonsense", 10))
@test tryparse(Int64, "nonsense", 36) === Nullable{Int64}(@compat Int64(1856056985582))

# Make sure exports from Libc and Libdl are defined
for x in [:strftime,:systemsleep,:getpid,:FILE,:malloc,:flush_cstdio,:realloc,:strptime,:Libc,:errno,:TmStruct,:calloc,:time,:strerror,:gethostname,:free]
    getfield(Libc, x)
end
for x in [:RTLD_LOCAL,:RTLD_GLOBAL,:find_library,:dlsym,:RTLD_LAZY,:RTLD_NODELETE,:DL_LOAD_PATH,:RTLD_NOW,:Libdl,:dlext,:dlsym_e,:RTLD_FIRST,:dlopen,:dllist,:dlpath,:RTLD_NOLOAD,:dlclose,:dlopen_e,:RTLD_DEEPBIND]
    getfield(Libdl, x)
end

# Test unsafe_convert
type Au_c; end
x = "abc"
@test @compat String(unsafe_string(Compat.unsafe_convert(Ptr{UInt8}, x))) == x
Compat.unsafe_convert(::Ptr{Au_c}, x) = x
@test Compat.unsafe_convert(pointer([Au_c()]), 1) == 1

# Test Ptr{T}(0)
@test @compat(Ptr{Int}(0)) == C_NULL

# Test Tuple{} syntax
if VERSION < v"0.4.0-dev+4319"
    @test @compat Tuple{1} == (1,)
    @test @compat Tuple{:a, :b} == (:a, :b)
    @test @compat Tuple{:a, Tuple{:b}} == (:a, (:b,))
    @test @compat Tuple{:a, Tuple{:b, :c}} == (:a, (:b, :c))
    @test @compat Tuple{Int} == (Int,)
    @test @compat Tuple{Int, Float64} == (Int, Float64)
    @test @compat Tuple{Int, Tuple{Float64}} == (Int, (Float64,))
    @test @compat Tuple{Int, Tuple{Float64, Char}} == (Int, (Float64, Char))
    @test @compat Tuple{Int, Vararg{Float64}} == (Int, Float64...)
    # Issue 81
    a81 = [Int, Int]
    b81 = (Int, Int)
    @test @compat Tuple{a81..., Vararg{Float64}} == (Int, Int, Float64...)
    @test @compat Tuple{b81..., Vararg{Float64}} == (Int, Int, Float64...)
end

# Ensure eachindex iterates over the whole array
let A, B, s
    A = reshape(1:20,4,5)
    s = 0
    for i in eachindex(A)
        s += A[i]
    end
    @test s == 210
    B = sparse(A)
    s = 0
    for i in eachindex(B)
        s += B[i]
    end
    @test s == 210
end

let
    d = @compat Dict(1=>2, 3=>4)
    d[5] = 6
    val = 0
    for I in eachindex(d)
        val += d[I]
    end
    @test val == 12
    empty!(d)
    for I in eachindex(d)
        val += d[I]
    end
    @test val == 12
end

# findlast, findprev
let a = [0,1,2,3,0,1,2,3]
    @test findlast(a) == 8
    @test findlast(a.==0) == 5
    @test findlast(a.==5) == 0
    @test findlast([1,2,4,1,2,3,4], 3) == 6
    @test findlast(isodd, [2,4,6,3,9,2,0]) == 5
    @test findlast(isodd, [2,4,6,2,0]) == 0
    @test findprev(a,4) == 4
    @test findprev(a,5) == 4
    @test findprev(a,1) == 0
    @test findprev(a,1,4) == 2
    @test findprev(a,1,8) == 6
    @test findprev(isodd, [2,4,5,3,9,2,0], 7) == 5
    @test findprev(isodd, [2,4,5,3,9,2,0], 2) == 0
end

# isdiag
@test isdiag(diagm([1,2,3,4]))
@test !isdiag([1 2; 3 4])
@test isdiag(5)

# keytype & valtype
if VERSION < v"0.4.0-dev+4502"
    @test keytype(@compat(Dict(1 => 1.))) == Int
    @test valtype(@compat(Dict(1 => 1.))) == Float64
end

# Val
begin
    local firstlast
    firstlast(::Type{Val{true}}) = "First"
    firstlast(::Type{Val{false}}) = "Last"

    @test firstlast(Val{true}) == "First"
    @test firstlast(Val{false}) == "Last"
end

# qr, qrfact, qrfact!
let A = [1.0 2.0; 3.0 4.0]
    Q, R = qr(A, Val{false})
    @test Q*R ≈ A
    Q, R, p = qr(A, Val{true})
    @test Q*R ≈ A[:,p]
    F = qrfact(A, Val{false})
    @test F[:Q]*F[:R] ≈ A
    F = qrfact(A, Val{true})
    @test F[:Q]*F[:R] ≈ A[:,F[:p]]
    A_copy = copy(A)
    F = qrfact!(A_copy, Val{false})
    @test F[:Q]*F[:R] ≈ A
    A_copy = copy(A)
    F = qrfact!(A_copy, Val{true})
    @test F[:Q]*F[:R] ≈ A[:,F[:p]]
end

# Cstring
let s = "foo"
    # note: need cconvert in 0.5 because of JuliaLang/julia#16893
    @test reinterpret(Ptr{Cchar}, Compat.unsafe_convert(Cstring, VERSION < v"0.4" ? s : Base.cconvert(Cstring, s))) == pointer(s)
    if VERSION < v"0.5.0-dev+4859"
        let w = wstring("foo")
            @test reinterpret(Ptr{Cwchar_t}, Compat.unsafe_convert(Cwstring, w)) == pointer(w)
        end
    end
end

# fma and muladd
@test fma(3,4,5) == 3*4+5 == muladd(3,4,5)

if VERSION < v"0.5.0-dev+5271"
    # is_valid_utf32
    s = utf32("abc")
    @test isvalid(s)
    s = utf32(UInt32[65,0x110000])
    @test !isvalid(s)

    # isvalid
    let s = "abcdef", u8 = "abcdef\uff", u16 = utf16(u8), u32 = utf32(u8),
        bad32 = utf32(UInt32[65,0x110000]), badch = Char[0x110000][1]

        @test !isvalid(bad32)
        @test !isvalid(badch)
        @test isvalid(s)
        @test isvalid(u8)
        @test isvalid(u16)
        @test isvalid(u32)
        @test isvalid(Compat.ASCIIString, s)
        @test isvalid(Compat.UTF8String,  u8)
        @test isvalid(UTF16String, u16)
        @test isvalid(UTF32String, u32)
    end
end

if VERSION < v"0.5.0-dev+907"
    # chol
    let A = rand(2,2)
        B = A'*A
        U = @compat chol(B, Val{:U})
        @test U'*U ≈ B
    end
end

# @generated
if VERSION > v"0.3.99"
    let
        @compat @generated function foo(x)
            T = x
            :(return $T)
        end
        @test foo(5) == Int
    end
end

# Timer
let c = 0, f, g, t
    @compat f(t::Timer) = (c += 1)
    @compat g(t::Base.Timer) = (c += 1)
    t = Timer(f, 0.0, 0.05)
    sleep(0.05)
    @test c >= 1
    sleep(0.1)
    @test c >= 3
    close(t)
    sleep(0.1)
    val = c
    sleep(0.1)
    @test val == c
    t = Timer(g, 0.0, 0.05)
    sleep(0.05)
    @test c >= 2
    close(t)
end

# MathConst -> Irrational
f(::Irrational) = true
@test f(π)
Compat.@irrational mathconst_one 1.0 big(1.)
@test f(mathconst_one)

# gc_enable(::Bool)
@test gc_enable(false)
@test !gc_enable(true)

# Vector{Int}(), Array{Int}

@test @compat typeof(Vector{Int}()) == Array{Int,1}
@test @compat length(Vector{Int}()) == 0

@test @compat typeof(Vector{Int8}(10)) == Array{Int8,1}
@test @compat length(Vector{Int8}(10)) == 10

@test @compat typeof(Array{UInt16}()) == Array{UInt16,0}
@test @compat length(Array{UInt16}()) == 1

@test @compat typeof(Array{UInt16}(0)) == Array{UInt16,1}
@test @compat length(Array{UInt16}(0)) == 0

@test @compat typeof(Array{Float16}(5)) == Array{Float16,1}
@test @compat length(Array{Float16}(5)) == 5

@test @compat typeof(Array{AbstractString}(2,2)) == Array{AbstractString,2}
@test @compat size(Array{AbstractString}(2,2)) == (2,2)

@test @compat typeof(Array{Rational{Int}}(2,2,2,2,2)) == Array{Rational{Int},5}
@test @compat size(Array{Rational{Int}}(2,2,2,2,2)) == (2,2,2,2,2)

@compat String(Mmap.mmap(@__FILE__(),Vector{UInt8},11,1)) == "sing Compat"

@test base64encode("hello world") == "aGVsbG8gd29ybGQ="

@test nothing === __precompile__(false) # tests should never be precompiled
@test nothing === __precompile__()
@test nothing === include_dependency("foo")

@test real(Int) == real(Complex{Int}) == Int

@test isa(1.2, AbstractFloat)

@test [1,2,3] ≈ [1,2,3+1e-9]
@test [0,1] ≈ [1e-9, 1]
@test [0,1] ≉ [1e-3, 1]

# linspace (some of the julia 0.4 tests)
@test [Compat.linspace(0.1,0.3,3);]     == [1:3;]./10
@test [Compat.linspace(0.0,0.3,4);]     == [0:3;]./10
@test [Compat.linspace(0.3,-0.1,5);]    == [3:-1:-1;]./10
@test [Compat.linspace(0.1,-0.3,5);]    == [1:-1:-3;]./10
@test [Compat.linspace(0.0,1.0,11);]    == [0:10;]./10
@test [Compat.linspace(0.0,1.0,0);]     == []
@test [Compat.linspace(0.0,-1.0,0);]    == []
@test [Compat.linspace(0.0,-1.0,11);]   == [0:-1:-10;]./10
@test [Compat.linspace(1.0,27.0,1275);] == [49:1323;]./49
@test [Compat.linspace(0.0,2.1,4);]     == [0:7:21;]./10
@test [Compat.linspace(0.0,3.3,4);]     == [0:11:33;]./10
@test [Compat.linspace(0.1,3.4,4);]     == [1:11:34;]./10
@test [Compat.linspace(0.0,3.9,4);]     == [0:13:39;]./10
@test [Compat.linspace(0.1,4.0,4);]     == [1:13:40;]./10
@test [Compat.linspace(1.1,3.3,3);]     == [11:11:33;]./10
@test [Compat.linspace(0.3,1.1,9);]     == [3:1:11;]./10
@test [Compat.linspace(0.0,0.0,1);]     == [0.0]
@test [Compat.linspace(0.0,0.0,1);]     == [0.0]

for T = (Float32, Float64)
    z = zero(T)
    u = eps(z)
    @test first(Compat.linspace(u,u,0)) == u
    @test last(Compat.linspace(u,u,0)) == u
    @test first(Compat.linspace(-u,u,0)) == -u
    @test last(Compat.linspace(-u,u,0)) == u
    @test [Compat.linspace(-u,u,0);] == []
    @test [Compat.linspace(-u,-u,1);] == [-u]
    @test [Compat.linspace(-u,u,2);] == [-u,u]
    @test [Compat.linspace(-u,u,3);] == [-u,0,u]
    @test first(Compat.linspace(-u,-u,0)) == -u
    @test last(Compat.linspace(-u,-u,0)) == -u
    @test first(Compat.linspace(u,-u,0)) == u
    @test last(Compat.linspace(u,-u,0)) == -u
    @test [Compat.linspace(u,-u,0);] == []
    @test [Compat.linspace(u,u,1);] == [u]
    @test [Compat.linspace(u,-u,2);] == [u,-u]
    @test [Compat.linspace(u,-u,3);] == [u,0,-u]
    v = [Compat.linspace(-u,u,12);]
    @test length(v) == 12
    @test [-3u:u:3u;] == [Compat.linspace(-3u,3u,7);] == [-3:3;].*u
    @test [3u:-u:-3u;] == [Compat.linspace(3u,-3u,7);] == [3:-1:-3;].*u
end

if VERSION < v"0.4.0-dev+768"
    @test @compat(Void) === Nothing
else
    @test @compat(Void) === Void
end
@test Ptr{Void} == @compat(Ptr{Void})

# MemoryError -> OutOfMemoryError
# Base64Pipe -> Base64EncodePipe
# UdpSocket -> UDPSocket
f141(::Type{OutOfMemoryError}) = true
f141(::Type{Base64EncodePipe}) = true
f141(::Type{UDPSocket}) = true
f141(::Type{TCPSocket}) = true

@test f141(OutOfMemoryError)
@test f141(Base64EncodePipe)
@test f141(UDPSocket)
@test f141(TCPSocket)

# Union syntax
if VERSION < v"0.4.0-dev+5379"
    @test @compat(Union{}) == None
    @test @compat(Union{Int,Float64}) == Union(Int,Float64)
    @test @compat(:(Union{})) == :(Union())
end

@test fetch(remotecall(() -> true, 1))
@test remotecall_fetch(() -> true, 1)
@test fetch(remotecall_wait(() -> true, 1))
Base.remote_do(() -> true, 1) # Doesn't return anything so cannot be `@test`ed but should print some output if it fails

# JuliaLang/julia#13440
@test isa(SparseArrays, Module)

# JuliaLang/julia#12819
@test Compat.Filesystem.JL_O_RDWR == Compat.Filesystem.JL_O_RDWR

# JuliaLang/julia#14338
@test supertype(Int) == Signed

# withenv
@test "1234" == @compat withenv(() -> ENV["_TESTVAR"], "_TESTVAR" => 1234)
@test "1234" == @compat withenv("_TESTVAR" => 1234) do
    return ENV["_TESTVAR"]
end

# Test functional form of mktemp and mktempdir
let
    tmp_path = mktemp() do p, io
        @test isfile(p)
        print(io, "鴨かも？")
        p
    end
    @test tmp_path != ""
    @test !isfile(tmp_path)
end

let
    tmpdir = mktempdir() do d
        @test isdir(d)
        d
    end
    @test tmpdir != ""
    @test !isdir(tmpdir)
end

# https://github.com/JuliaLang/julia/pull/14660
mktempdir() do dir

    verbose = false

    # Create test file...
    filename = joinpath(dir, "file.txt")
    text = "C1,C2\n1,2\na,b\n"

    # List of IO producers...
    l = [
        ("IOStream", (text) -> begin
            write(filename, text)
            open(filename)
        end),
        ("IOBuffer", (text)->IOBuffer(text))
    ]

    open_streams = Any[]
    function cleanup()
        for s in open_streams
            try close(s) end
        end
    end

    for (name, f) in l

        io = ()->(s=f(text); push!(open_streams, s); s)

        write(filename, text)

        verbose && println("$name read...")
        @test read(io(), UInt8) == read(IOBuffer(text), UInt8)
        @test read(io(), UInt8) == read(filename, UInt8)
        @test read(io(), Int) == read(IOBuffer(text), Int)
        @test read(io(), Int) == read(filename,Int)
        s1 = io()
        s2 = IOBuffer(text)
        @test read(s1, UInt32, 2) == read(s2, UInt32, 2)
        @test !eof(s1)
        @test read(s1, UInt8, 5) == read(s2, UInt8, 5)
        @test !eof(s1)
        @test read(s1, UInt8, 1) == read(s2, UInt8, 1)
        @test eof(s1)
        @test_throws EOFError read(s1, UInt8)
        @test eof(s1)
        close(s1)
        close(s2)

        verbose && println("$name eof...")
        n = length(text) - 1
        @test @compat read!(io(), Vector{UInt8}(n)) ==
              read!(IOBuffer(text), Vector{UInt8}(n))
        @test @compat (s = io(); read!(s, Vector{UInt8}(n)); !eof(s))
        n = length(text)
        @test @compat read!(io(), Vector{UInt8}(n)) ==
              read!(IOBuffer(text), Vector{UInt8}(n))
        @test @compat (s = io(); read!(s, Vector{UInt8}(n)); eof(s))
        n = length(text) + 1
        @test_throws EOFError @compat read!(io(), Vector{UInt8}(n))
        @test_throws EOFError @compat read!(io(), Vector{UInt8}(n))

        old_text = text
        cleanup()
        const SZ_UNBUFFERED_IO = 65536

        for text in [
            old_text,
            convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:(div(SZ_UNBUFFERED_IO,2))]),
            convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:(    SZ_UNBUFFERED_IO -1)]),
            convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:(    SZ_UNBUFFERED_IO   )]),
            convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:(    SZ_UNBUFFERED_IO +1)])
        ]

            write(filename, text)

            verbose && println("$name readstring...")
            @test readstring(io()) == text

            @test readstring(io()) == readstring(filename)

            verbose && println("$name read...")
            @test @compat read(io()) == UInt8[convert(UInt8, x) for x in text]

            @test read(io()) == read(filename)

            cleanup()

            verbose && println("$name readbytes!...")
            l = length(text)
            for n = [1, 2, l-2, l-1, l, l+1, l+2]
                @compat a1 = Vector{UInt8}(n);
                @compat a2 = Vector{UInt8}(n)
                s1 = io()
                s2 = IOBuffer(text)
                n1 = readbytes!(s1, a1)
                n2 = readbytes!(s2, a2)
                @test n1 == n2
                @test length(a1) == length(a2)
                @test a1[1:n1] == a2[1:n2]
                @test n <= length(text) || eof(s1)
                @test n <= length(text) || eof(s2)

                cleanup()
            end

            verbose && println("$name read!...")
            l = length(text)
            for n = [1, 2, l-2, l-1, l]
                @test @compat  read!(io(), Vector{UInt8}(n)) ==
                      read!(IOBuffer(text), Vector{UInt8}(n))
                @test @compat read!(io(), Vector{UInt8}(n)) ==
                      read!(filename, Vector{UInt8}(n))

                cleanup()
            end
            @test_throws EOFError @compat read!(io(), Vector{UInt8}(length(text)+1))

            verbose && println("$name readuntil...")
            @test readuntil(io(), '\n') == readuntil(IOBuffer(text),'\n')
            @test readuntil(io(), '\n') == readuntil(filename,'\n')
            @test readuntil(io(), "\n") == readuntil(IOBuffer(text),"\n")
            @test readuntil(io(), "\n") == readuntil(filename,"\n")
            @test readuntil(io(), ',')  == readuntil(IOBuffer(text),',')
            @test readuntil(io(), ',')  == readuntil(filename,',')

            cleanup()

            verbose && println("$name readline...")
            @test readline(io()) == readline(IOBuffer(text))
            @test readline(io()) == readline(filename)

            verbose && println("$name readlines...")
            @test readlines(io()) == readlines(IOBuffer(text))
            @test readlines(io()) == readlines(filename)
            @test collect(eachline(io())) == collect(eachline(IOBuffer(text)))
            @test collect(eachline(io())) == collect(eachline(filename))

            cleanup()

            verbose && println("$name countlines...")
            @test countlines(io()) == countlines(IOBuffer(text))

            # verbose && println("$name readcsv...")
            # @test readcsv(io()) == readcsv(IOBuffer(text))
            # @test readcsv(io()) == readcsv(filename)

            cleanup()
        end

        text = old_text
        write(filename, text)

        verbose && println("$name position...")
        @test @compat (s = io(); read!(s, Vector{UInt8}(4)); position(s))  == 4

        verbose && println("$name seek...")
        for n = 0:length(text)-1
            @test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n))
            cleanup()
        end
        verbose && println("$name skip...")
        for n = 0:length(text)-1
            @test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n))
            @test readlines(skip(io(), n)) == readlines(skip(IOBuffer(text), n))
            cleanup()
        end
        verbose && println("$name seekend...")
        @test readstring(seekend(io())) == ""

        verbose && println("$name write(::IOStream, ...)")
        to = open("$filename.to", "w")
        write(to, io())
        close(to)
        @test readstring("$filename.to") == text

        verbose && println("$name write(filename, ...)")
        write("$filename.to", io())
        @test readstring("$filename.to") == text

        verbose && println("$name write(::IOBuffer, ...)")
        @compat to = IOBuffer(UInt8[convert(UInt8, x) for x in text], false, true)
        write(to, io())
        @test String(take!(to)) == text

        cleanup()
    end

# https://github.com/JuliaLang/julia/pull/13232

setprecision(BigFloat, 100)
@test precision(BigFloat) == 100
setprecision(256)
@test precision(BigFloat) == 256

setprecision(BigFloat, 100) do
    a = big(pi)
    @test precision(a) == 100
end

setprecision(130) do
    a = big(pi)
    @test precision(a) == 130
end

for T in (BigFloat, Float64)
    setrounding(T, RoundDown)
    @test rounding(T) == RoundDown
    setrounding(T, RoundNearest)

    setrounding(T, RoundUp) do
        @test rounding(T) == RoundUp
    end
end

end

@test typeof(displaysize()) == @compat(Tuple{Int, Int})

@test Compat.LinAlg.checksquare(randn(4,4)) == 4
@test Compat.LinAlg.checksquare(randn(4,4), randn(3,3)) == [4,3]
@test_throws DimensionMismatch Compat.LinAlg.checksquare(randn(4,3))

@test issymmetric([1 2 3; 2 2 3; 3 3 2])
@test !issymmetric([1 3 3; 2 2 3; 3 3 2])

let X = randn(10,2), Y = randn(10,2), x = randn(10), y = randn(10)
    for b in (true, false)
        if VERSION < v"0.5.0-dev+679"
            @test cov(x, b) == cov(x, corrected=b)
        end
        for d in (1, 2)
            @test size(cov(X, d), 1) == 8*d - 6
            @test size(cov(X, d, b), 1) == 8*d - 6
            @test size(cov(X, Y, d), 1) == 8*d - 6
            @test size(cov(X, Y, d, b), 1) == 8*d - 6

            @test size(cor(X, d), 1) == 8*d - 6
            @test size(cor(X, Y, d), 1) == 8*d - 6
        end
    end
end

# foreach
let
    a = Any[]
    foreach(()->push!(a,0))
    @test a == [0]
    a = Any[]
    foreach(x->push!(a,x), [1,5,10])
    @test a == [1,5,10]
    a = Any[]
    foreach((args...)->push!(a,args), [2,4,6], [10,20,30])
    @test a == [(2,10),(4,20),(6,30)]
end

@test istextmime("text/html") && !istextmime("image/png")

module CallTest

using Base.Test, Compat

immutable A
    a
end

immutable B{T}
    b::T
end

if VERSION >= v"0.4"
    @compat (::Type{A})() = A(1)
    @compat (::Type{B})() = B{Int}()
    @compat (::Type{B{T}}){T}() = B{T}(zero(T))

    @compat (a::A)() = a.a
    @compat (a::A)(b) = (a.a, b)
    @compat (a::A)(b, c; d=2) = (a.a, b, c, d)
    @compat (b::B{T}){T}() = b.b, T
    @compat (b::B{T}){T}(c::T) = 1
    @compat (b::B{T}){T,T2}(c::T2) = 0
    @compat (b::B{T}){T}(c::T, d; f=1) = (c, d, f)

    @test A() === A(1)
    @test B() === B(0)
    @test B{Float64}() === B(0.0)

    @test A(1)() === 1
    @test A(1)(2) === (1, 2)
    @test A(1)(2, 3; d=10) === (1, 2, 3, 10)
    @test B(0)() === (0, Int)
    @test B(0)(1) === 1
    @test B(0)(1, 2; f=100) === (1, 2, 100)
    @test B(0)(1.0) === 0
end

end

# walkdir

dirwalk = mktempdir()
cd(dirwalk) do
    for i=1:2
        mkdir("sub_dir$i")
        open("file$i", "w") do f end

        mkdir(joinpath("sub_dir1", "subsub_dir$i"))
        touch(joinpath("sub_dir1", "file$i"))
    end
    touch(joinpath("sub_dir2", "file_dir2"))
    has_symlinks = is_unix() ? true : (isdefined(Base, :WINDOWS_VISTA_VER) && Base.windows_version() >= Base.WINDOWS_VISTA_VER)
    follow_symlink_vec = has_symlinks ? [true, false] : [false]
    has_symlinks && symlink(abspath("sub_dir2"), joinpath("sub_dir1", "link"))
    for follow_symlinks in follow_symlink_vec
        chnl = walkdir(".", follow_symlinks=follow_symlinks)
        root, dirs, files = take!(chnl)
        @test root == "."
        @test dirs == ["sub_dir1", "sub_dir2"]
        @test files == ["file1", "file2"]

        root, dirs, files = take!(chnl)
        @test root == joinpath(".", "sub_dir1")
        @test dirs == (has_symlinks ? ["link", "subsub_dir1", "subsub_dir2"] : ["subsub_dir1", "subsub_dir2"])
        @test files == ["file1", "file2"]

        root, dirs, files = take!(chnl)
        if follow_symlinks
            @test root == joinpath(".", "sub_dir1", "link")
            @test dirs == []
            @test files == ["file_dir2"]
            root, dirs, files = take!(chnl)
        end
        for i=1:2
            @test root == joinpath(".", "sub_dir1", "subsub_dir$i")
            @test dirs == []
            @test files == []
            root, dirs, files = take!(chnl)
        end

        @test root == joinpath(".", "sub_dir2")
        @test dirs == []
        @test files == ["file_dir2"]
    end

    for follow_symlinks in follow_symlink_vec
        chnl = walkdir(".", follow_symlinks=follow_symlinks, topdown=false)
        root, dirs, files = take!(chnl)
        if follow_symlinks
            @test root == joinpath(".", "sub_dir1", "link")
            @test dirs == []
            @test files == ["file_dir2"]
            root, dirs, files = take!(chnl)
        end
        for i=1:2
            @test root == joinpath(".", "sub_dir1", "subsub_dir$i")
            @test dirs == []
            @test files == []
            root, dirs, files = take!(chnl)
        end
        @test root == joinpath(".", "sub_dir1")
        @test dirs ==  (has_symlinks ? ["link", "subsub_dir1", "subsub_dir2"] : ["subsub_dir1", "subsub_dir2"])
        @test files == ["file1", "file2"]

        root, dirs, files = take!(chnl)
        @test root == joinpath(".", "sub_dir2")
        @test dirs == []
        @test files == ["file_dir2"]

        root, dirs, files = take!(chnl)
        @test root == "."
        @test dirs == ["sub_dir1", "sub_dir2"]
        @test files == ["file1", "file2"]
    end
    #test of error handling
    chnl_error = walkdir(".")
    chnl_noerror = walkdir(".", onerror=x->x)
    root, dirs, files = take!(chnl_error)
    @test root == "."
    @test dirs == ["sub_dir1", "sub_dir2"]
    @test files == ["file1", "file2"]

    rm(joinpath("sub_dir1"), recursive=true)
    @test_throws SystemError take!(chnl_error) # throws an error because sub_dir1 do not exist

    root, dirs, files = take!(chnl_noerror)
    @test root == "."
    @test dirs == ["sub_dir1", "sub_dir2"]
    @test files == ["file1", "file2"]

    root, dirs, files = take!(chnl_noerror) # skips sub_dir1 as it no longer exist
    @test root == joinpath(".", "sub_dir2")
    @test dirs == []
    @test files == ["file_dir2"]

end
rm(dirwalk, recursive=true)

# RemoteChannel/Future
r = remotecall(sin, 1, pi/3)
@compat foo(r::Future) = 7
@test foo(r) == 7

@compat rc = RemoteChannel()
@compat rc = RemoteChannel(myid())

@compat rc = Future()
@compat rc = Future(myid())

# @functorize
function checkfunc(Fun, func)
    if VERSION >= v"0.5.0-dev+3701"
        @eval @test @functorize($(func)) === Base.$(func)
    else
        if isdefined(Base, Fun)
            @eval @test isa(@functorize($(func)), Base.$(Fun))
        else
            @eval @test isa(@functorize($(func)), Function)
            @eval @test @functorize($(func)) === Base.$(func)
        end
    end
end

for (Fun, func) in [(:IdFun,                   :identity),
                    (:AbsFun,                  :abs),
                    (:Abs2Fun,                 :abs2),
                    (:ExpFun,                  :exp),
                    (:LogFun,                  :log),
                    (:ConjFun,                 :conj)]
    begin
        if isdefined(Base, func)
            checkfunc(Fun, func)
            a = rand(1:10, 10)
            @eval @test mapreduce($(func), +, $(a)) == mapreduce(@functorize($(func)), +, $(a))
        end
    end
end

dotfunctors = [(:DotAddFun,           :.+),
               (:DotSubFun,           :.-),
               (:DotMulFun,           :.*),
               (:DotRDivFun,          :./),
               (:DotIDivFun,          @compat(Symbol(".÷"))),
               (:DotRemFun,           :.%),
               (:DotLSFun,            :.<<),
               (:DotRSFun,            :.>>)]

functors    = [(:AndFun,              :&),
               (:OrFun,               :|),
               (:XorFun,              :⊻),
               (:AddFun,              :+),
               (:SubFun,              :-),
               (:MulFun,              :*),
               (:RDivFun,             :/),
               (:LDivFun,             :\ ),
               (:IDivFun,             :div),
               (:ModFun,              :mod),
               (:RemFun,              :rem),
               (:PowFun,              :^),
               (:MaxFun,              :scalarmax),
               (:MinFun,              :scalarmin),
               (:LessFun,             :<),
               (:MoreFun,             :>),
               (:ElementwiseMaxFun,   :max),
               (:ElementwiseMinFun,   :min)]

# since #17623, dot functions are no longer function objects
if VERSION < v"0.6.0-dev.1614"
    append!(functors, dotfunctors)
end

for (Fun, func) in functors
    begin
        if isdefined(Base, func) && (func !== :.>> || VERSION >= v"0.4.0-dev+553") && (func !== :.% || VERSION >= v"0.5.0-dev+1472")
            checkfunc(Fun, func)
            a = rand(1:10, 10)
            @eval @test mapreduce(identity, Base.$(func), $(a)) == mapreduce(identity, @functorize($(func)), $(a))
        end
    end
end

if VERSION >= v"0.5.0-dev+3701"
    @test @functorize(complex) === complex
    @test @functorize(dot) === dot
else
    if isdefined(Base, :SparseArrays) && isdefined(Base.SparseArrays, :ComplexFun)
        @test isa(@functorize(complex), Base.SparseArrays.ComplexFun)
        @test isa(@functorize(dot), Base.SparseArrays.DotFun)
    else
        @test isa(@functorize(complex), Function)
        @test isa(@functorize(dot), Function)
        @test @functorize(complex) === complex
        @test @functorize(dot) === dot
    end
end
let a = rand(1:10, 10)
    @test mapreduce(identity, dot, a) == mapreduce(identity, @functorize(dot), a)
end

if VERSION < v"0.6.0-dev.2521"
    @test isa(@functorize(centralizedabs2fun)(1), @functorize(centralizedabs2fun))
    @test isa(@functorize(centralizedabs2fun)(1.0), @functorize(centralizedabs2fun))
    let a = rand(1:10, 10)
        @eval @test mapreduce(x -> abs2(x - 1), +, $(a)) == mapreduce(@functorize(centralizedabs2fun)(1), +, $(a))
    end
end

# Threads.@threads
using Compat.Threads
@threads for i=1:10
    @test true
end

# Issue #223
@test 1 == threadid() <= nthreads()

@test @compat(Symbol("foo")) === :foo
@test @compat(Symbol("foo", "bar")) === :foobar
@test @compat(Symbol("a_", 2)) === :a_2
@test @compat(Symbol('c')) === :c
@test @compat(Symbol(1)) === @compat(Symbol("1"))

@test @compat(Base.:+) == +
let x = rand(3), y = rand(3)
    @test @compat(sin.(cos.(x))) == map(x -> sin(cos(x)), x)
    @test @compat(atan2.(sin.(y),x)) == broadcast(atan2,map(sin,y),x)
end
let x0 = Array{Float64}(), v, v0
    x0[1] = rand()
    v0 = @compat sin.(x0)
    @test isa(v0, Array{Float64,0})
    v = @compat sin.(x0[1])
    @test isa(v, Float64)
    @test v == v0[1] == sin(x0[1])
end
let x = rand(2, 2), v
    v = @compat sin.(x)
    @test isa(v, Array{Float64,2})
    @test v == [sin(x[1, 1]) sin(x[1, 2]);
                sin(x[2, 1]) sin(x[2, 2])]
end
let x1 = [1, 2, 3], x2 = ([3, 4, 5],), v
    v = @compat atan2.(x1, x2...)
    @test isa(v, Vector{Float64})
    @test v == [atan2(1, 3), atan2(2, 4), atan2(3, 5)]
end
# Do the following in global scope to make sure inference is able to handle it
@test @compat(sin.([1, 2])) == [sin(1), sin(2)]
@test isa(@compat(sin.([1, 2])), Vector{Float64})
@test @compat(atan2.(1, [2, 3])) == [atan2(1, 2), atan2(1, 3)]
@test isa(@compat(atan2.(1, [2, 3])), Vector{Float64})
@test @compat(atan2.([1, 2], [2, 3])) == [atan2(1, 2), atan2(2, 3)]
@test isa(@compat(atan2.([1, 2], [2, 3])), Vector{Float64})
# And make sure it is actually inferrable
f15032(a) = @compat sin.(a)
@inferred f15032([1, 2, 3])
@inferred f15032([1.0, 2.0, 3.0])

# Issue #291
if VERSION ≥ v"0.5.0-dev+4002"
    @test (1, 2) == @compat abs.((1, -2))
    @test broadcast(+, (1.0, 1.0), (0, -2.0)) == (1.0,-1.0)
end

if VERSION ≥ v"0.4.0-dev+3732"
    @test Symbol("foo") === :foo
    @test Symbol("foo", "bar") === :foobar
    @test Symbol("a_", 2) === :a_2
    @test Symbol('c') === :c
    @test Symbol(1) === Symbol("1")
end

foostring(::String) = 1
@test foostring("hello") == 1
@test foostring("λ") == 1
@test isa("hello", Compat.ASCIIString)
@test isa("λ", Compat.UTF8String)

let async, c = false
    run = Condition()
    async = Compat.AsyncCondition(x->(c = true; notify(run)))
    ccall(:uv_async_send, Void, (Ptr{Void},), async.handle)
    wait(run)
    @test c
end

let async, c = false
    async = Compat.AsyncCondition()
    started = Condition()
    task = @schedule begin
        notify(started)
        wait(async)
        true
    end
    wait(started)
    ccall(:uv_async_send, Void, (Ptr{Void},), async.handle)
    @test wait(task)
end

let io = IOBuffer(), s = "hello"
    unsafe_write(io, pointer(s), length(s))
    @test String(take!(io)) == s
end

@static if VERSION ≥ v"0.4"
    @test VERSION ≥ v"0.4"
else
    @test VERSION < v"0.4"
end

let io = IOBuffer(), s = "hello"
    @test @compat String(Vector{UInt8}(s)) == s
    write(io, s)
    @test @compat String(io) == s
    @test unsafe_string(pointer(s)) == s
    @test unsafe_string(pointer(s),sizeof(s)) == s
    @test string(s, s, s) == "hellohellohello"
    @test @compat(String(s)) == s
    @test String == @compat(Union{Compat.UTF8String,Compat.ASCIIString})
end

@test Compat.repeat(1:2, inner=2) == [1, 1, 2, 2]
@test Compat.repeat(1:2, outer=[2]) == [1, 2, 1, 2]
@test Compat.repeat([1,2], inner=(2,)) == [1, 1, 2, 2]

if VERSION < v"0.5.0-dev+4267"
    if OS_NAME == :Windows
        @test is_windows()
    elseif OS_NAME == :Darwin
        @test is_apple() && is_bsd() && is_unix()
    elseif OS_NAME == :FreeBSD
        @test is_bsd() && is_unix()
    elseif OS_NAME == :Linux
        @test is_linux() && is_unix()
    end
else
    @test Compat.KERNEL == Sys.KERNEL
end

io = IOBuffer()
@test @compat(get(io, :limit, false)) == false
@test @compat(get(io, :compact, false)) == false
@test @compat(get(io, :multiline, false)) == false
@test @compat(get(Nullable(1))) == 1

let
    test_str = "test"
    ptr = pointer(test_str)
    wrapped_str = if VERSION < v"0.6.0-dev.1988"
        unsafe_wrap(Compat.String, ptr)
    else
        unsafe_string(ptr)
    end
    new_str = unsafe_string(ptr)
    cstr = convert(Cstring, ptr)
    new_str2 = unsafe_string(cstr)
    @test wrapped_str == "test"
    @test new_str == "test"
    @test new_str2 == "test"
    if VERSION < v"0.6.0-dev.1988"
        # Test proper pointer aliasing behavior, which is not possible in 0.6
        # with the new String representation
        @test ptr == pointer(wrapped_str)
    end
    @test ptr ≠ pointer(new_str)
    @test ptr ≠ pointer(new_str2)
    @test unsafe_string(convert(Ptr{Int8}, ptr)) == "test"
    if VERSION < v"0.6.0-dev.1988"
        @test unsafe_wrap(Compat.String, convert(Ptr{Int8}, ptr)) == "test"
    end
    x = [1, 2]
    @test unsafe_wrap(Array, pointer(x), 2) == [1, 2]
end

@test allunique([1, 2, 3])
@test !allunique([1, 2, 1])
@test allunique(1:3)
if VERSION < v"0.6.0-dev.2390"
    @test allunique(FloatRange(0.0, 0.0, 0.0, 1.0))
    @test !allunique(FloatRange(0.0, 0.0, 2.0, 1.0))
end

# Add test for Base.view
let a = rand(10,10)
    @test view(a, :, 1) == a[:,1]
end

# 0.5 style single argument `@boundscheck`
@inline function do_boundscheck()
    # A bit ugly since `@boundscheck` returns `nothing`.
    checked = false
    @compat @boundscheck (checked = true;)
    checked
end
@test do_boundscheck() == true

if VERSION < v"0.6.0-dev.1886"
    # `promote_eltype_op` is deprecated
    @test Compat.promote_eltype_op(@functorize(+), ones(2,2), 1) === Float64
    @test Compat.promote_eltype_op(@functorize(*), ones(Int, 2), zeros(Int16,2)) === Int
end

#Add test for Base.normalize and Base.normalize!
let
    vr = [3.0, 4.0]
    for Tr in (Float32, Float64)
        for T in (Tr, Complex{Tr})
            v = convert(Vector{T}, vr)
            @test norm(v) == 5.0
            w = normalize(v)
            @test norm(w - [0.6, 0.8], Inf) < eps(Tr)
            @test isapprox(norm(w), 1.0)
            @test norm(normalize!(copy(v)) - w, Inf) < eps(Tr)
            @test isempty(normalize!(T[]))
        end
    end
end

#Test potential overflow in normalize!
let
    δ = inv(prevfloat(typemax(Float64)))
    v = [δ, -δ]
    if VERSION > v"0.4.0-pre+7164"
        @test norm(v) === 7.866824069956793e-309
    end
    w = normalize(v)
    if VERSION > v"0.4.0-pre+7164"
        @test w ≈ [1/√2, -1/√2]
        @test isapprox(norm(w), 1.0)
    end
    @test norm(normalize!(v) - w, Inf) < eps()
end

# JuliaLang/julia#16603
@test sprint(join, [1, 2, 3]) == "123"
@test sprint(join, [1, 2, 3], ',') == "1,2,3"
@test sprint(join, [1, 2, 3], ", ", ", and ") == "1, 2, and 3"
@test sprint(escape_string, "xyz\n", "z") == "xy\\z\\n"
@test sprint(unescape_string, "xyz\\n") == "xyz\n"

# three-argument show from JuliaLang/julia#16563
@test sprint(show, "text/plain", 1) == stringmime("text/plain", 1)

let n=5, a=rand(n), incx=1, b=rand(n), incy=1
    ccall((Compat.@blasfunc(dcopy_), Base.LinAlg.BLAS.libblas), Void,
          (Ptr{Base.LinAlg.BLAS.BlasInt}, Ptr{Float64}, Ptr{Base.LinAlg.BLAS.BlasInt}, Ptr{Float64}, Ptr{Base.LinAlg.BLAS.BlasInt}),
          &n, a, &incx, b, &incy)
    @test a == b
end

# do-block redirect_std*
let filename = tempname()
    ret = open(filename, "w") do f
        redirect_stdout(f) do
            println("hello")
            [1,3]
        end
    end
    @test ret == [1,3]
    @test chomp(readstring(filename)) == "hello"
    ret = open(filename, "w") do f
        redirect_stderr(f) do
            println(STDERR, "WARNING: hello")
            [2]
        end
    end
    @test ret == [2]
    @test contains(readstring(filename), "WARNING: hello")
    ret = open(filename) do f
        redirect_stdin(f) do
            readline()
        end
    end
    @test contains(ret, "WARNING: hello")
    rm(filename)
end

@test @__DIR__() == dirname(@__FILE__)

# PR #17302
# To be removed when 0.5/0.6 support is dropped.
f17302(a::Number) = a
f17302(a::Number, b::Number) = a + b
Compat.@dep_vectorize_1arg Real f17302
Compat.@dep_vectorize_2arg Real f17302
@test_throws MethodError f17302([1im])
@test_throws MethodError f17302([1im], [1im])
mktemp() do fname, f
    redirect_stderr(f) do
        @test f17302([1.0]) == [1.0]
        @test f17302(1.0, [1]) == [2.0]
        @test f17302([1.0], 1) == [2.0]
        @test f17302([1.0], [1]) == [2.0]
    end
end

# 0.5.0-dev+4677
for A in (Hermitian(randn(5,5) + 10I),
          Symmetric(randn(5,5) + 10I),
          Symmetric(randn(5,5) + 10I, :L))
    F = cholfact(A)
    @test F[:U]'F[:U]  ≈ A
    @test F[:L]*F[:L]' ≈ A

    Ac = copy(A)
    F = cholfact!(Ac)
    @test F[:U]'F[:U]  ≈ A
    @test F[:L]*F[:L]' ≈ A

    @test istriu(chol(A))
    @test chol(A) ≈ F[:U]

    F = cholfact(A, Val{true})
    @test F[:U]'F[:U]  ≈ A[F[:p], F[:p]]
    @test F[:L]*F[:L]' ≈ A[F[:p], F[:p]]
    Ac = copy(A)
    F = cholfact!(Ac, Val{true})
    @test F[:U]'F[:U]  ≈ A[F[:p], F[:p]]
    @test F[:L]*F[:L]' ≈ A[F[:p], F[:p]]
end

types = [
    Bool,
    Float16,
    Float32,
    Float64,
    Int128,
    Int16,
    Int32,
    Int64,
    Int8,
    UInt16,
    UInt32,
    UInt64,
    UInt8,
]
for T in types
    # julia#18510, Nullable constructors
    x = @compat Nullable(one(T), true)
    @test isnull(x) === false
    @test isa(x.value, T)
    @test eltype(x) === T

    x = @compat Nullable{T}(one(T), true)
    y = @compat Nullable{Any}(one(T), true)
    @test isnull(x) === false
    @test isnull(y) === false
    @test isa(x.value, T)
    @test eltype(x) === T
    @test eltype(y) === Any

    x = @compat Nullable{T}(one(T), false)
    y = @compat Nullable{Any}(one(T), false)
    @test isnull(x) === true
    @test isnull(y) === true
    @test eltype(x) === T
    @test eltype(y) === Any

    x = @compat Nullable(one(T), false)
    @test isnull(x) === true
    @test eltype(x) === T

    x = @compat Nullable{T}()
    @test isnull(x) === true
    @test eltype(x) === T

    # julia#18484, generic isnull, unsafe_get
    a = one(T)
    x = @compat Nullable(a, true)
    @test isequal(unsafe_get(x), a)

    x = @compat Nullable{Array{T}}()
    @test_throws UndefRefError unsafe_get(x)
end

@test xor(1,5) == 4
@test 1 ⊻ 5 == 4

# julia#20414
@compat let T = Array{<:Real}, f(x::AbstractVector{<:Real}) = 1
    @test isa([3,4],T)
    @test !isa([3,4im],T)
    @test f(1:3) == f([1,2]) == 1
end
@compat let T = Array{>:Integer}, f(x::AbstractVector{>:Integer}) = 1
    @test isa(Integer[1,2],T)
    @test !isa([3,4],T)
    @test !isa([3.0,4.0],T)
    @test f(Integer[1,2]) == f([1,'a',:sym]) == 1
end

# supertype operator
@test !(Int >: Integer)
@test Integer >: Int

# julia#19246
@test numerator(1//2) === 1
@test denominator(1//2) === 2

# julia#19088
let io = IOBuffer()
    write(io, "aaa")
    @test take!(io) == UInt8['a', 'a', 'a']
    write(io, "bbb")
    @test String(take!(io)) == "bbb"
end

# julia#17510
let x = [1,2,3]
    @compat x .= [3,4,5]
    @test x == [3,4,5]
    @compat x .= x .== 4
    @test x == [0,1,0]
    @compat x .= 7
    @test x == [7,7,7]
end

let s = "Koala test: 🐨"
    @test transcode(UInt16, s) == UInt16[75,111,97,108,97,32,116,101,115,116,58,32,55357,56360]
    @test transcode(UInt32, s) == UInt32[75,111,97,108,97,32,116,101,115,116,58,32,128040]
    for T in (UInt8,UInt16,UInt32,Cwchar_t)
        @test transcode(Compat.String, transcode(T, s)) == s
        @test transcode(UInt8, transcode(T, s)) == Vector{UInt8}(s)
        @test transcode(T, s) == transcode(T, Vector{UInt8}(s)) == transcode(T, transcode(T, s))
    end
end

# julia#17155, tests from Base Julia
@test (uppercase∘hex)(239487) == "3A77F"
let str = randstring(20)
    @test filter(!isupper, str) == replace(str, r"[A-Z]", "")
    @test filter(!islower, str) == replace(str, r"[a-z]", "")
end

# julia#19950, tests from Base (#20028)
for T in (Float16, Float32, Float64, BigFloat, Int8, Int16, Int32, Int64, Int128,
          BigInt, UInt8, UInt16, UInt32, UInt64, UInt128)
    @test iszero(T(0))
    @test iszero(Complex{T}(0))
    if T<:Integer
        @test iszero(Rational{T}(0))
    end
    if T<:AbstractFloat
        @test iszero(T(-0.0))
        @test iszero(Complex{T}(-0.0))
    end
end
@test !iszero([0, 1, 2, 3])
@test iszero([0, 0, 0, 0])

x = view(1:10, 2:4)
D = Diagonal(x)
@test D[1,1] == 2
@test D[3,3] == 4
A = view(rand(5,5), 1:3, 1:3)
@test D*A == Diagonal(copy(x)) * copy(A)
@test A*D == copy(A) * Diagonal(copy(x))

# julia#17623
if VERSION >= v"0.5.0-dev+5509"
# Use include_string to work around unsupported syntax on Julia 0.4
include_string("""
    @test [true, false] .& [true, true] == [true, false]
    @test [true, false] .| [true, true] == [true, true]
""")
end

# julia#20022
@test !Compat.isapprox(NaN, NaN)
@test Compat.isapprox(NaN, NaN, nans=true)

# julia#13998
for x in (3.1, -17, 3//4, big(111.1), Inf)
    @test min(x) == max(x) == x
    @test minmax(x) == (x, x)
end

# julia#20006
@compat abstract type AbstractFoo20006 end
immutable ConcreteFoo20006{T<:Int} <: AbstractFoo20006 end
immutable ConcreteFoo20006N{T<:Int,N} <: AbstractFoo20006 end
@compat ConcreteFoo200061{T<:Int} = ConcreteFoo20006N{T,1}
@test Compat.TypeUtils.isabstract(AbstractFoo20006)
@test !Compat.TypeUtils.isabstract(ConcreteFoo20006)
@test !Compat.TypeUtils.isabstract(ConcreteFoo20006N)
@test !Compat.TypeUtils.isabstract(ConcreteFoo200061)
@test !Compat.TypeUtils.isabstract(StridedArray)
@test Compat.TypeUtils.parameter_upper_bound(ConcreteFoo20006, 1) == Int
@test isa(Compat.TypeUtils.typename(Array), TypeName)

# @view and @views tests copied from Base
let X = reshape(1:24,2,3,4), Y = 4:-1:1
    @test isa(@view(X[1:3]), SubArray)

    @test X[1:end] == @dotcompat (@view X[1:end]) # test compatibility of @. and @view
    @test X[1:end-3] == @view X[1:end-3]
    @test X[1:end,2,2] == @view X[1:end,2,2]
    @test reshape(X[1,2,1:end-2],2) == @view X[1,2,1:end-2]
    @test reshape(X[1,2,Y[2:end]],3) == @view X[1,2,Y[2:end]]
    @test reshape(X[1:end,2,Y[2:end]],2,3) == @view X[1:end,2,Y[2:end]]

    u = (1,2:3)
    @test reshape(X[u...,2:end],2,3) == @view X[u...,2:end]
    @test reshape(X[(1,)...,(2,)...,2:end],3) == @view X[(1,)...,(2,)...,2:end]

    # the following tests fail on 0.5 because of bugs in the 0.5 Base.@view
    # macro (a bugfix is scheduled to be backported from 0.6: julia#20247)
    if !isdefined(Base, Symbol("@view")) || VERSION ≥ v"0.6.0-dev.2406"
        # test macro hygiene
        let size=(x,y)-> error("should not happen"), Base=nothing
            @test X[1:end,2,2] == @view X[1:end,2,2]
        end

        # test that side effects occur only once
        let foo = typeof(X)[X]
            @test X[2:end-1] == @view (push!(foo,X)[1])[2:end-1]
            @test foo == typeof(X)[X, X]
        end
    end

    # test @views macro
    @views @compat let f!(x) = x[1:end-1] .+= x[2:end].^2
        x = [1,2,3,4]
        f!(x)
        @test x == [5,11,19,4]
        @test isa(x[1:3],SubArray)
        @test x[2] === 11
        @test Dict((1:3) => 4)[1:3] === 4
        x[1:2] = 0
        @test x == [0,0,19,4]
        x[1:2] .= 5:6
        @test x == [5,6,19,4]
        f!(x[3:end])
        @test x == [5,6,35,4]
        x[Y[2:3]] .= 7:8
        @test x == [5,8,7,4]
        @dotcompat x[(3,)..., ()...] += 3 # @. should convert to .+=, test compatibility with @views
        @test x == [5,8,10,4]
        i = Int[]
        # test that lhs expressions in update operations are evaluated only once:
        x[push!(i,4)[1]] += 5
        @test x == [5,8,10,9] && i == [4]
        x[push!(i,3)[end]] += 2
        @test x == [5,8,12,9] && i == [4,3]
        @dotcompat x[3:end] = 0       # make sure @. works with end expressions in @views
        @test x == [5,8,0,0]
    end
    # same tests, but make sure we can switch the order of @compat and @views
    @compat @views let f!(x) = x[1:end-1] .+= x[2:end].^2
        x = [1,2,3,4]
        f!(x)
        @test x == [5,11,19,4]
        @test isa(x[1:3],SubArray)
        @test x[2] === 11
        @test Dict((1:3) => 4)[1:3] === 4
        x[1:2] = 0
        @test x == [0,0,19,4]
        x[1:2] .= 5:6
        @test x == [5,6,19,4]
        f!(x[3:end])
        @test x == [5,6,35,4]
        x[Y[2:3]] .= 7:8
        @test x == [5,8,7,4]
        @dotcompat x[(3,)..., ()...] += 3 # @. should convert to .+=, test compatibility with @views
        @test x == [5,8,10,4]
        i = Int[]
        # test that lhs expressions in update operations are evaluated only once:
        x[push!(i,4)[1]] += 5
        @test x == [5,8,10,9] && i == [4]
        x[push!(i,3)[end]] += 2
        @test x == [5,8,12,9] && i == [4,3]
        @dotcompat x[3:end] = 0       # make sure @. works with end expressions in @views
        @test x == [5,8,0,0]
    end
    @views @test isa(X[1:3], SubArray)
    @test X[1:end] == @views X[1:end]
    @test X[1:end-3] == @views X[1:end-3]
    @test X[1:end,2,2] == @views X[1:end,2,2]
    @test reshape(X[1,2,1:end-2],2) == @views X[1,2,1:end-2]
    @test reshape(X[1,2,Y[2:end]],3) == @views X[1,2,Y[2:end]]
    @test reshape(X[1:end,2,Y[2:end]],2,3) == @views X[1:end,2,Y[2:end]]
    @test reshape(X[u...,2:end],2,3) == @views X[u...,2:end]
    @test reshape(X[(1,)...,(2,)...,2:end],3) == @views X[(1,)...,(2,)...,2:end]

    # test macro hygiene
    let size=(x,y)-> error("should not happen"), Base=nothing
        @test X[1:end,2,2] == @views X[1:end,2,2]
    end
end

# @. (@__dot__) tests, from base:
let x = [4, -9, 1, -16]
    @test [2, 3, 4, 5] == @dotcompat(1 + sqrt($sort(abs(x))))
    @test @dotcompat(x^2) == x.^2
    @dotcompat x = 2
    @test x == [2,2,2,2]
end
@test [1,4,9] == @dotcompat let x = [1,2,3]; x^2; end
let x = [1,2,3], y = x
    @dotcompat for i = 1:3
        y = y^2 # should convert to y .= y.^2
    end
    @test x == [1,256,6561]
end
let x = [1,2,3]
    @dotcompat f(x) = x^2
    @test f(x) == [1,4,9]
end

# PR #20418
@compat abstract type Abstract20418{T} <: Ref{T} end
@test Compat.TypeUtils.isabstract(Abstract20418)
@compat primitive type Primitive20418{T} <: Ref{T} 16 end
@test !Compat.TypeUtils.isabstract(Primitive20418)
@test isbits(Primitive20418{Int})
@test sizeof(Primitive20418{Int}) == 2

# julia #18839
module Test18839

using Compat
using Compat.Iterators
using Base.Test

@test collect(take(countfrom(2), 3)) == [2, 3, 4]
@test collect(take(cycle(5:8), 9)) == [5:8; 5:8; 5]
@test collect(drop([1, 2, 3], 2)) == [3]
@test collect(enumerate([4, 5, 6])) == [(1,4), (2,5), (3,6)]
@test collect(flatten(Any[1:2, 4:5, Any[-1, 4]])) == [1,2,4,5,-1,4]
@test vec(collect(product([1, 2], [3, 4]))) == [(1,3), (2,3), (1,4), (2,4)]
@test vec(collect(product(1:2, 1:2, 1:2))) == [
    (1,1,1), (2,1,1), (1,2,1), (2,2,1),
    (1,1,2), (2,1,2), (1,2,2), (2,2,2)]
@test collect(take(repeated(10), 5)) == [10,10,10,10,10]
@test collect(rest(1:10, 5)) == [5,6,7,8,9,10]
@test collect(take([1, 2, 3], 2)) == [1, 2]
@test collect(zip([1,2], [3,4])) == [(1,3), (2,4)]
@test collect(partition(1:5, 2)) == Any[[1,2],[3,4],[5]]

end

# PR #20500
@compat A20500{T<:Integer} = Array{T,20500}
@compat const A20500_2{T<:Union{Int,Float32}} = Pair{T,T}
f20500() = A20500
f20500_2() = A20500_2
@inferred f20500()
@inferred f20500_2()

module CompatArray
using Compat
immutable CartesianArray{T,N} <: AbstractArray{T,N}
    parent::Array{T,N}
end
immutable LinearArray{T,N} <: AbstractArray{T,N}
    parent::Array{T,N}
end
@compat Base.IndexStyle(::Type{<:LinearArray}) = IndexLinear()
end
@test IndexStyle(Array{Float32,2}) === IndexLinear()
@test IndexStyle(CompatArray.CartesianArray{Float32,2}) === IndexCartesian()
@test IndexStyle(CompatArray.LinearArray{Float32,2}) === IndexLinear()
let a = CompatArray.CartesianArray(rand(2,3)), b = CompatArray.LinearArray(rand(2,3))
    @test IndexStyle(a) === IndexCartesian()
    @test IndexStyle(b) === IndexLinear()
end

for (A,val) in ((zeros(1:5, Float32, 3, 2), 0),
                (ones(1:5, Float32, 3, 2), 1),
                (zeros(1:5, Float32, (3, 2)), 0),
                (ones(1:5, Float32, (3, 2)), 1))
    @test isa(A, Matrix{Float32}) && size(A) == (3,2) && all(x->x==val, A)
end
for (A,val) in ((zeros(1:5, Float32), 0),
                (ones(1:5, Float32), 1))
    @test isa(A, Vector{Float32}) && size(A) == (5,) && all(x->x==val, A)
end

# PR 20203
@test Compat.readline(IOBuffer("Hello, World!\n")) == "Hello, World!"
@test Compat.readline(IOBuffer("x\n"), chomp=true) == "x"
@test Compat.readline(IOBuffer("x\n"), chomp=false) == "x\n"

# PR 18727
let
    iset = Set([17, 4711])
    cfset = convert(Set{Float64}, iset)
    @test typeof(cfset) == Set{Float64}
    @test cfset == iset
    fset = Set([17.0, 4711.0])
    ciset = convert(Set{Int}, fset)
    @test typeof(ciset) == Set{Int}
    @test ciset == fset
    ssset = Set(split("foo bar"))
    cssset = convert(Set{String}, ssset)
    @test typeof(cssset) == Set{String}
    @test cssset == Set(["foo", "bar"])
end

include("to-be-deprecated.jl")

nothing


text:
versioninfo()

# If needed:
#Pkg.add("DifferentialEquations")
#Pkg.add("PyPlot")
#Pkg.add("Plots")

using Plots
gr()
using DifferentialEquations

b = 0.25
c = 5.0

y0 = [pi - 0.1; 0.0]

function pend(t, y, dy)
    dy[1] = y[2]
    dy[2] = (-b * y[2]) - (c * sin(y[1]))
end

function f_pend(y, t)
    return [y[2], (-b * y[2]) - (c * sin(y[1]))]
end

tspan = (0.0, 10.0)

function odeint_1(f, y0, tspan)
    prob = ODEProblem(f, y0, tspan)
    sol = solve(prob)
    return sol.t, hcat(sol.u...)'
end

function odeint(f, y0, tspan)
    t, sol = odeint_1(f, y0, tspan)
    return sol
end

t, sol = odeint_1(pend, y0, tspan)

plot(t, sol[:, 1], xaxis="Time t", title="Solution to the pendulum ODE", label="\\theta (t)")
plot!(t, sol[:, 2], label="\\omega (t)")

function rungekutta1(f, y0, t)
    n = length(t)
    y = zeros((n, length(y0)))
    y[1,:] = y0
    for i in 1:n-1
        h = t[i+1] - t[i]
        y[i+1,:] = y[i,:] + h * f(y[i,:], t[i])
    end
    return y
end

t = linspace(0, 10, 101);
sol = rungekutta1(f_pend, y0, t);

plot(t, sol[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 1", label="\\theta (t)")
plot!(t, sol[:, 2], label="\\omega (t)")

t2 = linspace(0, 10, 1001);
sol2 = rungekutta1(f_pend, y0, t2);

plot(t2, sol2[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 1", label="\\theta (t)")
plot!(t2, sol2[:, 2], label="\\omega (t)")

t3 = linspace(0, 10, 2001);
sol3 = rungekutta1(f_pend, y0, t3);

plot(t3, sol3[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 1", label="\\theta (t)")
plot!(t3, sol3[:, 2], label="\\omega (t)")

function rungekutta2(f, y0, t)
    n = length(t)
    y = zeros((n, length(y0)))
    y[1,:] = y0
    for i in 1:n-1
        h = t[i+1] - t[i]
        y[i+1,:] = y[i,:] + h * f(y[i,:] + f(y[i,:], t[i]) * h/2, t[i] + h/2)
    end
    return y
end

t3 = linspace(0, 10, 21);
sol3 = rungekutta2(f_pend, y0, t3);

plot(t3, sol3[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 2 (21 points)", label="\\theta (t)")
plot!(t3, sol3[:, 2], label="\\omega (t)")

t3 = linspace(0, 10, 101);
sol3 = rungekutta2(f_pend, y0, t3);

plot(t3, sol3[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 2 (101 points)", label="\\theta (t)")
plot!(t3, sol3[:, 2], label="\\omega (t)")

function rungekutta4(f, y0, t)
    n = length(t)
    y = zeros((n, length(y0)))
    y[1,:] = y0
    for i in 1:n-1
        h = t[i+1] - t[i]
        k1 = f(y[i,:], t[i])
        k2 = f(y[i,:] + k1 * h/2, t[i] + h/2)
        k3 = f(y[i,:] + k2 * h/2, t[i] + h/2)
        k4 = f(y[i,:] + k3 * h, t[i] + h)
        y[i+1,:] = y[i,:] + (h/6) * (k1 + 2*k2 + 2*k3 + k4)
    end
    return y
end

t = linspace(0, 10, 31);
sol = rungekutta4(f_pend, y0, t);

plot(t, sol[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 4 (31 points)", label="\\theta (t)")
plot!(t, sol[:, 2], label="\\omega (t)")

t = linspace(0, 10, 101);
sol = rungekutta4(f_pend, y0, t);

plot(t, sol[:, 1], xaxis="Time t", title="Solution to the pendulum ODE with Runge-Kutta 4 (101 points)", label="\\theta (t)")
plot!(t, sol[:, 2], label="\\omega (t)")

methods = [rungekutta1, rungekutta2, rungekutta4]
markers = [:o, :s, :>]

function test_1(n=101)
    t = linspace(0, 10, n)
    tspan = (0.0, 10.0)
    t1, sol = odeint_1(pend, y0, tspan)
    plt = plot(t1, sol[:, 1], marker=:d, xaxis="Time t", title="Solution to the pendulum ODE with ($n points)", label="odeint")
    for (method, m) in zip(methods, markers)
        sol = method(f_pend, y0, t)
        plot!(t, sol[:, 1], marker=m, label=string(method))
    end
    display(plt)
end

test_1(10)

test_1(20)

test_1(100)

test_1(200)

y0 = [0; 1; 0.1]

function f(y, t)
    return [y[2], y[3], 12 * y[1]^(4/5) + cos(y[2])^3 - sin(y[3])]
end

function f_2(t, y, dy)
    dy[1] = y[2]
    dy[2] = y[3]
    dy[3] = 12 * y[1]^(4/5) + cos(y[2])^3 - sin(y[3])
end

function test_2(n=101)
    t = linspace(0, 1, n)
    tspan = (0.0, 1.0)
    t1, sol = odeint_1(f_2, y0, tspan)
    plt = plot(t1, sol[:, 1], marker=:d, xaxis="Time t", title="Solution to an ODE with ($n points)", label="odeint")
    for (method, m) in zip(methods, markers)
        sol = method(f, y0, t)
        plot!(t, sol[:, 1], marker=m, label=string(method))
    end
    display(plt)
end

test_2(10)

test_2(50)

y0 = [10.0, -3.0, 1.0, 1.0]

function f(y, t)
    return [y[2], y[3], y[4], y[1]^(-5/3)]
end

function f_2(t, y, dy)
    dy[1] = y[2]
    dy[2] = y[3]
    dy[3] = y[4]
    dy[4] = y[1]^(-5/3)
end

function test_3(n=101)
    t = linspace(0, 1, n)
    tspan = (0.0, 1.0)
    t1, sol = odeint_1(f_2, y0, tspan)
    plt = plot(t1, sol[:, 1], marker=:d, xaxis="Time t", title="Solution to an ODE with ($n points)", label="odeint")
    for (method, m) in zip(methods, markers)
        sol = method(f, y0, t)
        plot!(t, sol[:, 1], marker=m, label=string(method))
    end
    display(plt)
end

test_3(10)

test_3(50)

function benchmark(n=101)
    t = linspace(0, 1, n)
    tspan = (0.0, 1.0)

    print("Time of solving an ODE with the 'solve' method from 'DifferentialEquations' ...\n")
    @time t1, sol = odeint_1(f_2, y0, tspan)
    for method in methods
        print("Time of solving an ODE with the $method method for $n points ...\n")
        @time sol = method(f, y0, t)
    end
end

for n in [20, 100, 1000]
    print("\nFor $n points...\n")
    benchmark(n)
end

using BenchmarkTools, Compat

function benchmark(n=101)
    t = linspace(0, 1, n)
    tspan = (0.0, 1.0)

    print("Time of solving an ODE with the 'solve' method from 'DifferentialEquations' ...\n")
    @btime t1, sol = $odeint_1($f_2, $y0, $tspan)
    for method in methods
        print("Time of solving an ODE with the $method method for $n points ...\n")
        @btime sol = $method($f, $y0, $t)
    end
end

for n in [20, 100, 1000]
    print("\nFor $n points...\n")
    benchmark(n)
end

max_issues_repo_name: operade/notebooks

max_forks_repo_name: operade/notebooks