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

@doc raw"""StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.  StorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.

    IoK8sApiStorageV1StorageClass(;
        allowVolumeExpansion=nothing,
        allowedTopologies=nothing,
        apiVersion=nothing,
        kind=nothing,
        metadata=nothing,
        mountOptions=nothing,
        parameters=nothing,
        provisioner=nothing,
        reclaimPolicy=nothing,
        volumeBindingMode=nothing,
    )

    - allowVolumeExpansion::Bool : AllowVolumeExpansion shows whether the storage class allow volume expand
    - allowedTopologies::Vector{IoK8sApiCoreV1TopologySelectorTerm} : Restrict the node topologies where volumes can be dynamically provisioned. Each volume plugin defines its own supported topology specifications. An empty TopologySelectorTerm list means there is no topology restriction. This field is only honored by servers that enable the VolumeScheduling feature.
    - apiVersion::String : APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
    - kind::String : Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    - metadata::IoK8sApimachineryPkgApisMetaV1ObjectMeta : Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    - mountOptions::Vector{String} : Dynamically provisioned PersistentVolumes of this storage class are created with these mountOptions, e.g. [\"ro\", \"soft\"]. Not validated - mount of the PVs will simply fail if one is invalid.
    - parameters::Dict{String, String} : Parameters holds the parameters for the provisioner that should create volumes of this storage class.
    - provisioner::String : Provisioner indicates the type of the provisioner.
    - reclaimPolicy::String : Dynamically provisioned PersistentVolumes of this storage class are created with this reclaimPolicy. Defaults to Delete.
    - volumeBindingMode::String : VolumeBindingMode indicates how PersistentVolumeClaims should be provisioned and bound.  When unset, VolumeBindingImmediate is used. This field is only honored by servers that enable the VolumeScheduling feature.
"""
mutable struct IoK8sApiStorageV1StorageClass <: SwaggerModel
    allowVolumeExpansion::Any # spec type: Union{ Nothing, Bool } # spec name: allowVolumeExpansion
    allowedTopologies::Any # spec type: Union{ Nothing, Vector{IoK8sApiCoreV1TopologySelectorTerm} } # spec name: allowedTopologies
    apiVersion::Any # spec type: Union{ Nothing, String } # spec name: apiVersion
    kind::Any # spec type: Union{ Nothing, String } # spec name: kind
    metadata::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgApisMetaV1ObjectMeta } # spec name: metadata
    mountOptions::Any # spec type: Union{ Nothing, Vector{String} } # spec name: mountOptions
    parameters::Any # spec type: Union{ Nothing, Dict{String, String} } # spec name: parameters
    provisioner::Any # spec type: Union{ Nothing, String } # spec name: provisioner
    reclaimPolicy::Any # spec type: Union{ Nothing, String } # spec name: reclaimPolicy
    volumeBindingMode::Any # spec type: Union{ Nothing, String } # spec name: volumeBindingMode

    function IoK8sApiStorageV1StorageClass(;allowVolumeExpansion=nothing, allowedTopologies=nothing, apiVersion=nothing, kind=nothing, metadata=nothing, mountOptions=nothing, parameters=nothing, provisioner=nothing, reclaimPolicy=nothing, volumeBindingMode=nothing)
        o = new()
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("allowVolumeExpansion"), allowVolumeExpansion)
        setfield!(o, Symbol("allowVolumeExpansion"), allowVolumeExpansion)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("allowedTopologies"), allowedTopologies)
        setfield!(o, Symbol("allowedTopologies"), allowedTopologies)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("apiVersion"), apiVersion)
        setfield!(o, Symbol("apiVersion"), apiVersion)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("kind"), kind)
        setfield!(o, Symbol("kind"), kind)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("metadata"), metadata)
        setfield!(o, Symbol("metadata"), metadata)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("mountOptions"), mountOptions)
        setfield!(o, Symbol("mountOptions"), mountOptions)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("parameters"), parameters)
        setfield!(o, Symbol("parameters"), parameters)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("provisioner"), provisioner)
        setfield!(o, Symbol("provisioner"), provisioner)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("reclaimPolicy"), reclaimPolicy)
        setfield!(o, Symbol("reclaimPolicy"), reclaimPolicy)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("volumeBindingMode"), volumeBindingMode)
        setfield!(o, Symbol("volumeBindingMode"), volumeBindingMode)
        o
    end
end # type IoK8sApiStorageV1StorageClass

const _property_map_IoK8sApiStorageV1StorageClass = Dict{Symbol,Symbol}(Symbol("allowVolumeExpansion")=>Symbol("allowVolumeExpansion"), Symbol("allowedTopologies")=>Symbol("allowedTopologies"), Symbol("apiVersion")=>Symbol("apiVersion"), Symbol("kind")=>Symbol("kind"), Symbol("metadata")=>Symbol("metadata"), Symbol("mountOptions")=>Symbol("mountOptions"), Symbol("parameters")=>Symbol("parameters"), Symbol("provisioner")=>Symbol("provisioner"), Symbol("reclaimPolicy")=>Symbol("reclaimPolicy"), Symbol("volumeBindingMode")=>Symbol("volumeBindingMode"))
const _property_types_IoK8sApiStorageV1StorageClass = Dict{Symbol,String}(Symbol("allowVolumeExpansion")=>"Bool", Symbol("allowedTopologies")=>"Vector{IoK8sApiCoreV1TopologySelectorTerm}", Symbol("apiVersion")=>"String", Symbol("kind")=>"String", Symbol("metadata")=>"IoK8sApimachineryPkgApisMetaV1ObjectMeta", Symbol("mountOptions")=>"Vector{String}", Symbol("parameters")=>"Dict{String, String}", Symbol("provisioner")=>"String", Symbol("reclaimPolicy")=>"String", Symbol("volumeBindingMode")=>"String")
Base.propertynames(::Type{ IoK8sApiStorageV1StorageClass }) = collect(keys(_property_map_IoK8sApiStorageV1StorageClass))
Swagger.property_type(::Type{ IoK8sApiStorageV1StorageClass }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiStorageV1StorageClass[name]))}
Swagger.field_name(::Type{ IoK8sApiStorageV1StorageClass }, property_name::Symbol) =  _property_map_IoK8sApiStorageV1StorageClass[property_name]

function check_required(o::IoK8sApiStorageV1StorageClass)
    (getproperty(o, Symbol("provisioner")) === nothing) && (return false)
    true
end

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


text:
module ComplexValues

export Polar,Spherical,S2coord

# Individually overloaded operators
import Base: Complex,complex,float,iszero,isapprox,isinf,isfinite,one,zero
import Base: +,-,*,/,sign,inv,angle,abs,abs2,real,imag,conj,show

# Utilities
cleanangle(θ) = π - mod2pi(π-θ)  # map angle to equivalent in (-pi,pi]
Float = typeof(1.)  # default base floating type

