text:
function add_dual_vars_in_dual_cones(dual_model::MOI.ModelLike, primal_model::MOI.ModelLike,
                                     primal_dual_map::PrimalDualMap{T}, dual_names::DualNames,
                                     con_types::Vector{Tuple{DataType, DataType}}) where T
    dual_obj_affine_terms = Dict{VI, T}()
    for (F, S) in con_types
        for ci in MOI.get(primal_model, MOI.ListOfConstraintIndices{F,S}()) # Constraints of type {F, S}
            # Add dual variable to dual cone
            # Fill a dual objective dictionary
            # Fill the primal_con_dual_var dictionary
            ci_dual = add_dual_variable(dual_model, primal_model, dual_names,
                                        primal_dual_map.primal_con_dual_var, dual_obj_affine_terms, ci)
            push_to_primal_con_dual_con!(primal_dual_map.primal_con_dual_con, ci, ci_dual)
            push_to_primal_con_constants!(primal_model, primal_dual_map.primal_con_constants, ci)
        end
    end
    return dual_obj_affine_terms
end

# Utils for primal_con_constants dict
function push_to_primal_con_constants!(primal_model::MOI.ModelLike, primal_con_constants::Dict{CI, Vector{T}},
                                      ci::CI{F, S}) where {T, F <: MOI.AbstractScalarFunction, S <: MOI.AbstractScalarSet}
    push!(primal_con_constants, ci => get_scalar_term(primal_model, ci))
    return
end

function push_to_primal_con_constants!(primal_model::MOI.ModelLike, primal_con_constants::Dict{CI, Vector{T}},
                                       ci::CI{F, S}) where {T, F <: MOI.AbstractVectorFunction, S <: MOI.AbstractVectorSet}
    return # No constants need to be passed to the DualOptimizer in this case, don't need to push zero to the dict
end

# Utils for primal_con_dual_con dict
function push_to_primal_con_dual_con!(primal_con_dual_con::Dict{CI, CI}, ci::CI, ci_dual::CI)
    push!(primal_con_dual_con, ci => ci_dual)
    return
end

function push_to_primal_con_dual_con!(primal_con_dual_con::Dict{CI, CI}, ci::CI, ci_dual::Nothing)
    return # Don't put in the dict a nothing value
end

# Utils for dual_obj_affine_terms dict
function push_to_dual_obj_aff_terms!(primal_model::MOI.ModelLike, dual_obj_affine_terms::Dict{VI, T}, vi::VI,
                                     ci::CI{F, S}, i::Int) where {T, F <: MOI.AbstractFunction, S <: MOI.AbstractSet}
    s = get_set(primal_model, ci)
    value = set_dot(i, s, T)*get_scalar_term(primal_model, i, ci)
    if !iszero(value) # If value is different than 0 add to the dictionary
        push!(dual_obj_affine_terms, vi => value)
    end
    return
end

function push_to_dual_obj_aff_terms!(primal_model::MOI.ModelLike, dual_obj_affine_terms::Dict{VI, T}, vi::VI,
                                     ci::CI{VVF, S}, i::Int) where {T, S <: MOI.AbstractSet}
    return # It is zero so don't push to the dual_obj_affine_terms
end

function add_dual_variable(
    dual_model::MOI.ModelLike, primal_model::MOI.ModelLike,
    dual_names::DualNames, primal_con_dual_var::Dict{CI, Vector{VI}},
    dual_obj_affine_terms::Dict{VI, T}, ci::CI{F, S}
) where {T, F <: MOI.AbstractFunction, S <: MOI.AbstractSet}

    vis, con_index = add_dual_cone_constraint(dual_model, primal_model, ci)
    push!(primal_con_dual_var, ci => vis) # Add the map of the added dual variable to the relationated constraint
    # Get constraint name
    ci_name = MOI.get(primal_model, MOI.ConstraintName(), ci)
    # Add each vi to the dictionary
    for (i, vi) in enumerate(vis)
        push_to_dual_obj_aff_terms!(primal_model, dual_obj_affine_terms, vi, ci, i)
        if !is_empty(dual_names)
            set_dual_variable_name(dual_model, vi, i, ci_name,
                                   dual_names.dual_variable_name_prefix)
        end
    end
    return con_index
end

function set_dual_variable_name(dual_model::MOI.ModelLike, vi::VI, i::Int, ci_name::String, prefix::String)
    MOI.set(dual_model, MOI.VariableName(), vi, prefix*ci_name*"_$i")
    return
end

function add_primal_parameter_vars(dual_model::MOI.ModelLike,
    primal_model::MOI.ModelLike, primal_dual_map::PrimalDualMap{T},
    dual_names::DualNames, variable_parameters::Vector{VI},
    primal_objective, ignore_objective::Bool) where T
    # if objective is ignored we only need parameters that appear in the
    # quadratic objective
    if ignore_objective
        # only crossed terms (parameter times primal variable) of the objective
        # are required
        added = Set{VI}()
        for vec in values(primal_objective.quad_cross_parameters)
            for term in vec
                ind = term.variable_index
                if ind in added
                    # do nothing
                else
                    push!(added, ind)
                    vi = MOI.add_variable(dual_model)
                    push_to_primal_parameter!(primal_dual_map.primal_parameter, ind, vi)
                    # set name
                    if !is_empty(dual_names)
                        vi_name = MOI.get(primal_model, MOI.VariableName(), ind)
                        set_parameter_variable_name(dual_model, vi, vi_name, dual_names)
                    end
                end
            end
        end
    elseif length(variable_parameters) > 0
        vis = MOI.add_variables(dual_model, length(variable_parameters))
        for i in eachindex(vis)
            push_to_primal_parameter!(primal_dual_map.primal_parameter,
                variable_parameters[i], vis[i])
            if !is_empty(dual_names)
                vi_name = MOI.get(primal_model, MOI.VariableName(), variable_parameters[i])
                set_parameter_variable_name(dual_model, vis[i], vi_name, dual_names)
            end
        end
    end
    return
end

# Save mapping between primal parameter and dual parameter
function push_to_primal_parameter!(primal_parameter::Dict{VI, VI}, vi::VI, vi_dual::VI)
    push!(primal_parameter, vi => vi_dual)
    return
end

# Add name to parameter variable
function set_parameter_variable_name(dual_model::MOI.ModelLike, vi::VI, vi_name::String, dual_names)
    prefix = dual_names.parameter_name_prefix == "" ? "param_" : dual_names.parameter_name_prefix
    MOI.set(dual_model, MOI.VariableName(), vi, prefix*vi_name)
    return
end

function add_quadratic_slack_vars(dual_model::MOI.ModelLike,
    primal_model::MOI.ModelLike, primal_dual_map::PrimalDualMap{T},
    dual_names::DualNames, variable_parameters::Vector{VI},
    primal_objective, ignore_objective::Bool) where T
    # only crossed terms (parameter times primal variable) of the objective
    # are required
    added = Set{VI}()
    for term in primal_objective.obj.quadratic_terms
        for ind in [term.variable_index_1, term.variable_index_2]
            if ind in added
                #do nothing
            else
                push!(added, ind)
                vi = MOI.add_variable(dual_model)
                push_to_quad_slack!(primal_dual_map.primal_var_dual_quad_slack, ind, vi)
                # set name
                if !is_empty(dual_names)
                    vi_name = MOI.get(primal_model, MOI.VariableName(), ind)
                    set_quad_slack_name(dual_model, vi, vi_name, dual_names)
                end
            end
        end
    end
    return
end

# Save mapping between primal variable and dual quadratic slack
function push_to_quad_slack!(dual_quad_slack::Dict{VI, VI}, vi::VI, vi_dual::VI)
    push!(dual_quad_slack, vi => vi_dual)
    return
end

# set name for dual quadratic slack
function set_quad_slack_name(dual_model::MOI.ModelLike, vi::VI, vi_name::String, dual_names)
    prefix = dual_names.quadratic_slack_name_prefix == "" ? "quadslack_" : dual_names.quadratic_slack_name_prefix
    MOI.set(dual_model, MOI.VariableName(), vi, prefix*vi_name)
    return
end


text:
using DZOptimization: normalize!
using LinearAlgebra: cross
using ProgressMeter

push!(LOAD_PATH, @__DIR__)
using PCREO

function adjacent_facets(facets::Vector{Vector{Int}})
    result = Tuple{Int,Int}[]
    for i = 1 : length(facets) - 1
        for j = i+1 : length(facets)
            common_vertices = intersect(facets[i], facets[j])
            if length(common_vertices) >= 2
                @assert length(common_vertices) == 2
                push!(result, (i, j))
            end
        end
    end
    return result
end

function valence_table(facets::Vector{Vector{Int}})
    n = 0
    for facet in facets
        for vertex in facet
            @assert vertex >= 1
            n = max(n, vertex)
        end
    end
    result = zeros(Int, n)
    for facet in facets
        @simd ivdep for vertex in facet
            @inbounds result[vertex] += 1
        end
    end
    return result
end

function normal_vector(points::Vector{Vector{T}}) where {T}
    result = zeros(T, length(first(points)))
    for i = 1 : length(points) - 2
        for j = i+1 : length(points) - 1
            for k = j+1 : length(points)
                normal = cross(points[j] - points[i], points[k] - points[i])
                positive = all(signbit, normal' * p for p in points)
                negative = all(!signbit, normal' * p for p in points)
                @assert xor(positive, negative)
                if positive
                    result += normal
                else
                    result -= normal
                end
            end
        end
    end
    return normalize!(result)
end

function main()
    for dirname in readdir(PCREO_DATABASE_DIRECTORY)
        graphpath = joinpath(PCREO_GRAPH_DIRECTORY, dirname * ".g6")
        if isfile(graphpath)
            if countlines(graphpath) > 1
                println(dirname)
                dirpath = joinpath(PCREO_DATABASE_DIRECTORY, dirname)
                for filename in readdir(dirpath)
                    filepath = joinpath(dirpath, filename)
                    record = PCREORecord(filepath)
                    dot_products = Float64[]
                    for (i, j) in adjacent_facets(record.facets)
                        i_points = [record.points[:,v]
                                    for v in record.facets[i]]
                        j_points = [record.points[:,v]
                                    for v in record.facets[j]]
                        i_normal = normal_vector(i_points)
                        j_normal = normal_vector(j_points)
                        push!(dot_products, 1.0 - i_normal' * j_normal)
                    end
                    if minimum(dot_products) < 1.0e-12
                        mv(filepath, joinpath(
                            PCREO_FACET_ERROR_DIRECTORY, filename))
                    end
                end
            end
        else
            println("WARNING: ", graphpath, " does not exist.")
        end
    end
end

main()

ext: jl


text:
function NotInferenceDontLookHere.abstract_eval_ssavalue(s::SSAValue, src::IRCode)
    src.types[s.id]
end


text:
module Sounds

using CSFML, CSFML.LibCSFML
using FFTW

export AbstractSound
export SoundObject

export Music
export Sound
export SoundBuffer

export duration
export getsamples
export getstatus
export getbuffer
export islooping
export ispaused
export isplaying
export isstopped
export loop!
export nchannels
export nsamples
export pause!
export pitch
export pitch!
export play!
export samplepos
export samplerate
export stop!
export timepos
export timepos!
export volume
export volume!

export getprops
export showprops

abstract type SoundObject{T} end
abstract type AbstractSound{T} <: SoundObject{T} end

function Base.unsafe_convert(::Type{Ptr{T}}, x::SoundObject{T}) where {T}
    return getfield(x, :ptr)
end

include("utils.jl")
include("methods.jl")
include("soundbuffer.jl")
include("sound.jl")
include("music.jl")

end # Sound


text:
doc"""
    Uniform(a,b)

The *continuous uniform distribution* over an interval $[a, b]$ has probability density function

$f(x; a, b) = \frac{1}{b - a}, \quad a \le x \le b$

```julia
Uniform()        # Uniform distribution over [0, 1]
Uniform(a, b)    # Uniform distribution over [a, b]

params(d)        # Get the parameters, i.e. (a, b)
minimum(d)       # Get the lower bound, i.e. a
maximum(d)       # Get the upper bound, i.e. b
location(d)      # Get the location parameter, i.e. a
scale(d)         # Get the scale parameter, i.e. b - a
```

External links

* [Uniform distribution (continuous) on Wikipedia](http://en.wikipedia.org/wiki/Uniform_distribution_(continuous))

"""
immutable Uniform <: ContinuousUnivariateDistribution
    a::Float64
    b::Float64

    Uniform(a::Real, b::Real) = (@check_args(Uniform, a < b); new(a, b))
    Uniform() = new(0.0, 1.0)
end

@distr_support Uniform d.a d.b

#### Parameters

params(d::Uniform) = (d.a, d.b)

location(d::Uniform) = d.a
scale(d::Uniform) = d.b - d.a

#### Statistics

mean(d::Uniform) = middle(d.a, d.b)
median(d::Uniform) = mean(d)
mode(d::Uniform) = mean(d)
modes(d::Uniform) = Float64[]

var(d::Uniform) = (w = d.b - d.a; w^2 / 12.0)

skewness(d::Uniform) = 0.0
kurtosis(d::Uniform) = -1.2

entropy(d::Uniform) = log(d.b - d.a)

#### Evaluation

pdf(d::Uniform, x::Float64) = insupport(d, x) ? 1.0 / (d.b - d.a) : 0.0
logpdf(d::Uniform, x::Float64) = insupport(d, x) ? -log(d.b - d.a) : -Inf

function cdf(d::Uniform, x::Float64)
    (a, b) = params(d)
    x <= a ? 0.0 :
    x >= d.b ? 1.0 : (x - a) / (b - a)
end

function ccdf(d::Uniform, x::Float64)
    (a, b) = params(d)
    x <= a ? 1.0 :
    x >= d.b ? 0.0 : (b - x) / (b - a)
end

quantile(d::Uniform, p::Float64) = d.a + p * (d.b - d.a)
cquantile(d::Uniform, p::Float64) = d.b + p * (d.a - d.b)

function mgf(d::Uniform, t::Real)
    (a, b) = params(d)
    u = 0.5 * (b - a) * t
    u == zero(u) && return one(u)
    v = 0.5 * (a + b) *t
    exp(v) * (sinh(u) / u)
end

function cf(d::Uniform, t::Real)
    (a, b) = params(d)
    u = 0.5 * (b - a) * t
    u == zero(u) && return complex(one(u))
    v = 0.5 * (a + b) * t
    cis(v) * (sin(u) / u)
end

#### Evaluation

rand(d::Uniform) = d.a + (d.b - d.a) * rand()

#### Fitting

function fit_mle{T<:Real}(::Type{Uniform}, x::AbstractArray{T})
    if isempty(x)
        throw(ArgumentError("x cannot be empty."))
    end

    xmin = xmax = x[1]
    for i = 2:length(x)
        xi = x[i]
        if xi < xmin
            xmin = xi
        elseif xi > xmax
            xmax = xi
        end
    end

    Uniform(xmin, xmax)
end


text:
using CompositionalNetworks
using ConstraintDomains
using Test

CN = CompositionalNetworks

@testset "CompositionalNetworks.jl" begin
    include("layers.jl")
    include("icn.jl")
end


text:
@params mutable struct Volume{T, dim} <: AbstractFunction{T}
    problem::StiffnessTopOptProblem{dim, T}
    solver::AbstractFEASolver
    cellvolumes::AbstractVector{T}
    grad::AbstractVector{T}
    total_volume::T
    fixed_volume::T
    tracing::Bool
	topopt_trace::TopOptTrace{T}
    fraction::Bool
    fevals::Int
    maxfevals::Int
end
Base.show(::IO, ::MIME{Symbol("text/plain")}, ::Volume) = println("TopOpt volume (fraction) function")
Nonconvex.getdim(::Volume) = 1
@inline function Base.getproperty(vf::Volume, f::Symbol)
    f === :reuse && return false
    return getfield(vf, f)
end
@inline function Base.setproperty!(vf::Volume, f::Symbol, v)
    f === :reuse && return false
    return setfield!(vf, f, v)
end

function project(f::Volume, V, x)
    cellvolumes = f.cellvolumes
    if f.fraction
        V = V * f.total_volume
    end
    inds = sortperm(x, rev=true)
    total = zero(V)
    i = 0
    while i <= length(inds)
        i += 1
        ind = inds[i]
        _total = total + cellvolumes[ind]
        _total >= V && break
        total = _total
    end
    x = zeros(eltype(x), length(x))
    x[inds[1:i]] .= 1
    return x
end

function Volume(problem::StiffnessTopOptProblem{dim, T}, solver::AbstractFEASolver, ::Type{TI} = Int; fraction = true, tracing = true, maxfevals = 10^8) where {dim, T, TI}
    dh = problem.ch.dh
    varind = problem.varind
    black = problem.black
    white = problem.white
    vars = solver.vars
    cellvolumes = solver.elementinfo.cellvolumes
    grad = zeros(T, length(vars))
    for (i, cell) in enumerate(CellIterator(dh))
        if !(black[i]) && !(white[i])
            grad[varind[i]] = cellvolumes[i]
        end
    end
    total_volume = sum(cellvolumes)
    fixed_volume = dot(black, cellvolumes)
    if fraction
        grad ./= total_volume
    end
    return Volume(problem, solver, cellvolumes, grad, total_volume, fixed_volume, tracing, TopOptTrace{T, TI}(), fraction, 0, maxfevals)
end
function (v::Volume{T})(x, grad = nothing) where {T}
    varind = v.problem.varind
    black = v.problem.black
    white = v.problem.white
    cellvolumes = v.cellvolumes
    total_volume = v.total_volume
    fixed_volume = v.fixed_volume
    fraction = v.fraction
    v.fevals += 1

    tracing = v.tracing
    topopt_trace = v.topopt_trace
    dh = v.problem.ch.dh
    xmin = v.solver.xmin

    vol = compute_volume(cellvolumes, x, fixed_volume, varind, black, white)

    constrval = fraction ? vol / total_volume : vol
    if grad !== nothing
        grad .= v.grad
    end
    if tracing
        push!(topopt_trace.v_hist, vol/total_volume)
    end

    return constrval
end
function ChainRulesCore.rrule(vol::Volume, x)
    grad = similar(vol.grad)
    return vol(x, grad), Δ -> (nothing, Δ * grad)
end

function compute_volume(cellvolumes::Vector, x, fixed_volume, varind, black, white)
    vol = fixed_volume
    for i in 1:length(cellvolumes)
        if !(black[i]) && !(white[i])
            #vol += density(x[varind[i]], xmin)*cellvolumes[i]
            vol += x[varind[i]]*cellvolumes[i]
        end
    end
    return vol
end


text:
immutable SVector{S, T} <: StaticVector{T}
    data::NTuple{S, T}

    function SVector(x::NTuple{S,T})
        new(x)
    end

    function SVector(x::NTuple{S})
        new(convert_ntuple(T, x))
    end
end

@inline (::Type{SVector}){S}(x::NTuple{S}) = SVector{S}(x)
@inline (::Type{SVector{S}}){S, T}(x::NTuple{S,T}) = SVector{S,T}(x)
@inline (::Type{SVector{S}}){S, T <: Tuple}(x::T) = SVector{S,promote_tuple_eltype(T)}(x)

# conversion from AbstractVector / AbstractArray (better inference than default)
#@inline convert{S,T}(::Type{SVector{S}}, a::AbstractArray{T}) = SVector{S,T}((a...))

# Some more advanced constructor-like functions
@inline zeros{N}(::Type{SVector{N}}) = zeros(SVector{N,Float64})
@inline ones{N}(::Type{SVector{N}}) = ones(SVector{N,Float64})

#####################
## SVector methods ##
#####################

@pure size{S}(::Union{SVector{S},Type{SVector{S}}}) = (S, )
@pure size{S,T}(::Type{SVector{S,T}}) = (S,)

@propagate_inbounds function getindex(v::SVector, i::Integer)
    v.data[i]
end

@inline Tuple(v::SVector) = v.data

@inline function Base.unsafe_convert{N,T}(::Type{Ptr{T}}, v::SVector{N,T})
    Base.unsafe_convert(Ptr{T}, Base.data_pointer_from_objref(v))
end

macro SVector(ex)
    if isa(ex, Expr) && ex.head == :vect
        return esc(Expr(:call, SVector{length(ex.args)}, Expr(:tuple, ex.args...)))
    elseif isa(ex, Expr) && ex.head == :ref
        return esc(Expr(:call, Expr(:curly, :SVector, length(ex.args[2:end]), ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
    elseif isa(ex, Expr) && ex.head == :comprehension
        if length(ex.args) != 1 || !isa(ex.args[1], Expr) || ex.args[1].head != :generator
            error("Expected generator in comprehension, e.g. [f(i) for i = 1:3]")
        end
        ex = ex.args[1]
        if length(ex.args) != 2
            error("Use a one-dimensional comprehension for @SVector")
        end

        rng = eval(current_module(), ex.args[2].args[2])
        f = gensym()
        f_expr = :($f = ($(ex.args[2].args[1]) -> $(ex.args[1])))
        exprs = [:($f($j)) for j in rng]

        return quote
            $(Expr(:meta, :inline))
            $(esc(f_expr))
            $(esc(Expr(:call, Expr(:curly, :SVector, length(rng)), Expr(:tuple, exprs...))))
        end
    elseif isa(ex, Expr) && ex.head == :typed_comprehension
        if length(ex.args) != 2 || !isa(ex.args[2], Expr) || ex.args[2].head != :generator
            error("Expected generator in typed comprehension, e.g. Float64[f(i) for i = 1:3]")
        end
        T = ex.args[1]
        ex = ex.args[2]
        if length(ex.args) != 2
            error("Use a one-dimensional comprehension for @SVector")
        end

        rng = eval(current_module(), ex.args[2].args[2])
        f = gensym()
        f_expr = :($f = ($(ex.args[2].args[1]) -> $(ex.args[1])))
        exprs = [:($f($j)) for j in rng]

        return quote
            $(Expr(:meta, :inline))
            $(esc(f_expr))
            $(esc(Expr(:call, Expr(:curly, :SVector, length(rng), T), Expr(:tuple, exprs...))))
        end
    elseif isa(ex, Expr) && ex.head == :call
        if ex.args[1] == :zeros || ex.args[1] == :ones || ex.args[1] == :rand ||ex.args[1] == :randn
            if length(ex.args) == 2
                return quote
                    $(Expr(:meta, :inline))
                    $(esc(ex.args[1]))(SVector{$(esc(ex.args[2]))})
                end
            elseif length(ex.args) == 3
                return quote
                    $(Expr(:meta, :inline))
                    $(esc(ex.args[1]))(SVector{$(esc(ex.args[3])), $(esc(ex.args[2]))})
                end
            else
                error("@SVector expected a 1-dimensional array expression")
            end
        elseif ex.args[1] == :fill
            if length(ex.args) == 3
                return quote
                    $(Expr(:meta, :inline))
                    $(esc(ex.args[1]))($(esc(ex.args[2])), SVector{$(esc(ex.args[3]))})
                end
            else
                error("@SVector expected a 1-dimensional array expression")
            end
        else
            error("@SVector only supports the zeros(), ones(), fill(), rand() and randn() functions.")
        end
    else # TODO Expr(:call, :zeros), Expr(:call, :ones), Expr(:call, :eye) ?
        error("Use @SVector [a,b,c], @SVector Type[a,b,c] or a comprehension like [f(i) for i = i_min:i_max]")
    end
end


text:
const BBox = Rect2D{Float32}

const Optional{T} = Union{Nothing, T}

struct RectSides{T<:Real}
    left::T
    right::T
    bottom::T
    top::T
end

abstract type Side end

struct Left <: Side end
struct Right <: Side end
struct Top <: Side end
struct Bottom <: Side end
# for protrusion content:
struct TopLeft <: Side end
struct TopRight <: Side end
struct BottomLeft <: Side end
struct BottomRight <: Side end

struct Inner <: Side end
struct Outer <: Side end

abstract type GridDir end
struct Col <: GridDir end
struct Row <: GridDir end

struct RowCols{T <: Union{Number, Vector{Float64}}}
    lefts::T
    rights::T
    tops::T
    bottoms::T
end

"""
Used to specify space that is occupied in a grid. Like 1:1|1:1 for the first square,
or 2:3|1:4 for a rect over the 2nd and 3rd row and the first four columns.
"""
struct Span
    rows::UnitRange{Int64}
    cols::UnitRange{Int64}
end

"""
An object that can be aligned that also specifies how much space it occupies in
a grid via its span.
"""
mutable struct GridContent{G, T} # G should be GridLayout but can't be used before definition
    parent::Optional{G}
    al::T
    sp::Span
    side::Side
    needs_update::Node{Bool}
    protrusions_handle::Optional{Function}
    computedsize_handle::Optional{Function}
end

abstract type AlignMode end

struct Inside <: AlignMode end
struct Outside <: AlignMode
    padding::RectSides{Float32}
end
Outside() = Outside(0f0)
Outside(padding::Real) = Outside(RectSides{Float32}(padding, padding, padding, padding))
Outside(left::Real, right::Real, bottom::Real, top::Real) =
    Outside(RectSides{Float32}(left, right, bottom, top))

abstract type ContentSize end
abstract type GapSize <: ContentSize end

struct Auto <: ContentSize
    trydetermine::Bool # false for determinable size content that should be ignored
    ratio::Float64 # float ratio in case it's not determinable

    Auto(trydetermine::Bool = true, ratio::Real = 1.0) = new(trydetermine, ratio)
end
Auto(ratio::Real) = Auto(true, ratio)

struct Fixed <: GapSize
    x::Float64
end
struct Relative <: GapSize
    x::Float64
end
struct Aspect <: ContentSize
    index::Int
    ratio::Float64
end

mutable struct LayoutNodes{T, G} # G again GridLayout
    suggestedbbox::Node{BBox}
    protrusions::Node{RectSides{Float32}}
    computedsize::Node{NTuple{2, Optional{Float32}}}
    autosize::Node{NTuple{2, Optional{Float32}}}
    computedbbox::Node{BBox}
    gridcontent::Optional{GridContent{G, T}} # the connecting link to the gridlayout
end

mutable struct GridLayout
    content::Vector{GridContent}
    nrows::Int
    ncols::Int
    rowsizes::Vector{ContentSize}
    colsizes::Vector{ContentSize}
    addedrowgaps::Vector{GapSize}
    addedcolgaps::Vector{GapSize}
    alignmode::AlignMode
    equalprotrusiongaps::Tuple{Bool, Bool}
    needs_update::Node{Bool}
    block_updates::Bool
    layoutnodes::LayoutNodes
    attributes::Attributes
    _update_func_handle::Optional{Function} # stores a reference to the result of on(obs)

    function GridLayout(
        content, nrows, ncols, rowsizes, colsizes,
        addedrowgaps, addedcolgaps, alignmode, equalprotrusiongaps, needs_update,
        layoutnodes, attributes)

        gl = new(content, nrows, ncols, rowsizes, colsizes,
            addedrowgaps, addedcolgaps, alignmode, equalprotrusiongaps,
            needs_update, false, layoutnodes, attributes, nothing)

        validategridlayout(gl)

        # attach_parent!(gl, parent)

        # on(needs_update) do update
        #     request_update(gl)
        # end

        gl
    end
end

struct AxisAspect
    aspect::Float32
end

struct DataAspect end

abstract type Ticks end

struct AutoLinearTicks <: Ticks
    idealtickdistance::Float32
end

struct ManualTicks <: Ticks
    values::Vector{Float32}
    labels::Vector{String}
end

struct AxisContent{T}
    content::T
    attributes::Attributes
end

mutable struct LineAxis
    parent::Scene
    protrusion::Node{Float32}
    attributes::Attributes
    decorations::Dict{Symbol, Any}
    tickpositions::Node{Vector{Point2f0}}
    tickvalues::Node{Vector{Float32}}
    ticklabels::Node{Vector{String}}
end

abstract type LObject end

mutable struct LAxis <: AbstractPlotting.AbstractScene
    parent::Scene
    scene::Scene
    plots::Vector{AxisContent}
    xaxislinks::Vector{LAxis}
    yaxislinks::Vector{LAxis}
    limits::Node{BBox}
    layoutnodes::LayoutNodes
    needs_update::Node{Bool}
    attributes::Attributes
    block_limit_linking::Node{Bool}
    decorations::Dict{Symbol, Any}
end

mutable struct LColorbar <: LObject
    parent::Scene
    scene::Scene
    layoutnodes::LayoutNodes
    attributes::Attributes
    decorations::Dict{Symbol, Any}
end

mutable struct LText <: LObject
    parent::Scene
    layoutnodes::LayoutNodes
    text::AbstractPlotting.Text
    attributes::Attributes
end

mutable struct LRect <: LObject
    parent::Scene
    layoutnodes::LayoutNodes
    rect::AbstractPlotting.Poly
    attributes::Attributes
end

struct LSlider <: LObject
    scene::Scene
    layoutnodes::LayoutNodes
    attributes::Attributes
    decorations::Dict{Symbol, Any}
end

struct LButton <: LObject
    scene::Scene
    layoutnodes::LayoutNodes
    attributes::Attributes
    decorations::Dict{Symbol, Any}
end

struct LToggle <: LObject
    scene::Scene
    layoutnodes::LayoutNodes
    attributes::Attributes
    decorations::Dict{Symbol, Any}
end

abstract type LegendElement end

struct LineElement <: LegendElement
    attributes::Attributes
end

struct MarkerElement <: LegendElement
    attributes::Attributes
end

struct PolyElement <: LegendElement
    attributes::Attributes
end

struct LegendEntry
    elements::Vector{LegendElement}
    attributes::Attributes
end

struct LLegend <: LObject
    scene::Scene
    entries::Node{Vector{LegendEntry}}
    layoutnodes::LayoutNodes
    attributes::Attributes
    decorations::Dict{Symbol, Any}
    entrytexts::Vector{LText}
    entryplots::Vector{Vector{AbstractPlot}}
end

const Indexables = Union{UnitRange, Int, Colon}


text:
"""
    function generate_doubles_tournaments(
        Grandslam::Bool = true,
        ATPNitto::Bool = true,
        ATP1000::Bool = true,
        ATP500::Bool = true,
        ATP250::Bool = true,
        ATPChallenger::Bool = true,
        ITFWorldTennisTour::Bool = true
    )::Vector{Tournament}

Generates an array of tournaments in a twelve month season.

Arguments
=========
- `Grandslam`:
    whether or not to include Grandslam tournaments.
- `ATPNitto`
    whether or not to include the ATP Nitto tournament.
- `ATP1000`
    whether or not to include the ATP 1000 tournament.
- `ATP500`
    whether or not to include the ATP 500 tournament.
- `ATP250`
    whether or not to include the ATP 250 tournament.
- `ATPChallenger`
    whether or not to include the ATP Challenger tournament.
- `ITFWorldTennisTour`
    whether or not to include the ITF World Tennis Tour.
"""

function generate_doubles_tournaments(
    Grandslam::Bool = true,
    ATPNitto::Bool = true,
    ATP1000::Bool = true,
    ATP500::Bool = true,
    ATP250::Bool = true,
    ATPChallenger::Bool = true,
    ITFWorldTennisTour::Bool = true
)::Vector{Tournament}
    tournaments = Vector{Tournament}([])

    if ATPNitto == true
        append!(
            tournaments,
            [
                Tournament(
                    name = "Nitto Finals",
                    date = Date(2018, 11, 11),
                    type = "ATPNitto",
                    drawsize = 8
                )
            ]
        )
    end

    if Grandslam == true
        append!(
            tournaments,
            [
                Tournament(
                    name = "Australian Open",
                    date = Date(2018, 1, 15),
                    type = "Grandslam",
                    drawsize = 64
                ),Tournament(
                    name = "Roland Garros",
                    date = Date(2018, 5, 27),
                    type = "Grandslam",
                    drawsize = 64
                ),Tournament(
                    name = "Wimbledon",
                    date = Date(2018, 7, 2),
                    type = "Grandslam",
                    drawsize = 64
                ),Tournament(
                    name = "US Open",
                    date = Date(2018, 8, 27),
                    type = "Grandslam",
                    drawsize = 64
                )
            ]
        )
    end

    if ATP1000 == true
        append!(
            tournaments,
            [
                Tournament(
                    name = "Indian Wells Masters",
                    date = Date(2018, 3, 9),
                    type = "ATP1000",
                    drawsize = 32
                ),Tournament(
                    name = "Miami Open",
                    date = Date(2018, 3, 23),
                    type = "ATP1000",
                    drawsize = 32
                ),Tournament(
                    name = "Monte-Carlo Masters",
                    date = Date(2018, 4, 13),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                ),Tournament(
                    name = "Madrid Open",
                    date = Date(2018, 5, 4),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                ),Tournament(
                    name = "Italian Open",
                    date = Date(2018, 5, 11),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                ),Tournament(
                    name = "Canadian Open",
                    date = Date(2018, 8, 10),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                ),Tournament(
                    name = "Cincinnati Masters",
                    date = Date(2018, 8, 17),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                ),Tournament(
                    name = "Shanghai Masters",
                    date = Date(2018, 10, 12),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                ),Tournament(
                    name = "Paris Masters",
                    date = Date(2018, 11, 2),
                    type = "ATP1000",
                    drawsize = 32 # not accurate | reality - 24
                )
            ]
        )
    end

    if ATP500 == true
        append!(
            tournaments,
            [
                Tournament(
                    name = "Rotterdam Open",
                    date = Date(2018, 2, 9),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Rio Open",
                    date = Date(2018, 2, 16),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Dubai Tennis Championships",
                    date = Date(2018, 2, 23),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Mexican Open",
                    date = Date(2018, 2, 23),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Barcelona Open",
                    date = Date(2018, 4, 20),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Queen's Club Championships",
                    date = Date(2018, 6, 15),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Halle Open",
                    date = Date(2018, 6, 15),
                    type = "ATP500",
                    drawsize = 32
                ),Tournament(
                    name = "German Open",
                    date = Date(2018, 7, 27),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Washington Open",
                    date = Date(2018, 8, 3),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "China Open",
                    date = Date(2018, 10, 5),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Japan Open",
                    date = Date(2018, 10, 5),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Vienna Open",
                    date = Date(2018, 10, 19),
                    type = "ATP500",
                    drawsize = 16
                ),Tournament(
                    name = "Swiss Indoors",
                    date = Date(2018, 10, 26),
                    type = "ATP500",
                    drawsize = 16
                ),
            ]
        )
    end

    if ATP250 == true
        append!(
            tournaments,
            [
                Tournament(
                    name = "Brisbane International",
                    date = Date(2018, 1, 5),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Maharashtra Open",
                    date = Date(2018, 1, 5),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Qatar Open",
                    date = Date(2018, 1, 5),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Auckland Open",
                    date = Date(2018, 1, 12),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Sydney International",
                    date = Date(2018, 1, 12),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Open Sud de France",
                    date = Date(2018, 2, 2),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Brasil Open",
                    date = Date(2018, 2, 9),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Delray Beach Open",
                    date = Date(2018, 2, 16),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Open 13",
                    date = Date(2018, 2, 16),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Argentina Open",
                    date = Date(2018, 2, 23),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Grand Prix Hassan II",
                    date = Date(2018, 4, 6),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "US Men's Clay Court Championship",
                    date = Date(2018, 4, 6),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Bavaria Open",
                    date = Date(2018, 4, 27),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Estoril Open",
                    date = Date(2018, 4, 27),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Geneva Open",
                    date = Date(2018, 5, 19),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Rosmalen Open",
                    date = Date(2018, 6, 8),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Stuttgart Open",
                    date = Date(2018, 6, 8),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Eastbourne International",
                    date = Date(2018, 6, 21),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Mallorca Open",
                    date = Date(2018, 6, 19),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Hall of Fame Open",
                    date = Date(2018, 7, 13),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Swedish Open",
                    date = Date(2018, 7, 20),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Croatia Open",
                    date = Date(2018, 7, 20),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Atlanta Open",
                    date = Date(2018, 7, 27),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Swiss Open",
                    date = Date(2018, 7, 27),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Austrian Open",
                    date = Date(2018, 8, 3),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Winston-Salem Open",
                    date = Date(2018, 8, 24),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Moselle Open",
                    date = Date(2018, 9, 21),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Shenzhen Open",
                    date = Date(2018, 9, 24),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Stockholm Open",
                    date = Date(2018, 10, 19),
                    type = "ATP250",
                    drawsize = 16
                ),Tournament(
                    name = "Kremlin Cup",
                    date = Date(2018, 10, 19),
                    type = "ATP250",
                    drawsize = 16
                )
            ]
        )
    end

    if ATPChallenger == true
        append!(
            tournaments,
            map((index) -> Tournament(
                name = "Challenger125 $index",
                date = Date(2018, 1, 1),
                type = "ATPChallenger125",
                drawsize = 32
                ), 1:25)
        )
        append!(
            tournaments,
            map((index) -> Tournament(
                name = "Challenger110 $index",
                date = Date(2018, 1, 1),
                type = "ATPChallenger110",
                drawsize = 32
                ), 1:12)
        )
        append!(
            tournaments,
            map((index) -> Tournament(
                name = "Challenger100 $index",
                date = Date(2018, 1, 1),
                type = "ATPChallenger100",
                drawsize = 32
                ), 1:19)
        )
        append!(
            tournaments,
            map((index) -> Tournament(
                name = "Challenger90 $index",
                date = Date(2018, 1, 1),
                type = "ATPChallenger90",
                drawsize = 32
                ), 1:91)
        )
    end

    if ITFWorldTennisTour == true
        append!(
            tournaments,
            map((index) -> Tournament(
                name = "ITF $index",
                date = Date(2018, 1, 1),
                type = "ITFWorldTennisTour25k",
                drawsize = 32
            ), 1:550)
        )
    end

    return tournaments
end

max_stars_repo_name: Danial-Hussain/Tennis-Ranking

max_issues_repo_name: Danial-Hussain/Tennis-Ranking

max_forks_repo_name: Danial-Hussain/Tennis-Ranking


text:
# TODO:
# * energy and forces for ASEAtoms ????
#   -> maybe define these for AbstractAtoms, then remove the
#      conversion from ASE???
# * poly_regularise
#   that is available for all sub-modules?
# * a better structure for the descriptors and for the
#    coordinate transforms

"""
# `NBodyIPs.jl`

Package for specifying interatomic potentials based on the
N-Body expansion (ANOVA, HDMR, ...).

See `NBodyIPFitting` for the associated fitting and testing framework.
"""
module NBodyIPs

using Reexport

include("types.jl")

include("cutoffs.jl")
@reexport using NBodyIPs.Cutoffs

# generic types and function prototypes
include("common.jl")

# definitions for the one and only 1-body function
# this imports OneBody from JuLIP and supplies it with extra
# functionality needed for the NBodyIPs
include("onebody.jl")

# the machinery for evaluating the invariants as fast as possible
include("fastpolys.jl")

# bond-length invariants
include("blinvariants.jl")

# bond-angle invariants
include("bainvariants.jl")

# generic and specific descriptors for BL and BA
include("descriptors.jl")
# exports BondAngleDesc and BondLengthDesc

# evaluating Polynomials of an invariant coordinate system
include("polys.jl")
@reexport using NBodyIPs.Polys

# codes to generate basis functions
include("polybasis.jl")
@reexport using NBodyIPs.PolyBasis

# environment dependent potentials
include("environ.jl")
@reexport using NBodyIPs.EnvIPs

# regularisation methods specialised for NBodyIPs
include("sobol.jl")
include("regularisers.jl")
@reexport using NBodyIPs.Regularisers

# Some extra functionality to attach a repulsive core to a 2B fit
include("repulsion.jl")

include("experimental.jl")

end # module

max_stars_repo_name: cortner/ManyBodyIPs

max_issues_repo_name: cortner/ManyBodyIPs

max_forks_repo_name: cortner/ManyBodyIPs


text:
using StackedNets
using Base.Test

# Function to numerically check the analytic error gradients.
function test_deepnet_gradient(; cases::Int=1)
	for activation in ["leaky_rectified_linear", "linear", "rectified_linear", "sigmoid", "softmax", "softplus", "tanh"]
		for error in ("absolute_error", "cross_entropy", "squared_error")
			println("Testing $activation units with $error errors.")
			# Construct a random deep network based on the activation and error types.
			units = _generate_random_unit_list(activation, error)
			DN = StackedNet{Float64}(units, error=error)
			# Check the layers in the net have the required activation type.
			for l = 1:length(DN.layers) - 1
				@test DN.layers[l].activation == activation
			end
			# Construct input / output cases.
			X = rand(units[1].n, cases)
			Y = rand(units[end].n, cases)
			# Set gradient information on the pattern and compare it to numerically derived gradients.
			results = gradient_check(DN, X, Y)
			ok, notok = sum(results[:ok]), sum(!results[:ok])
			if notok > 0
				println(results[!results[:ok], :])
			end
			println("$ok/$(ok+notok) gradient checks passed.")
			println()
			@test sum(!results[:ok]) == 0
		end
	end
end

# Generates random arrays of units for testing purposes.
function _generate_random_unit_list(activation, error)
	# Create a random number of layers of units with the required activation function.
	units = Units[Units(rand(2:20))]
	for u = 1:rand(1:10)
		push!(units, Units(rand(2:20), activation=activation))
	end
	# If error is cross_entropy, add a final layer to ensure outputs are probabilities.
	if error == "cross_entropy"
		push!(units, Units(rand(1:20), activation="softmax"))
	end
	units
end

# Run tests.
@time test_deepnet_gradient()


text:
import LinearAlgebra.BLAS: asum, dot, blascopy!, nrm2, scal, scal!, gemm, gemm!, gemv, gemv!,
    syrk, symm, symm!, symv, symv!, trmm, trsm, trmv, trsv, trsv!, ger!

const SA = StridedArray

# Long-form `dot`.
@explicit_intercepts(
    dot,
    Tuple{Int, StridedArray, Int, StridedArray, Int},
    [false, true, false, true, false],
)
∇(::typeof(dot), ::Type{Arg{2}}, p, z, z̄, n::Int, x::SA, ix::Int, y::SA, iy::Int) =
    scal!(n, z̄, blascopy!(n, y, iy, zeroslike(x), ix), ix)
∇(::typeof(dot), ::Type{Arg{4}}, p, z, z̄, n::Int, x::SA, ix::Int, y::SA, iy::Int) =
    scal!(n, z̄, blascopy!(n, x, ix, zeroslike(y), iy), iy)
∇(x̄, ::typeof(dot), ::Type{Arg{2}}, p, z, z̄, n::Int, x::SA, ix::Int, y::SA, iy::Int) =
    (x̄ .= x̄ .+ scal!(n, z̄, blascopy!(n, y, iy, zeroslike(x), ix), ix))
∇(ȳ, ::typeof(dot), ::Type{Arg{4}}, p, z, z̄, n::Int, x::SA, ix::Int, y::SA, iy::Int) =
    (ȳ .= ȳ .+ scal!(n, z̄, blascopy!(n, x, ix, zeroslike(y), iy), iy))

# Short-form `nrm2`.
@explicit_intercepts nrm2 Tuple{Union{StridedVector, Array}}
∇(::typeof(nrm2), ::Type{Arg{1}}, p, y, ȳ, x) = x * (ȳ / y)
∇(x̄, ::typeof(nrm2), ::Type{Arg{1}}, p, y, ȳ, x) = (x̄ .= x̄ .+ x .* (ȳ / y))

# Long-form `nrm2`.
@explicit_intercepts(
    nrm2,
    Tuple{Integer, Union{DenseArray, Ptr{<:AbstractFloat}}, Integer},
    [false, true, false],
)
∇(::typeof(nrm2), ::Type{Arg{2}}, p, y, ȳ, n::Integer, x, inc::Integer) =
    scal!(n, ȳ / y, blascopy!(n, x, inc, zeroslike(x), inc), inc)
∇(x̄, ::typeof(nrm2), ::Type{Arg{2}}, p, y, ȳ, n::Integer, x, inc::Integer) =
    (x̄ .= x̄ .+ scal!(n, ȳ / y, blascopy!(n, x, inc, zeroslike(x), inc), inc))

# Short-form `asum`.
@explicit_intercepts asum Tuple{Union{StridedVector, Array}}
∇(::typeof(asum), ::Type{Arg{1}}, p, y, ȳ, x) = ȳ .* sign.(x)
∇(x̄, ::typeof(asum), ::Type{Arg{1}}, p, y, ȳ, x) = (x̄ .= x̄ .+ ȳ .* sign.(x))

# Long-form `asum`.
@explicit_intercepts(
    asum,
    Tuple{Integer, Union{DenseArray, Ptr{<:AbstractFloat}}, Integer},
    [false, true, false],
)
∇(::typeof(asum), ::Type{Arg{2}}, p, y, ȳ, n::Integer, x, inc::Integer) =
    scal!(n, ȳ, blascopy!(n, sign.(x), inc, zeroslike(x), inc), inc)
∇(x̄, ::typeof(asum), ::Type{Arg{2}}, p, y, ȳ, n::Integer, x, inc::Integer) =
    (x̄ .= x̄ .+ scal!(n, ȳ, blascopy!(n, sign.(x), inc, zeroslike(x), inc), inc))

# Some weird stuff going on that I haven't figured out yet.
# let f = :(scal{T <: AbstractArray, V <: AbstractFloat})
#     ā = :(blascopy!(n, z̄, inc, zeros(X), inc) .* X)
#     X̄ = :(scal!(n, a, z̄, inc))
#     @eva; @primitive $f(n::Int, a::V, X::T, inc::Int) z z̄ false $ā $X̄ false
# end

# `gemm` sensitivities implementation.
@explicit_intercepts(
    gemm,
    Tuple{Char, Char, StridedMatrix{T}, StridedMatrix{T}} where T<:∇Scalar,
    [false, false, true, true],
)
∇(::typeof(gemm), ::Type{Arg{3}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedMatrix{T},
) where T<:∇Scalar = sum(Ȳ .* Y) / α

∇(::typeof(gemm), ::Type{Arg{4}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedMatrix{T},
) where T<:∇Scalar =
    uppercase(tA) == 'N' ?
        uppercase(tB) == 'N' ?
            gemm('N', 'T', α, Ȳ, B) :
            gemm('N', 'N', α, Ȳ, B) :
        uppercase(tB) == 'N' ?
            gemm('N', 'T', α, B, Ȳ) :
            gemm('T', 'T', α, B, Ȳ)

∇(Ā::StridedMatrix{T}, ::typeof(gemm), ::Type{Arg{4}}, _, Y, Ȳ,
    tA::Char,
    tB::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedMatrix{T},
) where T<:∇Scalar =
    uppercase(tA) == 'N' ?
        uppercase(tB) == 'N' ?
            gemm!('N', 'T', α, Ȳ, B, 1.0, Ā) :
            gemm!('N', 'N', α, Ȳ, B, 1.0, Ā) :
        uppercase(tB) == 'N' ?
            gemm!('N', 'T', α, B, Ȳ, 1.0, Ā) :
            gemm!('T', 'T', α, B, Ȳ, 1.0, Ā)

∇(::typeof(gemm), ::Type{Arg{5}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedMatrix{T},
) where T<:∇Scalar =
    uppercase(tA) == 'N' ?
        uppercase(tB) == 'N' ?
            gemm('T', 'N', α, A, Ȳ) :
            gemm('T', 'N', α, Ȳ, A) :
        uppercase(tB) == 'N' ?
            gemm('N', 'N', α, A, Ȳ) :
            gemm('T', 'T', α, Ȳ, A)

∇(B̄::StridedMatrix{T}, ::typeof(gemm), ::Type{Arg{5}}, _, Y, Ȳ,
    tA::Char,
    tB::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedMatrix{T},
) where T<:∇Scalar =
    uppercase(tA) == 'N' ?
        uppercase(tB) == 'N' ?
            gemm!('T', 'N', α, A, Ȳ, 1.0, B̄) :
            gemm!('T', 'N', α, Ȳ, A, 1.0, B̄) :
        uppercase(tB) == 'N' ?
            gemm!('N', 'N', α, A, Ȳ, 1.0, B̄) :
            gemm!('T', 'T', α, Ȳ, A, 1.0, B̄)

# `gemm` sensitivities implementation for `α = 1`.
@explicit_intercepts(
    gemm,
    Tuple{Char, Char, T, StridedMatrix{T}, StridedMatrix{T}} where T<:∇Scalar,
    [false, false, true, true, true]
)
∇(::typeof(gemm), ::Type{Arg{3}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    A::StridedMatrix{T},
    B::StridedMatrix{T}
) where T<:∇Scalar = ∇(gemm, Arg{4}, p, Y, Ȳ, tA, tB, one(T), A, B)
∇(Ā, ::typeof(gemm), ::Type{Arg{3}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    A::StridedMatrix{T},
    B::StridedMatrix{T}
) where T<:∇Scalar = ∇(Ā, gemm, Arg{4}, p, Y, Ȳ, tA, tB, one(T), A, B)
∇(::typeof(gemm), ::Type{Arg{4}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    A::StridedMatrix{T},
    B::StridedMatrix{T},
) where T<:∇Scalar = ∇(gemm, Arg{5}, p, Y, Ȳ, tA, tB, one(T), A, B)
∇(B̄, ::typeof(gemm), ::Type{Arg{4}}, p, Y, Ȳ,
    tA::Char,
    tB::Char,
    A::StridedMatrix{T},
    B::StridedMatrix{T}
) where T<:∇Scalar = ∇(B̄, gemm, Arg{5}, p, Y, Ȳ, tA, tB, one(T), A, B)

# `gemv` sensitivities implementation.
@explicit_intercepts(
    gemv,
    Tuple{Char, T, StridedMatrix{T}, StridedVector{T}} where T<:∇Scalar,
    [false, true, true, true],
)
∇(::typeof(gemv), ::Type{Arg{2}}, p, y, ȳ,
    tA::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = dot(ȳ, y) / α
∇(::typeof(gemv), ::Type{Arg{3}}, p, y, ȳ,
    tA::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = uppercase(tA) == 'N' ? α * ȳ * x' : α * x * ȳ'
∇(Ā::StridedMatrix{T}, ::typeof(gemv), ::Type{Arg{3}}, _, y, ȳ,
    tA::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = uppercase(tA) == 'N' ? ger!(α, ȳ, x, Ā) : ger!(α, x, ȳ, Ā)
∇(::typeof(gemv), ::Type{Arg{4}}, p, y, ȳ,
    tA::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = gemv(uppercase(tA) == 'N' ? 'T' : 'N', α, A, ȳ)
∇(x̄::StridedVector{T}, ::typeof(gemv), ::Type{Arg{4}}, _, y, ȳ,
    tA::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = gemv!(uppercase(tA) == 'N' ? 'T' : 'N', α, A, ȳ, one(T), x̄)

# `gemv` sensitivities implementation with `α = 1`.
@explicit_intercepts(
    gemv,
    Tuple{Char, StridedMatrix{T}, StridedVector{T}} where T<:∇Scalar,
    [false, true, true],
)
∇(::typeof(gemv), ::Type{Arg{2}}, p, y, ȳ,
    tA::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(gemv, Arg{3}, p, y, ȳ, tA, one(T), A, x)
∇(Ā::StridedMatrix{T}, ::typeof(gemv), ::Type{Arg{2}}, p, y, ȳ,
    tA::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(Ā, gemv, Arg{3}, p, y, ȳ, tA, one(T), A, x)
∇(::typeof(gemv), ::Type{Arg{3}}, p, y, ȳ,
    tA::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(gemv, Arg{4}, p, y, ȳ, tA, one(T), A, x)
∇(x̄::StridedVector{T}, ::typeof(gemv), ::Type{Arg{3}}, p, y, ȳ,
    tA::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(x̄, gemv, Arg{4}, p, y, ȳ, tA, one(T), A, x)

# # `syrk` sensitivity implementations.
# @explicit_intercepts(
#     syrk,
#     Tuple{Char, Char, ∇Scalar, StridedVecOrMat{<:∇Scalar}},
#     [false, false, true, true],
# )
# function ∇(::typeof(syrk), ::Type{Arg{3}}, p, Y, Ȳ,
#     uplo::Char,
#     trans::Char,
#     α::∇Scalar,
#     A::StridedVecOrMat{<:∇Scalar},
# )
#     g! = uppercase(uplo) == 'L' ? tril! : triu!
#     return sum(g!(Ȳ .* Y)) / α
# end
# function ∇(::typeof(syrk), ::Type{Arg{4}}, p, Y, Ȳ,
#     uplo::Char,
#     trans::Char,
#     α::∇Scalar,
#     A::StridedVecOrMat{<:∇Scalar},
# )
#     triȲ = uppercase(uplo) == 'L' ? tril(Ȳ) : triu(Ȳ)
#     out = gemm('N', trans, α, triȲ .+ triȲ', A)
#     return uppercase(trans) == 'N' ? out : out'
# end
# function ∇(Ā::StridedVecOrMat{T}, ::typeof(syrk), ::Type{Arg{4}}, p, Y, Ȳ,
#     uplo::Char,
#     trans::Char,
#     α::∇Scalar,
#     A::StridedVecOrMat{T},
# ) where T<:∇Scalar
#     triȲ = uppercase(uplo) == 'L' ? tril(Ȳ) : triu(Ȳ)
#     out = gemm('N', trans, α, triȲ .+ triȲ', A)
#     return broadcast!((ā, δā)->ā+δā, Ā, Ā, uppercase(trans) == 'N' ? out : out')
# end

# # `syrk` sensitivity implementations for `α=1`.
# @explicit_intercepts(
#     syrk,
#     Tuple{Char, Char, StridedVecOrMat{<:∇Scalar}},
#     [false, false, true],
# )
# ∇(::typeof(syrk), ::Type{Arg{3}}, p, Y, Ȳ,
#     uplo::Char,
#     trans::Char,
#     A::StridedVecOrMat{<:∇Scalar},
# ) = ∇(syrk, Arg{4}, p, Y, Ȳ, uplo, trans, one(eltype(A)), A)
# ∇(Ā::StridedVecOrMat{T}, ::typeof(syrk), ::Type{Arg{4}}, p, Y, Ȳ,
#     uplo::Char,
#     trans::Char,
#     A::StridedVecOrMat{T},
# ) where T<:∇Scalar = ∇(Ā, syrk, Arg{4}, p, Y, Ȳ, uplo, char, one(eltype(A)), A)

# `symm` sensitivity implementations.
@explicit_intercepts(
    symm,
    Tuple{Char, Char, T, StridedMatrix{T}, StridedMatrix{T}} where T<:∇Scalar,
    [false, false, true, true, true],
)
∇(::typeof(symm), ::Type{Arg{3}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = sum(Ȳ .* Y) / α
function ∇(::typeof(symm), ::Type{Arg{4}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar
    tmp = uppercase(side) == 'L' ? Ȳ * B' : B'Ȳ
    g! = uppercase(ul) == 'L' ? tril! : triu!
    return α * g!(tmp + tmp' - Diagonal(tmp))
end
function ∇(Ā::StridedMatrix{T}, ::typeof(symm), ::Type{Arg{4}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar
    tmp = uppercase(side) == 'L' ? Ȳ * B' : B'Ȳ
    g! = uppercase(ul) == 'L' ? tril! : triu!
    return broadcast!((ā, δā)->ā + δā, Ā, Ā, α * g!(tmp + tmp' - Diagonal(tmp)))
end
∇(::typeof(symm), ::Type{Arg{5}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = symm(side, ul, α, A, Ȳ)
∇(B̄::StridedMatrix{T}, ::typeof(symm), ::Type{Arg{5}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = symm!(side, ul, α, A, Ȳ, 1.0, B̄)

# `symm` sensitivity implementations for `α=1`.
@explicit_intercepts(
    symm,
    Tuple{Char, Char, StridedMatrix{T}, StridedMatrix{T}} where T<:∇Scalar,
    [false, false, true, true],
)
∇(::typeof(symm), ::Type{Arg{3}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = ∇(symm, Arg{4}, p, Y, Ȳ, side, ul, one(T), A, B)
∇(Ā::StridedMatrix{T}, ::typeof(symm), ::Type{Arg{3}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = ∇(Ā, symm, Arg{4}, p, Y, Ȳ, side, ul, one(T), A, B)
∇(::typeof(symm), ::Type{Arg{4}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = ∇(symm, Arg{5}, p, Y, Ȳ, side, ul, one(T), A, B)
∇(B̄::StridedMatrix{T}, ::typeof(symm), ::Type{Arg{4}}, p, Y, Ȳ,
    side::Char,
    ul::Char,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = ∇(B̄, symm, Arg{5}, p, Y, Ȳ, side, ul, one(T), A, B)

# `symv` sensitivity implementations.
@explicit_intercepts(
    symv,
    Tuple{Char, T, StridedMatrix{T}, StridedVector{T}} where T<:∇Scalar,
    [false, true, true, true],
)
∇(::typeof(symv), ::Type{Arg{2}}, p, y, ȳ,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = dot(ȳ, y) / α
∇(::typeof(symv), ::Type{Arg{3}}, p, y, ȳ,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(symm, Arg{4}, p, y, ȳ, 'L', ul, α, A, x)
∇(Ā::StridedMatrix{T}, ::typeof(symv), ::Type{Arg{3}}, p, y, ȳ,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(Ā, symm, Arg{4}, p, y, ȳ, 'L', ul, α, A, x)
∇(::typeof(symv), ::Type{Arg{4}}, p, y, ȳ,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = symv(ul, α, A, ȳ)
∇(x̄::StridedVector{T}, ::typeof(symv), ::Type{Arg{4}}, p, y, ȳ,
    ul::Char,
    α::T,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = symv!(ul, α, A, ȳ, one(T), x̄)

# `symv` sensitivity implementations for `α=1`.
@explicit_intercepts(
    symv,
    Tuple{Char, StridedMatrix{T}, StridedVector{T}} where T<:∇Scalar,
    [false, true, true],
)
∇(::typeof(symv), ::Type{Arg{2}}, p, y, ȳ,
    ul::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(symv, Arg{3}, p, y, ȳ, ul, one(T), A, x)
∇(Ā::StridedMatrix{T}, ::typeof(symv), ::Type{Arg{2}}, p, y, ȳ,
    ul::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(Ā, symv, Arg{3}, p, y, ȳ, ul, one(T), A, x)
∇(::typeof(symv), ::Type{Arg{3}}, p, y, ȳ,
    ul::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(symv, Arg{4}, p, y, ȳ, ul, one(T), A, x)
∇(B̄::StridedVector{T}, ::typeof(symv), ::Type{Arg{3}}, p, y, ȳ,
    ul::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = ∇(B̄, symv, Arg{4}, p, y, ȳ, ul, one(T), A, x)

# `trmm` sensitivity implementations.
@explicit_intercepts(
    trmm,
    Tuple{Char, Char, Char, Char, T, StridedMatrix{T}, StridedMatrix{T}} where T<:∇Scalar,
    [false, false, false, false, true, true, true],
)
∇(::typeof(trmm), ::Type{Arg{5}}, p, Y, Ȳ,
    side::Char, ul::Char, ta::Char, dA::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar = sum(Ȳ .* Y) / α
function ∇(::typeof(trmm), ::Type{Arg{6}}, p, Y, Ȳ,
    side::Char, ul::Char, ta::Char, dA::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar
    Ā_full = uppercase(side) == 'L' ?
        uppercase(ta) == 'N' ?
            gemm('N', 'T', α, Ȳ, B) :
            gemm('N', 'T', α, B, Ȳ) :
        uppercase(ta) == 'N' ?
            gemm('T', 'N', α, B, Ȳ) :
            gemm('T', 'N', α, Ȳ, B)
    dA == 'U' && fill!(view(Ā_full, diagind(Ā_full)), zero(T))
    return (uppercase(ul) == 'L' ? tril! : triu!)(Ā_full)
end
∇(::typeof(trmm), ::Type{Arg{7}}, p, Y, Ȳ,
    side::Char, ul::Char, ta::Char, dA::Char,
    α::T,
    A::StridedMatrix{T},
    B::StridedVecOrMat{T},
) where T<:∇Scalar =
    uppercase(side) == 'L' ?
        uppercase(ta) == 'N' ?
            trmm('L', ul, 'T', dA, α, A, Ȳ) :
            trmm('L', ul, 'N', dA, α, A, Ȳ) :
        uppercase(ta) == 'N' ?
            trmm('R', ul, 'T', dA, α, A, Ȳ) :
            trmm('R', ul, 'N', dA, α, A, Ȳ)

# `trmv` sensitivity implementations.
@explicit_intercepts(
    trmv,
    Tuple{Char, Char, Char, StridedMatrix{T}, StridedVector{T}} where T<:∇Scalar,
    [false, false, false, true, true],
)
function ∇(::typeof(trmv), ::Type{Arg{4}}, p, y, ȳ,
    ul::Char, ta::Char, dA::Char,
    A::StridedMatrix{T},
    b::StridedVector{T},
) where T<:∇Scalar
    Ā = (uppercase(ul) == 'L' ? tril! : triu!)(uppercase(ta) == 'N' ? ȳ * b' : b * ȳ')
    dA == 'U' && fill!(view(Ā, diagind(Ā)), zero(T))
    return Ā
end
∇(::typeof(trmv), ::Type{Arg{5}}, p, y, ȳ,
    ul::Char, ta::Char, dA::Char,
    A::StridedMatrix{T},
    b::StridedVector{T},
) where T<:∇Scalar = trmv(ul, uppercase(ta) == 'N' ? 'T' : 'N', dA, A, ȳ)

# `trsm` sensitivity implementations.
@explicit_intercepts(
    trsm,
    Tuple{Char, Char, Char, Char, T, StridedMatrix{T}, StridedMatrix{T}} where T<:∇Scalar,
    [false, false, false, false, true, true, true],
)
∇(::typeof(trsm), ::Type{Arg{5}}, p, Y, Ȳ,
    side::Char, ul::Char, ta::Char, dA::Char,
    α::T,
    A::StridedMatrix{T},
    X::StridedMatrix{T},
) where T<:∇Scalar = sum(Ȳ .* Y) / α
function ∇(::typeof(trsm), ::Type{Arg{6}}, p, Y, Ȳ,
    side::Char, ul::Char, ta::Char, dA::Char,
    α::T,
    A::StridedMatrix{T},
    X::StridedVecOrMat{T},
) where T<:∇Scalar
    Ā_full = uppercase(side) == 'L' ?
        uppercase(ta) == 'N' ?
            trsm('L', ul, 'T', dA, -1.0, A, Ȳ * Y') :
            trsm('R', ul, 'T', dA, -1.0, A, Y * Ȳ') :
        uppercase(ta) == 'N' ?
            trsm('R', ul, 'T', dA, -1.0, A, Y'Ȳ) :
            trsm('L', ul, 'T', dA, -1.0, A, Ȳ'Y)
    dA == 'U' && fill!(view(Ā_full, diagind(Ā_full)), zero(T))
    return (uppercase(ul) == 'L' ? tril! : triu!)(Ā_full)
end
∇(::typeof(trsm), ::Type{Arg{7}}, p, Y, Ȳ,
    side::Char, ul::Char, ta::Char, dA::Char,
    α::T,
    A::StridedMatrix{T},
    X::StridedMatrix{T},
) where T<:∇Scalar =
    uppercase(side) == 'L' ?
        uppercase(ta) == 'N' ?
            trsm('L', ul, 'T', dA, α, A, Ȳ) :
            trsm('L', ul, 'N', dA, α, A, Ȳ) :
        uppercase(ta) == 'N' ?
            trsm('R', ul, 'T', dA, α, A, Ȳ) :
            trsm('R', ul, 'N', dA, α, A, Ȳ)

# `trsv` sensitivity implementations.
@explicit_intercepts(
    trsv,
    Tuple{Char, Char, Char, StridedMatrix{T}, StridedVector{T}} where T<:∇Scalar,
    [false, false, false, true, true],
)
function ∇(::typeof(trsv), ::Type{Arg{4}}, p, y, ȳ,
    ul::Char, ta::Char, dA::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar
    Ā = ∇(trsm, Arg{6}, p, y, ȳ, 'L', ul, ta, dA, one(T), A, x)
    dA == 'U' && fill!(view(Ā, diagind(Ā)), zero(T))
    return Ā
end
∇(::typeof(trsv), ::Type{Arg{5}}, p, y, ȳ,
    ul::Char, ta::Char, dA::Char,
    A::StridedMatrix{T},
    x::StridedVector{T},
) where T<:∇Scalar = trsv(ul, uppercase(ta) == 'N' ? 'T' : 'N', dA, A, ȳ)

# # # TODO: Banded matrix operations.
# # # gbmv
# # # sbmv


text:
@doc Markdown.doc"""
    compact_presentation(a::FacElem{nf_elem, AnticNumberField}, n::Int = 2; decom, arb_prec = 100, short_prec = 1000) -> FacElem

Computes a presentation $a = \prod a_i^{n_i}$ where all the exponents $n_i$ are powers of $n$
and, the elements $a_i$ are "small", generically, they have a norm bounded by $d^{n/2}$ where
$d$ is the discriminant of the maximal order.
As the algorithm needs the factorisation of the principal ideal generated by $a$, it can
be passed in in \code{decom}.
"""
function compact_presentation(a::FacElem{nf_elem, AnticNumberField}, nn::Int = 2; decom=false, arb_prec = 100, short_prec = 128)
  n = fmpz(nn)

  K = base_ring(a)
  if isempty(a.fac)
    return a
  end

  if typeof(decom) == Bool
    ZK = lll(maximal_order(K))
    de::Dict{NfOrdIdl, fmpz} = factor_coprime(a, IdealSet(ZK), refine = true)
  else
    #de = Dict{NfOrdIdl, fmpz}((p, v) for (p, v) = decom)
    de = Dict((p, v) for (p, v) = decom)
    if length(decom) == 0
      ZK = lll(maximal_order(K))
    else
      ZK = order(first(keys(decom)))
    end
  end
  de_inv = Dict{NfOrdIdl, NfOrdFracIdl}()

  be = FacElem(K(1))

  if !(decom isa Bool)
    @hassert :CompactPresentation 1 (length(de) == 0 && isone(abs(factored_norm(a)))) ||
                                    (abs(factored_norm(a)) == factored_norm(FacElem(de)))
  end

  v = conjugates_arb_log_normalise(a, arb_prec)
  if length(de) == 0
    _v = FlintZZ(1)
  else
    _v = maximum(abs, values(de))+1
  end

  #Step 1: reduce the ideal in a p-power way...

  A = ideal(ZK, 1)
  @vprint :CompactPresentation 1 "First reduction step\n"
  cached_red = Dict{NfOrdIdl, Dict{Int, Tuple{NfOrdIdl, FacElem{nf_elem, AnticNumberField}}}}()
  n_iterations = Int(flog(_v, n))
  for _k = n_iterations:-1:0
    @vprint :CompactPresentation 3 "Reducing the support: step $(_k) / $(n_iterations)\n"
    B = Dict{NfOrdIdl, Int}()
    for (p, vv) in de
      e_p = Int(div(vv, n^_k) % nn)
      if iszero(e_p)
        continue
      end
      if haskey(cached_red, p)
        Dp = cached_red[p]
        if haskey(Dp, e_p)
          Ap, ap = Dp[e_p]
        else
          Ap, ap = power_reduce(p, fmpz(e_p))
          Dp[e_p] = (Ap, ap)
        end
        add_to_key!(B, Ap, 1)
        mul!(be, be, ap^(-(n^_k)))
        v -= Ref(n^_k) .* conjugates_arb_log_normalise(ap, arb_prec)
      else
        Dp = Dict{Int, Tuple{NfOrdIdl, FacElem{nf_elem, AnticNumberField}}}()
        Ap, ap = power_reduce(p, fmpz(e_p))
        Dp[e_p] = (Ap, ap)
        cached_red[p] = Dp
        add_to_key!(B, Ap, 1)
        v -= Ref(n^_k) .* conjugates_arb_log_normalise(ap, arb_prec)
        mul!(be, be, ap^(-(n^_k)))
      end
    end
    add_to_key!(B, A, n)
    @vtime :CompactPresentation 3 A, alpha = reduce_ideal(FacElem(B))
    mul!(be, be, alpha^(-(n^_k)))
    #be *= alpha^(-(n^_k))
    v -= Ref(n^_k) .* conjugates_arb_log_normalise(alpha, arb_prec)
  end
  if length(be.fac) > 1
    delete!(be.fac, K(1))
  end

  #Step 2: now reduce the infinite valuation

  r1, r2 = signature(K)

  if length(de) == 0
    m = FlintZZ(1)
  else
    m = maximum(abs, values(de))
  end
  m = max(m, 1)
  local mm
  while true
    try
      mm = abs_upper_bound(log(1+maximum(abs, v))//log(n), fmpz)
      break
    catch e
      if !isa(e, InexactError)
        rethrow(e)
      end
      arb_prec *= 2
      @vprint :CompactPresentation 2 "increasing precision to $arb_prec\n"
      v = conjugates_arb_log_normalise(a, arb_prec) +
          conjugates_arb_log_normalise(be, arb_prec)
    end
  end
  k = max(ceil(Int, log(m)/log(n)), Int(mm))

  de = Dict(A => fmpz(1))
  delete!(de, ideal(ZK, 1))

  @hassert :CompactPresentation 1 length(de) == 0 && isone(abs(factored_norm(a*be))) == 1 ||
                                  abs(factored_norm(a*be)) == factored_norm(FacElem(de))

  @hassert :CompactPresentation 2 length(de) != 0 || isone(ideal(ZK, a*be))
  @hassert :CompactPresentation 2 length(de) == 0 || ideal(ZK, a*be) == FacElem(de)

  while k>=1
    @vprint :CompactPresentation 1 "k now: $k\n"
    D = Dict((p, div(fmpz(v), n^k)) for (p, v) = de if v >= n^k)
    if length(D) == 0
      A = FacElem(Dict(ideal(ZK, 1) => 1))
    else
      A = FacElem(D)
    end
    vv = arb[x//n^k for x = v]
    vvv = fmpz[]
    el_embs = a*be
    for i=1:r1
      while !radiuslttwopower(vv[i], -5)
        arb_prec *= 2
        v = conjugates_arb_log_normalise(el_embs, arb_prec)
        vv = arb[x//n^k for x = v]
      end
      push!(vvv, round(fmpz, vv[i]//log(2)))
    end
    for i=r1+1:r1+r2
      while !radiuslttwopower(vv[i], -5)
        arb_prec *= 2
        v = conjugates_arb_log_normalise(el_embs, arb_prec)
        vv = arb[x//n^k for x = v]
      end
      local r = round(fmpz, vv[i]//log(2)//2)
      push!(vvv, r)
      push!(vvv, r)
    end
    @assert abs(sum(vvv)) <= degree(K)
    @vtime :CompactPresentation 1 eA = (simplify(evaluate(A, coprime = true)))
    @vtime :CompactPresentation 1 id = inv(eA)
    @vtime :CompactPresentation 1 b = short_elem(id, matrix(FlintZZ, 1, length(vvv), vvv), prec = short_prec) # the precision needs to be done properly...

    @assert abs(norm(b)//norm(id)) <= abs(discriminant(ZK)) # the trivial case

    for (p, v) in A
      if isone(p)
        continue
      end
      de[p] -= n^k*v
    end

    @vtime :CompactPresentation 1 B = simplify(b*eA)
    @assert isone(B.den)
    B1 = B.num
    @assert norm(B1) <= abs(discriminant(ZK))

    @vprint :CompactPresentation 1 "Factoring ($(B1.gen_one), $(B1.gen_two)) of norm $(norm(B1))\n"
    @vtime :CompactPresentation 1 lfB1 = factor_easy(B1)
    for (p, _v) = lfB1
      if haskey(de, p)
        de[p] += _v*n^k
        elseif isprime_known(p) && isprime(p)
        insert_prime_into_coprime!(de, p, _v*n^k)
      else
        de = insert_into_coprime(de, p, _v*n^k)
      end
    end
    v_b = conjugates_arb_log_normalise(b, arb_prec)
    @v_do :CompactPresentation 2 @show old_n = sum(x^2 for x = v)
    v += Ref(n^k) .* v_b
    @v_do :CompactPresentation 2 @show new_n = sum(x^2 for x = v)
    @v_do :CompactPresentation 2 @show old_n / new_n

    add_to_key!(be.fac, b, n^k)
    #be *= FacElem(b)^(n^k)
    @hassert :CompactPresentation 1 length(de) == 0 && isone(abs(factored_norm(a*be))) == 1 ||
                                    abs(factored_norm(a*be)) == factored_norm(FacElem(de))
    @hassert :CompactPresentation 2 length(de) != 0 || isone(ideal(ZK, a*be))
    @hassert :CompactPresentation 2 length(de) == 0 || ideal(ZK, a*be) == FacElem(de)
    k -= 1
  end
  if isempty(de)
    de[ideal(ZK, 1)] = 1
  end
  @hassert :CompactPresentation 2 length(de) != 0 || isone(ideal(ZK, a*be))
  @hassert :CompactPresentation 2 length(de) == 0 || ideal(ZK, a*be) == FacElem(de)
  @hassert :CompactPresentation 1 length(de) == 0 && isone(abs(factored_norm(a*be))) == 1 ||
                                    factored_norm(ideal(ZK, a*be)) == abs(factored_norm(FacElem(de)))
  @vprint :CompactPresentation 1 "Final eval...\n"
  @vtime :CompactPresentation 1 A = evaluate(FacElem(de), coprime = true)
  @vtime :CompactPresentation 1 b_ev = evaluate_mod(a*be, A)
  inv!(be)
  add_to_key!(be.fac, b_ev, fmpz(1))
  return be
end

function insert_prime_into_coprime!(de::Dict{NfOrdIdl, fmpz}, p::NfOrdIdl, e::fmpz)
  @assert !isone(p)
  P = p.gen_one
  for (k, v) in de
    if k.gen_one % P == 0
      if k.splitting_type[2] == 0
        #k is not known to be prime, so p could divide...
        v1 = valuation(k, p)
        if v1 == 0
          continue
        end
        #since it divides k it cannot divide any other (coprime!)
        p2 = simplify(k*inv(p)^v1).num
        if !isone(p2)
          de[p2] = v
        end
        de[p] = v*v1+e
        delete!(de, k)
        return nothing
      else
        #both are know to be prime, and p is new to the dict.
        @assert p != k
      end
    end
  end
  de[p] = e
  return nothing
end

function insert_into_coprime(de::Dict{NfOrdIdl, fmpz}, p::NfOrdIdl, e::fmpz)
  @assert !isone(p)
  P = p.gen_one
  cp = NfOrdIdl[]
  for (k, v) in de
    if !iscoprime(k.gen_one, P)
      push!(cp, k)
    end
  end
  if isempty(cp)
    de[p] = e
    return de
  end
  push!(cp, p)
  cp = coprime_base(cp)
  de1 = Dict{NfOrdIdl, fmpz}()
  for (k, v) in de
    if iscoprime(k.gen_one, P)
      de1[k] = v
    end
  end
  for pp in cp
    vp = e*valuation(p, pp)
    for (k, v) in de
      vp += valuation(k, pp)*v
    end
    if !iszero(vp)
      de1[pp] = vp
    end
  end
  return de1
end

#TODO: use the log as a stopping condition as well
@doc Markdown.doc"""
    evaluate_mod(a::FacElem{nf_elem, AnticNumberField}, B::NfOrdFracIdl) -> nf_elem

Evaluates $a$ using CRT and small primes. Assumes that the ideal generated by $a$ is in fact $B$.
Useful in cases where $a$ has huge exponents, but the evaluated element is actually "small".
"""
function evaluate_mod(a::FacElem{nf_elem, AnticNumberField}, B::NfOrdFracIdl)
  K = base_ring(a)
  if isempty(a.fac)
    return one(K)
  end
  p = fmpz(next_prime(p_start))

  ZK = order(B)
  dB = denominator(B)*denominator(basis_matrix(ZK, copy = false))

  @hassert :CompactPresentation 1 factored_norm(B) == abs(factored_norm(a))
  @hassert :CompactPresentation 2 B == ideal(order(B), a)

  @assert order(B) === ZK
  pp = fmpz(1)
  re = K(0)
  threshold = 3
  if degree(K) > 30
    threshold = div(degree(K), 10)
  end
  while (true)
    dt = prime_decomposition_type(ZK, Int(p))
    fl = true
    for i = 1:length(dt)
      if dt[i][1] > threshold
        fl = false
        break
      end
    end
    if !fl
      p = next_prime(p)
      continue
    end
    me = modular_init(K, p)
    mp = Ref(dB) .* modular_proj(a, me)
    m = modular_lift(mp, me)
    if isone(pp)
      re = m
      pp = p
    else
      p2 = pp*p
      last = re
      re = induce_inner_crt(re, m, pp*invmod(pp, p), p2, div(p2, 2))
      if re == last
        return re//dB
      end
      pp = p2
    end
    @hassert :CompactPresentation 1 nbits(pp) < 10000
    p = next_prime(p)
  end
end

function Hecke.ispower(a::FacElem{nf_elem, AnticNumberField}, n::Int; with_roots_unity = false, decom = false, trager = false, easy = false)
  if n == 1
    return true, a
  end
  @assert n > 1
  K = base_ring(a)
  if isempty(a.fac)
    return true, FacElem(one(K))
  end
  anew_fac = Dict{nf_elem, fmpz}()
  rt = Dict{nf_elem, fmpz}()
  for (k, v) in a
    if iszero(v)
      continue
    end
    if isone(k)
      continue
    end
    q, r = divrem(v, n)
    if easy
      if r <= 0
        q -= 1
        r += n
      end
    end
    if !iszero(q)
      rt[k] = q
    end
    if !iszero(r)
      anew_fac[k] = r
    end
  end
  if isempty(anew_fac)
    K = base_ring(a)
    if isempty(rt)
      rt[one(K)] = 1
    end
    return true, FacElem(K, rt)
  end
  anew = FacElem(K, anew_fac)
  if easy
    fl, res1 = ispower(evaluate(anew), n, with_roots_unity = with_roots_unity)
    res = FacElem(K, rt)*res1
    return fl, res
  end
  c = conjugates_arb_log(a, 64)
  c1 = conjugates_arb_log(anew, 64)
  b = maximum(fmpz[upper_bound(abs(x), fmpz) for x in c])
  b1 = maximum(fmpz[upper_bound(abs(x), fmpz) for x in c1])
  if b1 <= root(b, 2)
    fl, res = _ispower(anew, n, with_roots_unity = with_roots_unity, trager = trager)
    if !fl
      return fl, res
    end
    if !isempty(rt)
      res = FacElem(rt)*res
    end
    return true, res
    return r
  end
  return _ispower(a, n, with_roots_unity = with_roots_unity, decom = decom, trager = trager)
end

function _ispower(a::FacElem{nf_elem, AnticNumberField}, n::Int; with_roots_unity = false, decom = false, trager = false)

  K = base_ring(a)
  ZK = maximal_order(K)
  @vprint :Saturate 1 "Computing compact presentation\n"
  @vtime :Saturate 1 c = Hecke.compact_presentation(a, n, decom = decom)
  b = one(K)
  d = Dict{nf_elem, fmpz}()
  for (k, v) = c.fac
    q, r = divrem(v, n)
    if r < 0
      r += n
      q -= 1
      @assert r > 0
      @assert n*q+r == v
    end
    d[k] = q
    mul!(b, b, k^r)
  end

  if isempty(d)
    d[one(K)] = fmpz(1)
  end
  df = FacElem(d)
  @hassert :CompactPresentation 2 evaluate(df^n*b *inv(a))== 1

  den = denominator(b, ZK)
  fl, den1 = ispower(den, n)
  if fl
    den = den1
  end
  fl, x = ispower((den^n)*b, n, with_roots_unity = with_roots_unity, isintegral = true, trager = trager)
  if fl
    @hassert :CompactPresentation 2 x^n == b*(den^n)
    add_to_key!(df.fac, K(den), -1)
    return fl, df*x
  else
    return fl, df
  end
end


text:
# CIE Standard white-points
# -------------------------

const WP_A   = XYZ(1.09850, 1.00000, 0.35585)
const WP_B   = XYZ(0.99072, 1.00000, 0.85223)
const WP_C   = XYZ(0.98074, 1.00000, 1.18232)
const WP_D50 = XYZ(0.96422, 1.00000, 0.82521)
const WP_D55 = XYZ(0.95682, 1.00000, 0.92149)
const WP_D65 = XYZ(0.95047, 1.00000, 1.08883)
const WP_D75 = XYZ(0.94972, 1.00000, 1.22638)
const WP_E   = XYZ(1.00000, 1.00000, 1.00000)
const WP_F2  = XYZ(0.99186, 1.00000, 0.67393)
const WP_F7  = XYZ(0.95041, 1.00000, 1.08747)
const WP_F11 = XYZ(1.00962, 1.00000, 0.64350)
const WP_DEFAULT = WP_D65


text:
import GaussianMixtureTest
using DelimitedFiles
using StatsBase:counts

Ctrue = parse(Int, ARGS[1]); B=200
C_max = max(5, (2*Ctrue - 1))

n_vec = [80, 100, 200, 300, 500, 800, 1000]
nn=length(n_vec)
bic_choice = fill(0, B, nn)
ks_choice = fill(0, B, nn)
ks_choice_tapering = fill(0, B, nn)
thecounts = fill(0, C_max, nn, 3)
for ik in 1:nn
    n2 = n_vec[ik]
    teststat = readdlm("compare_$(Ctrue)_$(n2).csv")
    for b in 1:B
        bic_choice[b, ik] = findmin(teststat[b, 1:C_max])[2]
        for C in 1:C_max
            if teststat[b, C_max+C] >= log(n2)/n2
                ks_choice_tapering[b, ik] = C
                break
            end
        end
        for C in 1:C_max
            if teststat[b, C_max + C] >= 0.05
                ks_choice[b, ik] = C
                break
            end
        end
    end

    thecounts[:, ik, 1] = counts(bic_choice[:,ik], 1:C_max)
    thecounts[:, ik, 2] = counts(ks_choice[:,ik], 1:C_max)
    thecounts[:, ik, 3] = counts(ks_choice_tapering[:,ik], 1:C_max)
end
res = transpose(thecounts[Ctrue,:,:]) ./ B
display(res)
println()
using RCall
@rput res n_vec

R"""
library(xtable)
res = as.data.frame(res)
colnames(res) = n_vec
rownames(res) = c("BIC", "Seq. Test 0.05", "Seq. Test log(n)/n")
print(xtable(res))
"""


text:
module Light

export Polar, Stokes, PolEllipse, rotate, mean, convert, measurements2stokes
import Base: mean, convert, +, *

immutable Stokes{T <: AbstractFloat}
	s0::T
	s1::T
	s2::T
	s3::T
	function Stokes(s0,s1,s2,s3)
		if (s0 < 0) || (s1*s1 + s2*s2 + s3*s3 > s0*s0)
			s0 = s1 = s2 = s3 = T(NaN)
		end
		new(s0,s1,s2,s3)
	end
end
Stokes{T <: AbstractFloat}(s0::T,s1::T,s2::T,s3::T) = Stokes{T}(s0,s1,s2,s3)

immutable Polar{T <: AbstractFloat}
	I::T
	dolp::T
	aop::T
	docp::T
	function Polar(I,dolp,aop,docp)
		if (I < 0) || (dolp*dolp + docp*docp > 1)
			I = dolp = aop = docp = T(NaN)
		end
		new(I,dolp,aop,docp)
	end
end
Polar{T <: AbstractFloat}(I::T,dolp::T,aop::T,docp::T) = Polar{T}(I,dolp,aop,docp)

#stokes2polar(s0,s1,s2,s3) = (s0, sqrt(s1*s1 + s2*s2)/s0, atan2(s2,s1)/2, s3/s0)

immutable PolEllipse{T <: AbstractFloat}
	polarization::T
	a::T
	b::T
	angle::T
	lefthand::Bool
end
#PolEllipse{T <: AbstractFloat}(polarization::T,a::T,angle::T,lefthand::Bool) = PolEllipse{T}(polarization,ellipticity,angle,lefthand)

function PolEllipse(s::Stokes)
	tmp = s.s1*s.s1 + s.s2*s.s2
	s0P = sqrt(tmp + s.s3*s.s3)
	dolp = sqrt(tmp)
	R = (s0P - dolp)/(s0P + dolp)
	aop = atan2(s.s2,s.s1)/2
	h = s.s3 < 0
	P = s0P/s.s0
	a = P*R
	b = P
	return PolEllipse(P,a,b,aop,s.s3 < 0)
end

#=function convert(::Type{PolEllipse}, a::Polar)
	P = sqrt(a.dolp*a.dolp + a.docp*a.docp)
	A = sqrt(.5*(1 + a.dolp))
	B = sqrt(.5*(1 - a.dolp))
	return PolEllipse(P,A/B,a.aop,a.docp < 0)
end

convert(::Type{PolEllipse}, a::Stokes) = PolEllipse(Polar(a))=#

convert(::Type{Stokes}, a::Polar) = Stokes(a.I, a.dolp*cos(2a.aop)*a.I, a.dolp*sin(2a.aop)*a.I, a.docp*a.I)
convert(::Type{Polar}, a::Stokes) = Polar(a.s0, sqrt(a.s1*a.s1 + a.s2*a.s2)/a.s0, atan2(a.s2,a.s1)/2, a.s3/a.s0)

*(a::Stokes,b::AbstractFloat) = Stokes(a.s0*b, a.s1*b, a.s2*b, a.s3*b)

+(a::Stokes,b::Stokes) = Stokes(a.s0 + b.s0, a.s1 + b.s1, a.s2 + b.s2, a.s3 + b.s3)

rotate(a::Polar,b::AbstractFloat) = Polar(a.I,a.dolp,a.aop + b,a.docp)
rotate(a::Stokes,b::AbstractFloat) = Stokes(rotate(Polar(a),b))

function mean(a::Vector{Polar})
	I = mean(map(x -> x.I,a))
	dolp = mean(map(x -> x.dolp,a))
	α = map(x -> x.aop,a)
	aop = atan2(mean(sin(α)),mean(cos(α)))
	docp = mean(map(x -> x.docp,a))
	return Polar(I,dolp,aop,docp)
end

function measurements2stokes(ad, v, d, h, r, l)
	s0 = (v + h + d + ad + r + l)/3
	s1 = v - h
	s2 = d - ad
	s3 = r - l
	return (s0,s1,s2,s3)
end

convert(::Type{Stokes}, ad, v, d, h, r, l) = Stokes(measurements2stokes(ad, v, d, h, r, l)...)
convert(::Type{Polar}, ad, v, d, h, r, l) = Polar(Stokes(ad, v, d, h, r, l))

end


text:
function _precompile_()
    ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
    isdefined(ObjectDetector.YOLO, Symbol("#7#19")) && precompile(Tuple{getfield(ObjectDetector.YOLO, Symbol("#7#19")),Tuple{Int64,Symbol}})
    isdefined(ObjectDetector.YOLO, Symbol("#9#21")) && precompile(Tuple{getfield(ObjectDetector.YOLO, Symbol("#9#21")),Function})
    isdefined(ObjectDetector.YOLO, Symbol("#9#21")) && precompile(Tuple{getfield(ObjectDetector.YOLO, Symbol("#9#21")),Nothing})
    isdefined(ObjectDetector.YOLO, Symbol("#9#21")) && precompile(Tuple{getfield(ObjectDetector.YOLO, Symbol("#9#21")),Tuple{Int64,Symbol}})
    precompile(Tuple{Type{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{4},Axes,F,Args} where Args<:Tuple where F where Axes},typeof(ObjectDetector.YOLO.leaky),Tuple{Array{Float32,4}}})
    precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Float64,1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(ObjectDetector.YOLO.cfgparse),Tuple{Base.Broadcast.Extruded{Array{SubString{String},1},Tuple{Bool},Tuple{Int64}}}},Base.OneTo{Int64},Int64,Int64})
    precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Int64,1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(ObjectDetector.YOLO.cfgparse),Tuple{Base.Broadcast.Extruded{Array{SubString{String},1},Tuple{Bool},Tuple{Int64}}}},Base.OneTo{Int64},Int64,Int64})
    precompile(Tuple{typeof(Base.Broadcast.instantiate),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{4},Nothing,typeof(ObjectDetector.YOLO.leaky),Tuple{Array{Float32,4}}}})
    precompile(Tuple{typeof(ObjectDetector.YOLO.upsample),Array{Float32,4},Int64})
    precompile(Tuple{typeof(ObjectDetector.YOLO.v3_320_COCO)})
    precompile(Tuple{typeof(copy),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{4},NTuple{4,Base.OneTo{Int64}},typeof(ObjectDetector.YOLO.leaky),Tuple{Array{Float32,4}}}})
end


text:
function solve()
    n = parse(Int, readline())
    a = [parse(Int, x) for x in split(readline())]

    ans = zeros(Int, n)
    for i=1:length(a)
        ans[a[i]] += 1
    end

    for x in ans
        println(x)
    end
end

solve()

max_stars_repo_name: aishikawa/atcoder-julia

max_issues_repo_name: aishikawa/atcoder-julia

max_forks_repo_name: aishikawa/atcoder-julia


text:
# Automatically generated using Clang.jl
#! format: off

const FILE = Cvoid

# Skipping MacroDefinition: CEED_QFUNCTION ( name ) static const char name ## _loc [ ] = __FILE__ ":" # name ; static int name

# Skipping MacroDefinition: CeedError ( ceed , ecode , ... ) ( CeedErrorImpl ( ( ceed ) , __FILE__ , __LINE__ , __func__ , ( ecode ) , __VA_ARGS__ ) ? : ( ecode ) )

const CEED_VERSION_MAJOR = 0
const CEED_VERSION_MINOR = 8
const CEED_VERSION_PATCH = 0
const CEED_VERSION_RELEASE = false

# Skipping MacroDefinition: CEED_VERSION_GE ( major , minor , patch ) ( ! CEED_VERSION_RELEASE || ( CEED_VERSION_MAJOR > major || ( CEED_VERSION_MAJOR == major && ( CEED_VERSION_MINOR > minor || ( CEED_VERSION_MINOR == minor && CEED_VERSION_PATCH >= patch ) ) ) ) )

const CeedInt = Int32
const CeedScalar = Cdouble
const Ceed_private = Cvoid
const Ceed = Ptr{Ceed_private}
const CeedRequest_private = Cvoid
const CeedRequest = Ptr{CeedRequest_private}
const CeedVector_private = Cvoid
const CeedVector = Ptr{CeedVector_private}
const CeedElemRestriction_private = Cvoid
const CeedElemRestriction = Ptr{CeedElemRestriction_private}
const CeedBasis_private = Cvoid
const CeedBasis = Ptr{CeedBasis_private}
const CeedQFunction_private = Cvoid
const CeedQFunction = Ptr{CeedQFunction_private}
const CeedQFunctionContext_private = Cvoid
const CeedQFunctionContext = Ptr{CeedQFunctionContext_private}
const CeedOperator_private = Cvoid
const CeedOperator = Ptr{CeedOperator_private}
const CeedErrorHandler = Ptr{Cvoid}

@cenum CeedErrorType::Int32 begin
    CEED_ERROR_SUCCESS = 0
    CEED_ERROR_MINOR = 1
    CEED_ERROR_DIMENSION = 2
    CEED_ERROR_INCOMPLETE = 3
    CEED_ERROR_INCOMPATIBLE = 4
    CEED_ERROR_ACCESS = 5
    CEED_ERROR_MAJOR = -1
    CEED_ERROR_BACKEND = -2
    CEED_ERROR_UNSUPPORTED = -3
end

@cenum CeedMemType::UInt32 begin
    CEED_MEM_HOST = 0
    CEED_MEM_DEVICE = 1
end

@cenum CeedCopyMode::UInt32 begin
    CEED_COPY_VALUES = 0
    CEED_USE_POINTER = 1
    CEED_OWN_POINTER = 2
end

@cenum CeedNormType::UInt32 begin
    CEED_NORM_1 = 0
    CEED_NORM_2 = 1
    CEED_NORM_MAX = 2
end

@cenum CeedTransposeMode::UInt32 begin
    CEED_NOTRANSPOSE = 0
    CEED_TRANSPOSE = 1
end

@cenum CeedEvalMode::UInt32 begin
    CEED_EVAL_NONE = 0
    CEED_EVAL_INTERP = 1
    CEED_EVAL_GRAD = 2
    CEED_EVAL_DIV = 4
    CEED_EVAL_CURL = 8
    CEED_EVAL_WEIGHT = 16
end

@cenum CeedQuadMode::UInt32 begin
    CEED_GAUSS = 0
    CEED_GAUSS_LOBATTO = 1
end

@cenum CeedElemTopology::UInt32 begin
    CEED_LINE = 65536
    CEED_TRIANGLE = 131073
    CEED_QUAD = 131074
    CEED_TET = 196611
    CEED_PYRAMID = 196612
    CEED_PRISM = 196613
    CEED_HEX = 196614
end

const CeedQFunctionUser = Ptr{Cvoid}

# Skipping MacroDefinition: CEED_INTERN CEED_EXTERN __attribute__ ( ( visibility ( "hidden" ) ) )
# Skipping MacroDefinition: CEED_UNUSED __attribute__ ( ( unused ) )

const CEED_MAX_RESOURCE_LEN = 1024
const CEED_MAX_BACKEND_PRIORITY = typemax(Cuint)
const CEED_ALIGN = 64
const CEED_COMPOSITE_MAX = 16
const CEED_EPSILON = 1.0e-16
const CEED_DEBUG_COLOR = 0

# Skipping MacroDefinition: CeedDebug1 ( ceed , format , ... ) CeedDebugImpl ( ceed , format , ## __VA_ARGS__ )
# Skipping MacroDefinition: CeedDebug256 ( ceed , color , ... ) CeedDebugImpl256 ( ceed , color , ## __VA_ARGS__ )
# Skipping MacroDefinition: CeedDebug ( ... ) CeedDebug256 ( ceed , ( unsigned char ) CEED_DEBUG_COLOR , ## __VA_ARGS__ )
# Skipping MacroDefinition: CeedChk ( ierr ) do { int ierr_ = ierr ; if ( ierr_ ) return ierr_ ; } while ( 0 )
# Skipping MacroDefinition: CeedChkBackend ( ierr ) do { int ierr_ = ierr ; if ( ierr_ ) { if ( ierr_ > CEED_ERROR_SUCCESS ) return CEED_ERROR_BACKEND ; else return ierr_ ; } } while ( 0 )
# Skipping MacroDefinition: CeedMalloc ( n , p ) CeedMallocArray ( ( n ) , sizeof ( * * ( p ) ) , p )
# Skipping MacroDefinition: CeedCalloc ( n , p ) CeedCallocArray ( ( n ) , sizeof ( * * ( p ) ) , p )
# Skipping MacroDefinition: CeedRealloc ( n , p ) CeedReallocArray ( ( n ) , sizeof ( * * ( p ) ) , p )

const CeedTensorContract_private = Cvoid
const CeedTensorContract = Ptr{CeedTensorContract_private}
const CeedQFunctionField_private = Cvoid
const CeedQFunctionField = Ptr{CeedQFunctionField_private}
const CeedOperatorField_private = Cvoid
const CeedOperatorField = Ptr{CeedOperatorField_private}

max_stars_repo_name: DiffeoInvariant/libCEED

max_issues_repo_name: DiffeoInvariant/libCEED

max_forks_repo_name: DiffeoInvariant/libCEED


text:
using IterTools.groupby

orderwords(words::Vector) = Dict(w[1][1] => Set(w) for w in groupby(first, words))
longest(a, b) = ifelse(length(a) > length(b), a, b)
function linkfirst(byfirst::Dict, sofar::Vector)
    @assert(!isempty(sofar))
    chmatch = sofar[end][end]
    if ! haskey(byfirst, chmatch) return sofar end
    options = setdiff(byfirst[chmatch], sofar)
    if isempty(options)
        return sofar
    else
        alternatives = ( linkfirst(byfirst, vcat(sofar, word)) for word in options )
        mx = reduce(longest, alternatives)
        return mx
    end
end
function llfl(words)
    byfirst = orderwords(words)
    alternatives = ( linkfirst(byfirst, [word]) for word in words )
    return reduce(longest, alternatives)
end

pokemon = String.(unique(split("""
    audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
    cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
    girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
    kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
    nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
    porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
    sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
    tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
    """)))

l = llfl(pokemon)
println("Example of longest seq.:\n", join(l, ", "))
println("Max length: ", length(l)

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
abstract type AbstractLattice{T,N_ARR,N_CDT} <: AbstractSpace{T,N_ARR,N_CDT} end
(t::Type{<:AbstractLattice})(start, stop, n_points) = t(discrete_lattice(start, stop, n_points))

(t::Type{<:AbstractLattice})(; extent, n_points) = t(.-extent ./ 2, extent ./ 2, n_points)

Base.CartesianIndices(lattice::AbstractLattice) = CartesianIndices(lattice.arr)
Base.step(space::AbstractLattice) = extent(space) ./ (size(space) .- 1)
Base.size(lattice::AbstractLattice) = size(lattice.arr)
Base.size(lattice::AbstractLattice, d::Int) = size(lattice.arr, d)
Base.zeros(lattice::AbstractLattice{T}) where T = zeros(T,size(lattice)...)
start(space::AbstractLattice) = space.arr[1]
stop(space::AbstractLattice) = space.arr[end]
extent(space::AbstractLattice) = stop(space) .- start(space)

"""
    discrete_segment(extent, n_points)

Return an object containing `n_points` equidistant coordinates of a segment of length `extent` centered at 0. If you want 0 to be an element of the segment, make sure `n_points` is odd.

# Example
```jldoctest
julia> seg = discrete_segment(0.0, 5.0, 7);

julia> length(seg) == 7
true

julia> seg[end] - seg[1] ≈ 5.0
true
```
"""
function discrete_segment(start::T, stop::T, n_points::Int) where {T <: Number}
    LinRange{T}(start, stop, n_points)
end
# function discrete_segment(extent::T, n_points::Int) where {T <: Number}
#     discrete_segment(-extent/2,extent/2,n_points)
# end
"""
    coordinates(extent, n_points)

Return an object containing `n_points` equidistant coordinates along each dimension of a grid of length `extent` along each dimension, centered at (0,0,...,0).
"""
# function discrete_lattice(extent::NTuple{N,T}, n_points::NTuple{N,Int}) where {N,T}
#     Iterators.product(discrete_segment.(extent, n_points)...) |> collect
# end
function discrete_lattice(start::Tup, stop::Tup, n_points::IntTup) where {Nminusone,T,Tup<:Tuple{T,Vararg{T,Nminusone}},IT<:Int,IntTup<:Tuple{IT,Vararg{IT,Nminusone}}}
    Iterators.product(discrete_segment.(start, stop, n_points)...) |> collect
end
discrete_lattice(start::T, stop::T, n_points::Int) where T = discrete_lattice((start,), (stop,), (n_points,))
coordinates(lattice::AbstractLattice) = lattice.arr
coordinate_axes(lattice::AbstractLattice) = (discrete_segment.(start(lattice), stop(lattice), size(lattice))...,)

using Statistics
# @recipe function f(lattice::AbstractLattice, values::AbstractArray{<:AbstractArray,1})
#     standard_deviations = std.(values)
#     means = mean.(values)
#     up_stds = means .+ standard_deviations
#     down_stds = means .- standard_deviations
#     seriestype := :line
#     @series begin
#         linestyle := [:dot :dot :solid]
#         (lattice, hcat(up_stds, down_stds, means))
#     end
# end

# @recipe function f(lattice::AbstractLattice{T,1}, values; val_lim=nothing) where T
#     x := coordinate_axes(lattice)[1] |> collect
#     y := values
#     seriestype := :line
#     if val_lim != nothing
#         ylim := val_lim
#     end
#     ()
# end
#
# @recipe function f(lattice::AbstractLattice{T,2}, values::Array{T,2}; val_lim=nothing) where T
#     (x, y) = coordinate_axes(lattice) .|> collect
#     seriestype := :heatmap
#     if val_lim != nothing
#         clim := val_lim
#         zlim := val_lim
#     end
#     aspect_ratio := :equal
#     (x,y,values)
# end


text:
module _Algebra

using Base.Test
using Brainstorm
using Nemo

include("group.jl")
include("field.jl")

function test_all()
    test_group_all()
    test_field_all()
end

end