# Definitions of the types
include("spherical.jl")
include("polar.jl")

AnyComplex{T<:AbstractFloat} = Union{Complex{T},Polar{T},Spherical{T}}
AnyNonnative{T<:AbstractFloat} = Union{Polar{T},Spherical{T}}
#AllValues = Union{Number,AnyNonnative}

complex(z::AnyNonnative) = z
float(z::AnyNonnative) = z

# promotion rules and conversion boilerplate
import Base: promote_rule
promote_rule(::Union{Type{Complex{S}},Type{S}},::Type{Spherical{T}}) where {S<:Real,T<:AbstractFloat} = Spherical{promote_type(S,T)}
promote_rule(::Union{Type{Complex{S}},Type{S}},::Type{Polar{T}}) where {S<:Real,T<:AbstractFloat} = Polar{promote_type(S,T)}
promote_rule(::Type{Polar{S}},::Type{Spherical{T}}) where {S<:AbstractFloat,T<:AbstractFloat} = Spherical{promote_type(S,T)}

# convert() boilerplate to invoke constructors
import Base.convert
convert(::Type{Complex{S}},z::AnyNonnative) where S<:Real = convert(Complex{S},Complex(z))
convert(::Type{Polar{S}},z::AnyNonnative) where S<:AbstractFloat = Polar{S}(z)
convert(::Type{Polar{S}},z::Number) where S<:AbstractFloat = Polar{S}(Complex(z))
convert(::Type{Spherical{S}},z::AnyNonnative) where S<:AbstractFloat = Spherical{S}(z)
convert(::Type{Spherical{S}},z::Number) where S<:AbstractFloat = Spherical{S}(Complex(z))

# Most other 1-argument and 2-argument base functions just get converted to regular complex
for f in [:cos,:sin,:tan,:sec,:csc,:cot,:acos,:asin,:atan,:asec,:acsc,:acot,:sincos,:sinpi,
	:cosh,:sinh,:tanh,:sech,:csch,:coth,:acosh,:asinh,:atanh,:asech,:acsch,:acoth,
	:exp,:exp10,:exp2,:expm1,:log,:log10,:log1p,:log2,:sqrt]
	quote
		import Base: $f
		$f(z::AnyNonnative) = $f(Complex(z))
	end |> eval
end

for f in [:log,:^]
	quote
		import Base: $f
		$f(z::AnyNonnative,w::AnyNonnative) = $f(Complex(z),Complex(w))
	end |> eval
end

include("plotrecipes.jl")

end # module

ext: jl


text:
using BinDeps
using Compat

@BinDeps.setup
libnames = ["libCLBLAS", "clBLAS", "libclBLAS"]
libCLBLAS = library_dependency("libCLBLAS", aliases = libnames)
baseurl = "https://github.com/clMathLibraries/clBLAS/releases/download/v2.12/clBLAS-2.12.0-"

# download a pre-compiled binary
if is_windows()
    if Sys.ARCH == :x86_64
        uri = URI(baseurl * "Windows-x64.zip")
        basedir = joinpath(@__DIR__, "package")
        provides(
            Binaries, uri,
            libCLBLAS, unpacked_dir = basedir,
            installed_libpath = joinpath(basedir, "bin"), os = :Windows
        )
    else
        error("Only 64 bits windows supported with automatic build")
    end
end

if is_linux()
    if Sys.ARCH == :x86_64
        push!(BinDeps.defaults, Binaries)
        name, ext = splitext(splitext(basename(baseurl * "Linux-x64.tar.gz"))[1])
        uri = URI(baseurl * "Linux-x64.tar.gz")
        basedir = joinpath(@__DIR__, name)
        provides(
            Binaries, uri,
            libCLBLAS, unpacked_dir = basedir,
            installed_libpath = joinpath(basedir, "lib64"), os = :Linux
        )
    end
    # provides(AptGet, "libclblas-dev", libCLBLAS)
end

if is_apple()
    using Homebrew
    provides(Homebrew.HB, "homebrew/core/clblas", libCLBLAS, os = :Darwin)
end

@BinDeps.install Dict("libCLBLAS" => "libCLBLAS")

is_linux() && Sys.ARCH == :x86_64 && pop!(BinDeps.defaults)


text:
using Luxor, Colors

function logistic(r,x)
    r*x*(1.0-x)
end

function logisticmap(;x0=0.2,r=4,n=10)
    results = [(x0,logistic(r,x0))];
    #N = 100; Note this line should not be here
    for i in 1:(n-1) # Note change of case N -> n.  Why?
      xold = results[end][2]
      xnew = logistic(r,xold)
      append!(results,[(xold,xold)])
      append!(results,[(xold,xnew)])
  end
  results
end

simres = logisticmap(x0=0.2,r=4,n=100)

xvals = []
yvals = []

for (x, y) in simres
    append!(xvals, x)
    append!(yvals, y)
end

function cross(turtle)
    Forward(turtle, 5)
    Turn(turtle, 180)
    Forward(turtle, 10)
    Turn(turtle, 180)
    Forward(turtle, 5)
    Turn(turtle, 90)
    Forward(turtle, 5)
    Turn(turtle, 180)
    Forward(turtle, 10)
    Turn(turtle, 180)
end

turtle = Turtle()
Pencolor(turtle, "black")
Penwidth(turtle, 1.5)
Reposition(turtle, 100*simres[1][1], -100*simres[1][2])
Pendown(turtle)
for (x, y) in simres
    Reposition(turtle, 100*x, -100*y)
    #Pendown(turtle)
    #cross(turtle)
end
finish()

Drawing(500,500,"turtlegraph2.png")
origin()
background("white")

turtle = Turtle()
Pencolor(turtle, "black")
Penwidth(turtle, 1.5)
for (x, y) in simres
    Reposition(turtle, 250*x, -250*y)
    Pendown(turtle)
    cross(turtle)
end
finish()


text:
export PhasePartition
# Thermodynamic states
export ThermodynamicState,
    PhaseDry,
    PhaseDry_given_pT,
    PhaseEquil,
    PhaseNonEquil,
    TemperatureSHumEquil,
    LiquidIcePotTempSHumEquil,
    LiquidIcePotTempSHumEquil_given_pressure,
    LiquidIcePotTempSHumNonEquil,
    LiquidIcePotTempSHumNonEquil_given_pressure

"""
    PhasePartition

Represents the mass fractions of the moist air mixture.

# Constructors

    PhasePartition(q_tot::Real[, q_liq::Real[, q_ice::Real]])
    PhasePartition(ts::ThermodynamicState)

See also [`PhasePartition_equil`](@ref)

# Fields

$(DocStringExtensions.FIELDS)
"""
struct PhasePartition{FT <: Real}
    "total specific humidity"
    tot::FT
    "liquid water specific humidity (default: `0`)"
    liq::FT
    "ice specific humidity (default: `0`)"
    ice::FT
end

PhasePartition(q_tot::FT, q_liq::FT) where {FT <: Real} =
    PhasePartition(q_tot, q_liq, zero(FT))
PhasePartition(q_tot::FT) where {FT <: Real} =
    PhasePartition(q_tot, zero(FT), zero(FT))

"""
    ThermodynamicState{FT}

A thermodynamic state, which can be initialized for
various thermodynamic formulations (via its sub-types).
All `ThermodynamicState`'s have access to functions to
compute all other thermodynamic properties.
"""
abstract type ThermodynamicState{FT} end

"""
    PhaseEquil{FT} <: ThermodynamicState

A thermodynamic state assuming thermodynamic equilibrium (therefore, saturation adjustment
may be needed).

# Constructors

    PhaseEquil(param_set, e_int, ρ, q_tot)

# Fields

$(DocStringExtensions.FIELDS)
"""
struct PhaseEquil{FT, PS} <: ThermodynamicState{FT}
    "parameter set, used to dispatch planet parameter function calls"
    param_set::PS
    "internal energy"
    e_int::FT
    "density of air (potentially moist)"
    ρ::FT
    "total specific humidity"
    q_tot::FT
    "temperature: computed via [`saturation_adjustment`](@ref)"
    T::FT
end
function PhaseEquil(
    param_set::APS,
    e_int::FT,
    ρ::FT,
    q_tot::FT,
    maxiter::Int = 3,
    tol::FT = FT(1e-1),
    sat_adjust::Function = saturation_adjustment,
) where {FT <: Real}
    # TODO: Remove these safety nets, or at least add warnings
    # waiting on fix: github.com/vchuravy/GPUifyLoops.jl/issues/104
    q_tot_safe = clamp(q_tot, FT(0), FT(1))
    T = sat_adjust(param_set, e_int, ρ, q_tot_safe, maxiter, tol)
    return PhaseEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q_tot_safe, T)
end

"""
    PhaseDry{FT} <: ThermodynamicState

A dry thermodynamic state (`q_tot = 0`).

# Constructors

    PhaseDry(param_set, e_int, ρ)

# Fields

$(DocStringExtensions.FIELDS)
"""
struct PhaseDry{FT, PS} <: ThermodynamicState{FT}
    "parameter set, used to dispatch planet parameter function calls"
    param_set::PS
    "internal energy"
    e_int::FT
    "density of dry air"
    ρ::FT
end
PhaseDry(param_set::APS, e_int::FT, ρ::FT) where {FT} =
    PhaseDry{FT, typeof(param_set)}(param_set, e_int, ρ)

"""
    PhaseDry_given_pT(param_set, p, T)

Constructs a [`PhaseDry`](@ref) thermodynamic state from:

 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `p` pressure
 - `T` temperature
"""
function PhaseDry_given_pT(param_set::APS, p::FT, T::FT) where {FT <: Real}
    e_int = internal_energy(param_set, T)
    ρ = air_density(param_set, T, p)
    return PhaseDry{FT, typeof(param_set)}(param_set, e_int, ρ)
end

"""
    LiquidIcePotTempSHumEquil(param_set, θ_liq_ice, ρ, q_tot)

Constructs a [`PhaseEquil`](@ref) thermodynamic state from:

 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `θ_liq_ice` liquid-ice potential temperature
 - `ρ` (moist-)air density
 - `q_tot` total specific humidity
 - `tol` tolerance for saturation adjustment
 - `maxiter` maximum iterations for saturation adjustment
"""
function LiquidIcePotTempSHumEquil(
    param_set::APS,
    θ_liq_ice::FT,
    ρ::FT,
    q_tot::FT,
    maxiter::Int = 30,
    tol::FT = FT(1e-1),
) where {FT <: Real}
    T = saturation_adjustment_q_tot_θ_liq_ice(
        param_set,
        θ_liq_ice,
        ρ,
        q_tot,
        maxiter,
        tol,
    )
    q_pt = PhasePartition_equil(param_set, T, ρ, q_tot)
    e_int = internal_energy(param_set, T, q_pt)
    return PhaseEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q_tot, T)
end

"""
    LiquidIcePotTempSHumEquil_given_pressure(param_set, θ_liq_ice, p, q_tot)

Constructs a [`PhaseEquil`](@ref) thermodynamic state from:

 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `θ_liq_ice` liquid-ice potential temperature
 - `p` pressure
 - `q_tot` total specific humidity
 - `tol` tolerance for saturation adjustment
 - `maxiter` maximum iterations for saturation adjustment
"""
function LiquidIcePotTempSHumEquil_given_pressure(
    param_set::APS,
    θ_liq_ice::FT,
    p::FT,
    q_tot::FT,
    maxiter::Int = 30,
    tol::FT = FT(1e-1),
) where {FT <: Real}
    T = saturation_adjustment_q_tot_θ_liq_ice_given_pressure(
        param_set,
        θ_liq_ice,
        p,
        q_tot,
        maxiter,
        tol,
    )
    ρ = air_density(param_set, T, p, PhasePartition(q_tot))
    q = PhasePartition_equil(param_set, T, ρ, q_tot)
    e_int = internal_energy(param_set, T, q)
    return PhaseEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q.tot, T)
end

"""
    TemperatureSHumEquil(param_set, T, p, q_tot)

Constructs a [`PhaseEquil`](@ref) thermodynamic state from temperature.

 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `T` temperature
 - `p` pressure
 - `q_tot` total specific humidity
"""
function TemperatureSHumEquil(
    param_set::APS,
    T::FT,
    p::FT,
    q_tot::FT,
) where {FT <: Real}
    ρ = air_density(param_set, T, p, PhasePartition(q_tot))
    q = PhasePartition_equil(param_set, T, ρ, q_tot)
    e_int = internal_energy(param_set, T, q)
    return PhaseEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q_tot, T)
end

"""
   	 PhaseNonEquil{FT} <: ThermodynamicState

A thermodynamic state assuming thermodynamic non-equilibrium (therefore, temperature can
be computed directly).

# Constructors

    PhaseNonEquil(param_set, e_int, q::PhasePartition, ρ)

# Fields

$(DocStringExtensions.FIELDS)

"""
struct PhaseNonEquil{FT, PS} <: ThermodynamicState{FT}
    "parameter set, used to dispatch planet parameter function calls"
    param_set::PS
    "internal energy"
    e_int::FT
    "density of air (potentially moist)"
    ρ::FT
    "phase partition"
    q::PhasePartition{FT}
end
function PhaseNonEquil(
    param_set::APS,
    e_int::FT,
    ρ::FT,
    q::PhasePartition{FT} = q_pt_0(FT),
) where {FT}
    return PhaseNonEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q)
end

"""
    LiquidIcePotTempSHumNonEquil(param_set, θ_liq_ice, ρ, q_pt)

Constructs a [`PhaseNonEquil`](@ref) thermodynamic state from:

 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `θ_liq_ice` liquid-ice potential temperature
 - `ρ` (moist-)air density
 - `q_pt` phase partition
and, optionally
 - `tol` tolerance for non-linear equation solve
 - `maxiter` maximum iterations for non-linear equation solve
"""
function LiquidIcePotTempSHumNonEquil(
    param_set::APS,
    θ_liq_ice::FT,
    ρ::FT,
    q_pt::PhasePartition{FT},
    maxiter::Int = 5,
    tol::FT = FT(1e-1),
) where {FT <: Real}
    T = air_temperature_from_liquid_ice_pottemp_non_linear(
        param_set,
        θ_liq_ice,
        ρ,
        maxiter,
        tol,
        q_pt,
    )
    e_int = internal_energy(param_set, T, q_pt)
    return PhaseNonEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q_pt)
end

"""
    LiquidIcePotTempSHumNonEquil_given_pressure(param_set, θ_liq_ice, p, q_pt)

Constructs a [`PhaseNonEquil`](@ref) thermodynamic state from:

 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `θ_liq_ice` liquid-ice potential temperature
 - `p` pressure
 - `q_pt` phase partition
"""
function LiquidIcePotTempSHumNonEquil_given_pressure(
    param_set::APS,
    θ_liq_ice::FT,
    p::FT,
    q_pt::PhasePartition{FT},
) where {FT <: Real}
    T = air_temperature_from_liquid_ice_pottemp_given_pressure(
        param_set,
        θ_liq_ice,
        p,
        q_pt,
    )
    ρ = air_density(param_set, T, p, q_pt)
    e_int = internal_energy(param_set, T, q_pt)
    return PhaseNonEquil{FT, typeof(param_set)}(param_set, e_int, ρ, q_pt)
end

"""
    fixed_lapse_rate_ref_state(
        param_set::APS,
        z::FT,
        T_surface::FT,
        T_min::FT,
        ) where {FT <: AbstractFloat}

Fixed lapse rate hydrostatic reference state
"""
function fixed_lapse_rate_ref_state(
    param_set::APS,
    z::FT,
    T_surface::FT,
    T_min::FT,
) where {FT <: AbstractFloat}
    _grav::FT = grav(param_set)
    _cp_d::FT = cp_d(param_set)
    _R_d::FT = R_d(param_set)
    _MSLP::FT = MSLP(param_set)
    Γ = _grav / _cp_d
    z_tropopause = (T_surface - T_min) / Γ
    H_min = _R_d * T_min / _grav
    T = max(T_surface - Γ * z, T_min)
    p = _MSLP * (T / T_surface)^(_grav / (_R_d * Γ))
    T == T_min && (p = p * exp(-(z - z_tropopause) / H_min))
    ρ = p / (_R_d * T)
    return T, p, ρ
end

"""
    tested_convergence_range(param_set, n::Int, ::Type{FT})

A range of input arguments to thermodynamic state constructors
 - `param_set` an `AbstractParameterSet`, see the [`MoistThermodynamics`](@ref) for more details
 - `e_int` internal energy
 - `ρ` (moist-)air density
 - `q_tot` total specific humidity
 - `q_pt` phase partition
 - `T` air temperature
 - `θ_liq_ice` liquid-ice potential temperature
that are tested for convergence in saturation adjustment.

Note that the output vectors are of size ``n*n_RH``, and they
should span the input arguments to all of the constructors.
"""
function tested_convergence_range(param_set::APS, n::Int, ::Type{FT}) where {FT}
    n_RS1 = 10
    n_RS2 = 20
    n_RS = n_RS1 + n_RS2
    z_range = range(FT(0), stop = FT(2.5e4), length = n)
    relative_sat1 = range(FT(0), stop = FT(1), length = n_RS1)
    relative_sat2 = range(FT(1), stop = FT(1.02), length = n_RS2)
    relative_sat = [relative_sat1..., relative_sat2...]
    T_min = FT(150)
    T_surface = FT(350)

    args =
        fixed_lapse_rate_ref_state.(
            Ref(param_set),
            z_range,
            Ref(T_surface),
            Ref(T_min),
        )
    T, p, ρ = getindex.(args, 1), getindex.(args, 2), getindex.(args, 3)

    p = collect(Iterators.flatten([p for RS in 1:n_RS]))
    ρ = collect(Iterators.flatten([ρ for RS in 1:n_RS]))
    T = collect(Iterators.flatten([T for RS in 1:n_RS]))
    relative_sat = collect(Iterators.flatten([relative_sat for RS in 1:n]))

    # Additional variables
    q_sat = q_vap_saturation.(Ref(param_set), T, ρ)
    q_tot = min.(relative_sat .* q_sat, FT(1))
    q_pt = PhasePartition_equil.(Ref(param_set), T, ρ, q_tot)
    e_int = internal_energy.(Ref(param_set), T, q_pt)
    θ_liq_ice = liquid_ice_pottemp.(Ref(param_set), T, ρ, q_pt)
    return e_int, ρ, q_tot, q_pt, T, p, θ_liq_ice
end


text:
# Data for the simulation

using Parameters

  @with_kw struct Data
   N :: Int64 = 10_000

   eps :: Float64 = 5.0
   sig :: Float64 = 0.5

   cutoff :: Float64 = 2.0
   side :: Float64 = 100

   sig6 :: Float64 = (sig^2)^3
   eps4 :: Float64 = 4*eps
   sig12 :: Float64 = (sig^2)^6

end


text:
using PackageCompilerX: PackageCompilerX, create_sysimage, create_app
using Test
using Libdl

ENV["JULIA_DEBUG"] = "PackageCompilerX"

# Make a new depot
new_depot = mktempdir()
mkpath(joinpath(new_depot, "registries"))
cp(joinpath(DEPOT_PATH[1], "registries", "General"), joinpath(new_depot, "registries", "General"))
ENV["JULIA_DEPOT_PATH"] = new_depot
Base.init_depot_path()

@testset "PackageCompilerX.jl" begin
    tmp = mktempdir()
    sysimage_path = joinpath(tmp, "sys." * Libdl.dlext)
    create_sysimage(:Example; sysimage_path=sysimage_path,
                              precompile_execution_file="precompile_execution.jl",
                              precompile_statements_file=["precompile_statements.jl",
                                                          "precompile_statements2.jl"])
    # Check we can load sysimage and that Example is available in Main
    str = read(`$(Base.julia_cmd()) -J $(sysimage_path) -e 'print(Example.hello("foo"))'`, String)
    @test occursin("Hello, foo", str)

    # Test creating an app
    app_source_dir = joinpath(@__DIR__, "..", "examples/MyApp/")
    # TODO: Also test something that actually gives audit warnings
    @test_logs PackageCompilerX.audit_app(app_source_dir)
    app_compiled_dir = joinpath(tmp, "MyAppCompiled")
    for incremental in (true, false)
        if incremental == false
            filter_stdlibs = (true, false)
        else
            filter_stdlibs = (false,)
        end
        for filter in filter_stdlibs
            tmp_app_source_dir = joinpath(tmp, "MyApp")
            cp(app_source_dir, tmp_app_source_dir)
            create_app(tmp_app_source_dir, app_compiled_dir; incremental=incremental, force=true, filter_stdlibs=filter,
                       precompile_execution_file=joinpath(app_source_dir, "precompile_app.jl"))
            rm(tmp_app_source_dir; recursive=true)
            # Get rid of some local state
            rm(joinpath(new_depot, "packages"); recursive=true)
            rm(joinpath(new_depot, "compiled"); recursive=true)
            app_path = abspath(app_compiled_dir, "bin", "MyApp" * (Sys.iswindows() ? ".exe" : ""))
            app_output = read(`$app_path`, String)

            # Check stdlib filtering
            if filter == true
                @test !(occursin("LinearAlgebra", app_output))
            else
                @test occursin("LinearAlgebra", app_output)
            end
            # Check dependency run
            @test occursin("Example.domath", app_output)
            # Check jll package runs
            @test occursin("Hello, World!", app_output)
            # Check artifact runs
            @test occursin("The result of 2*5^2 - 10 == 40.000000", app_output)
            # Check artifact gets run from the correct place
            @test occursin("HelloWorld artifact at $(realpath(app_compiled_dir))", app_output)
        end
    end
end


text:
module NoInliningAllowed

using Mixtape
import Mixtape: CompilationContext, transform, allow
using MacroTools
using CodeInfoTools
using BenchmarkTools

@noinline foo(x) = x^5
@noinline bar(x) = x^10
apply(f, x1, x2::Val{T}) where {T} = f(x1, T)

@noinline function f(x)
    g = x < 5 ? foo : bar
    return g(2)
end

struct MyMix <: CompilationContext end

allow(ctx::MyMix, m::Module) = m == NoInliningAllowed

swap(e) = e
function swap(e::Expr)
    new = MacroTools.postwalk(e) do s
        isexpr(s, :call) || return s
        s.args[1] == Base.literal_pow || return s
        return Expr(:call, apply, Base.:(*), s.args[3:end]...)
    end
    return new
end

function transform(::MyMix, src)
    b = CodeInfoTools.Builder(src)
    for (v, st) in b
        b[v] = swap(st)
    end
    return CodeInfoTools.finish(b)
end

# JIT compile an entry and call.
fn = Mixtape.jit(f, Tuple{Int64}; ctx = MyMix())
display(fn(3))
display(fn(6))
@btime fn(6)

# Mixtape cached call.
Mixtape.@load_abi()
display(call(f, 3; ctx = MyMix()))
display(call(f, 6; ctx = MyMix()))
@btime call(f, 6; ctx = MyMix())

# Native.
f(5)
@btime f(5)

end # module


text:
# HACK: So Weave.jl has a submodule `WeavePlots` which is loaded using Requires.jl if Plots.jl is available.
# This means that if we want to overload methods in that submodule we need to wait until `Plots.jl` has been loaded.

# HACK
function Weave.WeavePlots.add_plots_figure(report::Weave.Report, plot::Plots.AnimatedGif, ext)
    chunk = report.cur_chunk
    full_name, rel_name = Weave.get_figname(report, chunk, ext = ext)

    # A `AnimatedGif` has been saved somewhere temporarily, so make a copy to `full_name`.
    cp(plot.filename, full_name; force = true)
    push!(report.figures, rel_name)
    report.fignum += 1
        return full_name
end

function Base.display(report::Weave.Report, m::MIME"text/plain", plot::Plots.AnimatedGif)
    Weave.WeavePlots.add_plots_figure(report, plot, ".gif")
end

max_stars_repo_name: staticfloat/TuringTutorials

max_issues_repo_name: staticfloat/TuringTutorials

max_forks_repo_name: staticfloat/TuringTutorials


text:
@testset "get_file_loc" begin
    str = "(x+y for x in X for y in Y if begin if true end end)"
    cst = CSTParser.parse(str)
    @test LanguageServer.get_file_loc(cst[2][5][1][1]) == (nothing, 20)
end


text:
module Day04

using ..ReTest, ..DocStringExtensions

import ..solve, ..PuzzleInfo, ..TEST_DATA_DIRECTORY

abstract type Day04PuzzleInfo <: PuzzleInfo end

"""
Day 4 part 1 puzzle information.

$(FIELDS)
"""
struct Part1PuzzleInfo <: Day04PuzzleInfo
    """Path to input data file."""
    datapath::String
end

"""
Day 4 part 2 puzzle information.

$(FIELDS)
"""
struct Part2PuzzleInfo <: Day04PuzzleInfo
    """Path to input data file."""
    datapath::String
end

"""
    $(FUNCTIONNAME)(input)

Read bingo game data from input stream `input`.

First line of input is assumed to be comma-delimited list of drawn (interger) numbers.

Subsequent lines corresponds to game boards, with each 5x5 board separated by a blank
new line (and separated by a blank new line from the draws), with each row of numbers in
each board separated by a new line and each number within each row separated by spaces.

Returns a tuple `(draws, boards)` with `draws` a one-dimensional integer array of the
numbers drawn in order, and boards a three dimensional integer array with first
dimension indexing over the different boards in the order the appear in `input`, and
second and third dimensions over the rows and columns within each board.
"""
function readbingodata(input::IO)
    # First line of input is comma-delimited integers corresponding to drawn numbers
    draws = [parse(Int, draw) for draw in split(readuntil(input, "\n\n"), ',')]
    boardstrings = []
    while !eof(input)
        push!(boardstrings, readuntil(input, "\n\n"))
    end
    boards = Array{Int}(undef, length(boardstrings), 5, 5)
    for (i, boardstring) in enumerate(boardstrings)
        boards[i, :, :] = reduce(
            vcat,
            [parse(Int, numstring) for numstring in split(boardline)]'
            for boardline in split(boardstring, '\n')
        )
    end
    draws, boards
end

"""
    $(FUNCTIONNAME)(marks)

Computes which of bingo boards with marked entries indicated by `marks` are winners.

The bit array `marks` is assumed to be of shape `(numboards, 5, 5)` with the first
dimension indexing over different bingo boards and the second and third dimensions the
rows and columns of each board. A board is defined as a winner if all entries in a
row or column are marked, that is the correspond entries in `marks` are set to 1.

A bit array is returned of length `numboards` with entries set to 1 if the board at the
corresponding index is a winner.
"""
function getbingowinners(marks::BitArray{3})
    (any(all(marks, dims=2), dims=3) .| any(all(marks, dims=3), dims=2))[:, 1, 1]
end

function solve(info::Part1PuzzleInfo)
    draws, boards = open(readbingodata, info.datapath)
    marks = falses(size(boards))
    for draw in draws
        marks[boards .== draw] .= true
        winners = getbingowinners(marks)
        if any(winners)
            @assert sum(winners) == 1 "Multiple simultaneous winners."
            winningboard = dropdims(boards[winners, :, :]; dims=1)
            winningmarks = dropdims(marks[winners, :, :]; dims=1)
            return sum(winningboard[.!winningmarks]) * draw
        end
    end
end

function solve(info::Part2PuzzleInfo)
    draws, boards = open(readbingodata, info.datapath)
    marks = falses(size(boards))
    local lasttowinindex
    for draw in draws
        marks[boards .== draw] .= true
        winners = getbingowinners(marks)
        if sum(winners) == size(boards, 1) - 1
            lasttowinindex = findfirst(.!winners)
        elseif all(winners)
            lasttowinboard = boards[lasttowinindex, :, :]
            lasttowinmarks = marks[lasttowinindex, :, :]
            return sum(lasttowinboard[.!lasttowinmarks]) * draw
        end
    end
end

@testset begin
    @test solve(Part1PuzzleInfo(joinpath(TEST_DATA_DIRECTORY, "day04.txt"))) == 4512
    @test solve(Part2PuzzleInfo(joinpath(TEST_DATA_DIRECTORY, "day04.txt"))) == 1924
end

end # module


text:
using DrWatson
@quickactivate
using ArgParse
using GenerativeAD
using StatsBase: fit!, predict, sample
using BSON

s = ArgParseSettings()
@add_arg_table! s begin
   "max_seed"
        required = true
        arg_type = Int
        help = "seed"
    "dataset"
        required = true
        arg_type = String
        help = "dataset"
    "contamination"
    	arg_type = Float64
    	help = "contamination rate of training data"
    	default = 0.0
end
parsed_args = parse_args(ARGS, s)
@unpack dataset, max_seed, contamination = parsed_args

modelname = "pidforest"
function set_params(data)
	D, N = size(data[1][1])
	if N > 100
		ms = 100
	else
		ms = max(25, N - mod(N, 50))
	end
	return (max_depth=10, n_trees=50, max_samples=ms, max_buckets=3, epsilon=0.1)
end

function fit(data, parameters)
	model = GenerativeAD.Models.PIDForest(Dict(pairs(parameters)))

	try
		global info, fit_t, _, _, _ = @timed fit!(model, data[1][1])
	catch e
		@info "Failed training due to \n$e"
		return (fit_t = NaN,), []
	end

	training_info = (
		fit_t = fit_t,
		model = nothing
		)

	training_info, [(x -> predict(model, x, pct=p), merge(parameters, Dict(:percentile => p))) for p in [25]]
end

function remove_constant_features(data)
	X = data[1][1]
	mask = (maximum(X, dims=2) .== minimum(X, dims=2))[:]
	if any(mask)
		@info "Removing $(sum(mask)) features with constant values."
		return Tuple((data[i][1][.~mask,:], data[i][2]) for i in 1:3)
	end
	data
end

try_counter = 0
max_tries = 10*max_seed
cont_string = (contamination == 0.0) ? "" : "_contamination-$contamination"
while try_counter < max_tries
    for seed in 1:max_seed
		savepath = datadir("experiments/tabular_clean_val_default/$(modelname)/$(dataset)/seed=$(seed)")
		mkpath(savepath)

		# get data
		data = GenerativeAD.load_data(dataset, seed=seed, contamination=contamination)
		data = remove_constant_features(data)
		parameters = set_params(data)

		if GenerativeAD.check_params(savepath, parameters)
			@info "Started training PIDForest$(parameters) on $(dataset):$(seed)"

			training_info, results = fit(data, parameters)
			save_entries = merge(training_info, (modelname = modelname, seed = seed, dataset = dataset, contamination = contamination))

			for result in results
				GenerativeAD.experiment(result..., data, savepath; save_entries...)
			end
			global try_counter = max_tries + 1
		else
			@info "Model already present, trying new hyperparameters..."
			global try_counter += 1
		end
	end
end
(try_counter == max_tries) ? (@info "Reached $(max_tries) tries, giving up.") : nothing


text:
@testset "Solver: LDL" begin
    Random.seed!(100)
    n = 50
    d = 0.7

    # Generate diffrent matrices with the same sparsity pattern
    A0_ = sprand(n, n, d)
    A1_ = deepcopy(A0_)
    A1_.nzval[1:10] .+= 1.0
    A0 = A0_ + A0_'
    A1 = A1_ + A1_'
    @test rank(A0) == n
    @test rank(A1) == n
    # Generate random vector
    b = rand(n)

    # QDLDL works
    F0 = qdldl(A0)
    x0 = deepcopy(b)
    QDLDL.solve!(F0, x0)
    @test norm(A0 * x0 - b, Inf) < 1e-8

    # The in-place QDLDL works on the same matrix A0
    G0 = ContactImplicitMPC.LDLSolver(A0, F0)
    ContactImplicitMPC.factorize!(G0, A0)
    x0 = deepcopy(b)
    QDLDL.solve!(G0.F, x0)
    @test norm(A0 * x0 - b, Inf) < 1e-8

    # The in-place QDLDL works on a different marix A1 but with the same sparsity pattern
    G1 = ContactImplicitMPC.LDLSolver(A0, F0)
    ContactImplicitMPC.factorize!(G0, A1)
    x0 = deepcopy(b)
    QDLDL.solve!(G0.F, x0)
    @test !(norm(A0 * x0 - b, Inf) < 1e-8)
    @test norm(A1 * x0 - b, Inf) < 1e-8
end


text:
using Pkg

Pkg.add(PackageSpec(; url="https://github.com/StructuralEquationModels/StructuralEquationModels.jl", rev = "devel"))


text:
## debug.jl - developer utilities, not exported to users

function find_bad(g)
    for i=1:length(g.tape)
        println("Evaliating $(i)th node $(g[i])")
        evaluate!(g, g[i])
    end
end

function load_espresso()
    for n in Base.names(Espresso, true) @eval import Espresso: $n end
end


text:
module GridWorlds

import REPL
import ReinforcementLearningBase as RLBase

include("navigation.jl")
include("abstract_grid_world.jl")
include("play.jl")
include("rlbase.jl")
include("envs/envs.jl")

end


text:
module XCompiler

# overloads
# ---------

import Core.Compiler:
    # types.jl
    InferenceParams,
    OptimizationParams,
    get_world_counter,
    get_inference_cache,
    lock_mi_inference,
    unlock_mi_inference,
    add_remark!,
    may_optimize,
    may_compress,
    may_discard_trees,
    verbose_stmt_info,
    # xcache.jl
    code_cache,
    get_inference_cache,
    cache_lookup

# usings
# ------

import Core:
    CodeInfo,
    MethodInstance,
    CodeInstance,
    MethodMatch,
    LineInfoNode,
    SimpleVector,
    Builtin,
    Typeof,
    svec

import Core.Compiler:
    AbstractInterpreter,
    NativeInterpreter,
    InferenceState,
    InferenceResult,
    OptimizationState,
    WorldRange,
    WorldView,
    MethodCallResult,
    VarTable,
    IRCode,
    to_tuple_type,
    _methods_by_ftype,
    specialize_method,
    inlining_enabled,
    typeinf, # entry
    typeinf_ext_toplevel # entry for native compilation

import Base:
    unwrap_unionall,
    rewrap_unionall,
    destructure_callex

const CC = Core.Compiler

# AbstractInterpreter interface
# =============================

abstract type XInterpreter <: AbstractInterpreter end

# XInterpreter API requirements

native(interp::XInterpreter) = throw(native)
cache_key(::XInterpreter)    = throw(cache_key)

# TODO allow customization

CC.InferenceParams(interp::XInterpreter)    = InferenceParams(native(interp))
CC.OptimizationParams(interp::XInterpreter) = OptimizationParams(native(interp))
CC.get_world_counter(interp::XInterpreter)  = get_world_counter(native(interp))

CC.lock_mi_inference(::XInterpreter,   ::MethodInstance) = nothing
CC.unlock_mi_inference(::XInterpreter, ::MethodInstance) = nothing

CC.add_remark!(interp::XInterpreter, sv, s) = add_remark!(native(interp), sv, s)

CC.may_optimize(interp::XInterpreter)      = may_optimize(native(interp))
CC.may_compress(interp::XInterpreter)      = may_compress(native(interp))
CC.may_discard_trees(interp::XInterpreter) = may_discard_trees(native(interp))
CC.verbose_stmt_info(interp::XInterpreter) = verbose_stmt_info(native(interp))

XInferenceParams(; ipo_constant_propagation::Bool        = true,
                   aggressive_constant_propagation::Bool = false,
                   unoptimize_throw_blocks::Bool         = true,
                   max_methods::Int                      = 3,
                   union_splitting::Int                  = 4,
                   apply_union_enum::Int                 = 8,
                   tupletype_depth::Int                  = 3,
                   tuple_splat::Int                      = 32,
                   __xconfigs...) =
    return InferenceParams(; ipo_constant_propagation,
                             aggressive_constant_propagation,
                             unoptimize_throw_blocks,
                             max_methods,
                             union_splitting,
                             apply_union_enum,
                             tupletype_depth,
                             tuple_splat,
                             )
XOptimizationParams(; inlining::Bool                = inlining_enabled(),
                      inline_cost_threshold::Int    = 100,
                      inline_nonleaf_penalty::Int   = 1000,
                      inline_tupleret_bonus::Int    = 250,
                      inline_error_path_cost::Int   = 20,
                      max_methods::Int              = 3,
                      tuple_splat::Int              = 32,
                      union_splitting::Int          = 4,
                      unoptimize_throw_blocks::Bool = true,
                      __xconfigs...) =
    return OptimizationParams(; inlining,
                                inline_cost_threshold,
                                inline_nonleaf_penalty,
                                inline_tupleret_bonus,
                                inline_error_path_cost,
                                max_methods,
                                tuple_splat,
                                union_splitting,
                                unoptimize_throw_blocks,
                                )
# # assert here that they create same objects as the original constructors
@assert XInferenceParams()    == InferenceParams()
@assert XOptimizationParams() == OptimizationParams()

# cache
# =====

# global
# ------

"""
    X_CODE_CACHE::$(typeof(X_CODE_CACHE))

Keeps `CodeInstance` associated with `mi::MethodInstace`, which is a customized compilation
result of `mi` performed by `XInterpreter`.
The cache is partitioned by identities of each `XInterpreter`, and thus running a pipeline
with different configurations will yeild a different cache and not be influenced by the
previous compilation.
This cache should be separated from the `NativeInterpreter`'s global cache, but currently
code cache can be created in many different points of compilation pipeline, and thus a
customized compilation will pollute the native cache.
"""
const X_CODE_CACHE = IdDict{UInt, IdDict{MethodInstance,CodeInstance}}()

function maybe_init_cache!(cache_key::UInt)
    haskey(X_CODE_CACHE, cache_key) && return
    X_CODE_CACHE[cache_key] = IdDict{MethodInstance,CodeInstance}()
end
__clear_cache!() = empty!(X_CODE_CACHE)

function CC.code_cache(interp::XInterpreter)
    cache = XGlobalCache(interp)
    worlds = WorldRange(get_world_counter(interp))
    return WorldView(cache, worlds)
end

struct XGlobalCache{Interp<:XInterpreter}
    interp::Interp
end

# cache existence for this `analyzer` is ensured on its construction
x_code_cache(interp::XInterpreter) = X_CODE_CACHE[cache_key(interp)]
x_code_cache(wvc::WorldView{XGlobalCache{Interp}}) where Interp<:XInterpreter = x_code_cache(wvc.cache.interp)

native_code_cache(interp::XInterpreter) = CC.code_cache(native(interp))
native_code_cache(wvc::WorldView{XGlobalCache{Interp}}) where Interp<:XInterpreter = native_code_cache(wvc.cache.interp)

CC.haskey(wvc::WorldView{XGlobalCache{Interp}}, mi::MethodInstance) where Interp<:XInterpreter =
    haskey(x_code_cache(wvc), mi)

function CC.get(wvc::WorldView{XGlobalCache{Interp}}, mi::MethodInstance, default) where Interp<:XInterpreter
    r = get(x_code_cache(wvc), mi, default)
    r !== default && return r
    return CC.get(native_code_cache(wvc), mi, default)
end

function CC.getindex(wvc::WorldView{XGlobalCache{Interp}}, mi::MethodInstance) where Interp<:XInterpreter
    r = CC.get(wvc, mi, nothing)
    r === nothing && throw(KeyError(mi))
    return r::CodeInstance
end

function CC.setindex!(wvc::WorldView{XGlobalCache{Interp}}, ci::CodeInstance, mi::MethodInstance) where Interp<:XInterpreter
    x_code_cache(wvc)[mi] = ci
    add_x_callback!(mi) # register the callback on invalidation
    return nothing
end

function add_x_callback!(linfo)
    if !isdefined(linfo, :callbacks)
        linfo.callbacks = Any[invalidate_x_cache!]
    else
        if !any(@nospecialize(cb)->cb===invalidate_x_cache!, linfo.callbacks)
            push!(linfo.callbacks, invalidate_x_cache!)
        end
    end
    return nothing
end

function invalidate_x_cache!(replaced, max_world, depth = 0)
    for cache in values(X_CODE_CACHE); delete!(cache, replaced); end

    if isdefined(replaced, :backedges)
        for mi in replaced.backedges
            mi = mi::MethodInstance
            if !any(cache->haskey(cache, mi), values(X_CODE_CACHE))
                continue # otherwise fall into infinite loop
            end
            invalidate_x_cache!(mi, max_world, depth+1)
        end
    end
    return nothing
end

# local
# -----

# to inspect local cache, we will just look for `get_inference_cache(native(interp))`
# and thus we won't create a global store to hold these caches

CC.get_inference_cache(interp::XInterpreter) = XLocalCache(interp)

struct XLocalCache
    interp::XInterpreter
end

CC.cache_lookup(linfo::MethodInstance, given_argtypes::Vector{Any}, inf_cache::XLocalCache) =
    return cache_lookup(linfo, given_argtypes, get_inference_cache(native(inf_cache.interp)))

CC.push!(inf_cache::XLocalCache, inf_result::InferenceResult) =
    return CC.push!(get_inference_cache(native(inf_cache.interp)), inf_result)

# entry
# =====

function with(@nospecialize(f), interp::XInterpreter)
    x_typeinf_ext_toplevel(mi::MethodInstance, world::UInt) =
        typeinf_ext_toplevel(interp, mi)

    try
        ccall(:jl_set_typeinf_func, Cvoid, (Any,), x_typeinf_ext_toplevel)
        return f()
    catch err
        rethrow(err)
    finally
        ccall(:jl_set_typeinf_func, Cvoid, (Any,), typeinf_ext_toplevel)
    end
end

# exports

export
    XInterpreter,
    native,
    cache_key,
    with

end # module XCompiler


text:
function bisect_right(A, p, r, v)
    i = p
    if p < r
        q = floor(Int, (p+r)/2)
        if v < A[q]
            i = bisect_right(A, p, q, v)
       	else
            i = bisect_right(A, q+1, r, v)
        end
    end
    return i
end


text:
# #############################################################################
# rainfarm.jl
# Authors:       J. von Hardenberg (ISAC-CNR, Italy)
#                E. Arnone (ISAC-CNR, Italy)
# #############################################################################
# Description
# ESMValTool diagnostic calling the RainFARM library written in Julia
# (by von Hardenberg, ISAC-CNR, Italy).
# RainFARM is a stochastic precipitation downscaling method, further adapted
# for climate downscaling.
#
# Required
# CDO
# Julia language: https://julialang.org
# RainFARM Julia library: https://github.com/jhardenberg/RainFARM.jl
#
# Optional
#
# Caveats
#
# Modification history
#    20190810-vonhardenberg_jost: rewritten in pure Julia, no R
#    20181210-vonhardenberg_jost: cleanup and using juliacall
#    20180508-arnone_enrico: Conversion to v2.0
#    20170908-arnone_enrico: 1st github version
#
# ############################################################################

import YAML
using RainFARM
using Printf

function provenance_record(infile)
    xprov = Dict( "ancestors" => infile,
        "authors" => ["vonhardenberg_jost", "arnone_enrico"],
        "references" => ["donofrio14jh", "rebora06jhm",
                         "terzago18nhess"],
        "projects" => ["c3s-magic"],
        "caption" => "RainFARM precipitation downscaling",
        "statistics" => ["other"],
        "realms" => ["atmos"],
        "themes" => ["phys"],
        "domains" => ["reg"]
    )
    return(xprov)
end

let
diag_scripts_dir = ENV["diag_scripts"]
include(joinpath(diag_scripts_dir, "shared/external.jl"))

settings = YAML.load_file(ARGS[1])

metadata = YAML.load_file(settings["input_files"][1])
climofiles = collect(keys(metadata))
climolist = metadata[climofiles[1]]
varname = climolist["short_name"]
diag_base = climolist["diagnostic"]

println(diag_base, ": starting routine")
println(diag_base, ": creating work and plot directories")
work_dir = settings["work_dir"]
run_dir = settings["run_dir"]
mkpath(work_dir)
mkpath(run_dir)
cd(run_dir)

# setup provenance file and list
provenance_file = joinpath(run_dir, "diagnostic_provenance.yml")
provenance = Dict()

# Reading parameters from the settings
nf = get(settings, "nf", 2)
slope = get(settings, "slope", 0.0)
kmin = get(settings, "kmin", 1)
nens = get(settings, "nens", 1)
weights_climo = get(settings, "weights_climo", "")
conserv_glob = get(settings, "conserv_glob", false)
conserv_smooth = get(settings, "conserv_smooth", true)
auxiliary_data_dir = get(settings, "auxiliary_data_dir", "")

if weights_climo isa Bool # Compatibility with old standard
    weights_climo = ""
end

# Conservation options
if (conserv_glob)
    println("Conserving global field")
elseif (conserv_smooth)
    println("Smooth conservation")
else
    println("Box conservation")
end

for (infile, value) in metadata
    (infilename, ) = splitext(basename(infile))
    outfilename = joinpath(work_dir, infilename * "_downscaled")

    println(diag_base, ": calling RainFARM for ", infilename)

    (pr, lon_mat, lat_mat) = read_netcdf2d(infile, varname)

    # Ensure grid is square and with even dims
    nmin = min(size(pr)[1], size(pr)[2])
    nmin = floor(Int, nmin / 2) * 2
    pr = pr[1:nmin, 1:nmin, :]
    if (ndims(lon_mat) == 1)
        lon_mat = lon_mat[1:nmin]
        lat_mat = lat_mat[1:nmin]
    else
        lon_mat = lon_mat[1:nmin, 1:nmin]
        lat_mat = lat_mat[1:nmin, 1:nmin]
    end

    (lon_f, lat_f) = lon_lat_fine(lon_mat, lat_mat, nf);

    # Automatic spectral slope
    if (slope == 0.)
        (fxp, ftp)=fft3d(pr)
        slope =fitslopex(fxp, kmin=kmin)
        println("Computed spatial spectral slope: ", slope)
    else
        println("Fixed spatial spectral slope: ", slope)
    end

    if weights_climo != ""
        if weights_climo[1] != '/'
            weights_climo = joinpath(auxiliary_data_dir, weights_climo)
        end
        println("Using external climatology for weights: ", weights_climo)
        fileweights = joinpath(work_dir, infilename * "_w.nc")

        ww = rfweights(weights_climo, infile, nf,
                       weightsfn = fileweights, varname = varname,
                       fsmooth = conserv_smooth)
    else
       ww = 1.
    end

    for iens=1:nens
        println("Realization ", iens)
        rd=rainfarm(pr, slope, nf, ww, fglob = conserv_glob,
                    fsmooth = conserv_smooth, verbose=true)
        fname=@sprintf("%s_%04d.nc", outfilename, iens);
        write_netcdf2d(fname, rd, lon_f, lat_f, varname, infile)
        xprov = provenance_record(infile)
        provenance[fname] = xprov
     end
end

# Write provenance file
create_yaml(provenance, provenance_file)
end

max_stars_repo_name: chrisdane/ESMValTool

max_issues_repo_name: chrisdane/ESMValTool

max_forks_repo_name: chrisdane/ESMValTool