Skip to content

Commit

Permalink
Bump dependencies (oscar-system#3071)
Browse files Browse the repository at this point in the history
  • Loading branch information
thofma authored Dec 8, 2023
1 parent 32b7e89 commit 503d48c
Show file tree
Hide file tree
Showing 31 changed files with 59 additions and 408 deletions.
10 changes: 5 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
cohomCalg_jll = "5558cf25-a90e-53b0-b813-cadaa3ae7ade"

[compat]
AbstractAlgebra = "0.33.0"
AlgebraicSolving = "0.3.6"
AbstractAlgebra = "0.34.5"
AlgebraicSolving = "0.4.2"
Distributed = "1.6"
DocStringExtensions = "0.8, 0.9"
GAP = "0.10.0"
Hecke = "0.22.7"
Hecke = "0.23.0"
JSON = "^0.20, ^0.21"
JSON3 = "1.13.2"
LazyArtifacts = "1.6"
Nemo = "0.37.5"
Nemo = "0.38.0"
Pkg = "1.6"
Polymake = "0.11.8"
Preferences = "1"
Random = "1.6"
RandomExtensions = "0.4.3"
Serialization = "1.6"
Singular = "0.20.0"
Singular = "0.21.0"
TOPCOM_jll = "0.17.8"
UUIDs = "1.6"
cohomCalg_jll = "0.32.0"
Expand Down
2 changes: 1 addition & 1 deletion experimental/BasisLieHighestWeight/src/MainAlgorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function basis_lie_highest_weight_compute(
operators, [asVec(v) for v in operators], weights_w, weights_alpha
)

ZZx, _ = PolynomialRing(ZZ, length(operators)) # for our monomials
ZZx, _ = polynomial_ring(ZZ, length(operators)) # for our monomials
monomial_ordering = get_monomial_ordering(monomial_ordering_symb, ZZx, weights_alpha)

# save computations from recursions
Expand Down
2 changes: 1 addition & 1 deletion experimental/BasisLieHighestWeight/test/MBOld.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function basisLieHighestWeight(t::String, n::Int, hw::Vector{Int}; roots=[]) #--
hwv = sparse_row(ZZ, [(1, 1)])

monomials = compute(hwv, mats, wts)
ZZx, x = PolynomialRing(ZZ, length(monomials[1]))
ZZx, x = polynomial_ring(ZZ, length(monomials[1]))
monomials = [
finish(push_term!(MPolyBuildCtx(ZZx), ZZ(1), Int.(mon))) for mon in monomials
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
weight = BasisLieHighestWeight.weight
calc_vec = BasisLieHighestWeight.calc_vec

ZZx, _ = PolynomialRing(ZZ, 2)
ZZx, _ = polynomial_ring(ZZ, 2)
x = gens(ZZx)
mon1 = ZZx(1)
mon2 = x[1]^2 * x[2]
Expand Down
2 changes: 1 addition & 1 deletion experimental/DoubleAndHyperComplexes/src/vector_spaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function (fac::VerticalTensorMapFactory{AbstractAlgebra.Generic.ModuleHomomorphi
end

R = base_ring(B)
res_mat = zero(MatrixSpace(R, r1i*nrows(B), r1i*ncols(B)))
res_mat = zero_matrix(R, r1i*nrows(B), r1i*ncols(B))
for ii in 1:nrows(B)
for jj in 1:ncols(B)
for k in 1:r1i
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ julia> v = ambient_space(t)
A family of spaces of dimension d = 5
julia> coordinate_ring(v)
Multivariate polynomial ring in 9 variables Kbar, w, a1, a21..., z
Multivariate polynomial ring in 9 variables Kbar, w, a1, a21, ..., z
over rational field
```
It is also possible to construct a literature model over a particular base.
Expand Down
10 changes: 5 additions & 5 deletions experimental/FTheoryTools/src/auxiliary.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ function _ambient_space(base::NormalToricVariety, fiber_ambient_space::NormalTor
fiber_cones = matrix(ZZ, ray_indices(maximal_cones(fiber_ambient_space)))

# Compute the u-matrix
base_weights = transpose(vcat([elem.coeff for elem in cox_ring(base).d]))
m1 = transpose(vcat([divisor_class(D1).coeff, divisor_class(D2).coeff]))
base_weights = transpose(reduce(vcat, [elem.coeff for elem in cox_ring(base).d]))
m1 = transpose(reduce(vcat, [divisor_class(D1).coeff, divisor_class(D2).coeff]))
m2 = fiber_rays[1:2,:]
u_matrix = solve(base_weights,(-1)*m1*m2)

# Form the rays of the toric ambient space
new_base_rays = hcat(base_rays, u_matrix)
new_fiber_rays = hcat(zero_matrix(ZZ, nrows(fiber_rays), ncols(base_rays)), fiber_rays)
ambient_space_rays = vcat(new_base_rays, new_fiber_rays)
ambient_space_rays = vcat([[k for k in ambient_space_rays[i,:]] for i in 1:nrows(ambient_space_rays)]...)
ambient_space_rays = reduce(vcat, [[k for k in ambient_space_rays[i,:]] for i in 1:nrows(ambient_space_rays)])

# Construct the incidence matrix for the maximal cones of the ambient space
ambient_space_max_cones = []
Expand All @@ -94,7 +94,7 @@ function _ambient_space(base::NormalToricVariety, fiber_ambient_space::NormalTor
ambient_space_grading[i,j] = base_weights[j,i]
end
end
fiber_weights = transpose(vcat([elem.coeff for elem in cox_ring(fiber_ambient_space).d]))
fiber_weights = transpose(reduce(vcat, [elem.coeff for elem in cox_ring(fiber_ambient_space).d]))
for i in 1:ncols(fiber_weights)
for j in 1:nrows(fiber_weights)
ambient_space_grading[i + nrows(base_rays),j + nrows(base_weights)] = fiber_weights[j,i]
Expand Down Expand Up @@ -377,7 +377,7 @@ function _construct_generic_sample(base_grading::Matrix{Int64}, base_vars::Vecto
base_space = family_of_spaces(polynomial_ring(QQ, base_vars, cached = false)[1], base_grading, d)
ambient_space_vars = vcat(base_vars, coordinate_names(fiber_ambient_space))
coordinate_ring_ambient_space = polynomial_ring(QQ, ambient_space_vars, cached = false)[1]
w = Matrix{Int64}(vcat([k.coeff for k in cox_ring(fiber_ambient_space).d]))
w = Matrix{Int64}(reduce(vcat, [k.coeff for k in cox_ring(fiber_ambient_space).d]))
z_block = zeros(Int64, ncols(w), ncols(base_grading))
D_block = [D1 D2 zeros(Int64, nrows(base_grading), nrows(w)-2)]
ambient_space_grading = [base_grading D_block; z_block w']
Expand Down
2 changes: 1 addition & 1 deletion experimental/GModule/Cohomology.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,7 @@ function Oscar.hom(V::Module, W::Module, v::Vector{<:ModuleElem}; check::Bool =
if ngens(V) == 0
return Generic.ModuleHomomorphism(V, W, zero_matrix(base_ring(V), ngens(V), ngens(W)))
end
return Generic.ModuleHomomorphism(V, W, vcat([x.v for x = v]))
return Generic.ModuleHomomorphism(V, W, reduce(vcat, [x.v for x = v]))
end
function Oscar.hom(V::Module, W::Module, v::MatElem; check::Bool = true)
return Generic.ModuleHomomorphism(V, W, v)
Expand Down
6 changes: 3 additions & 3 deletions experimental/GModule/GModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ function trivial_gmodule(G::Oscar.GAPGroup, M::Union{GrpAbFinGen, AbstractAlgebr
end

function Oscar.gmodule(::Type{AnticNumberField}, M::GModule{<:Oscar.GAPGroup, <:AbstractAlgebra.FPModule{nf_elem}})
k, mk = Hecke.subfield(base_ring(M), vec(collect(vcat(map(matrix, M.ac)...))))
k, mk = Hecke.subfield(base_ring(M), vec(collect(reduce(vcat, map(matrix, M.ac)))))
if k != base_ring(M)
F = free_module(k, dim(M))
return gmodule(group(M), [hom(F, F, map_entries(pseudo_inv(mk), matrix(x))) for x = M.ac])
Expand Down Expand Up @@ -1287,7 +1287,7 @@ end
function hom_base(C::_T, D::_T) where _T <: GModule{<:Any, <:AbstractAlgebra.FPModule{ZZRingElem}}

h = hom_base(gmodule(QQ, C), gmodule(QQ, D))
H = vcat([integral_split(matrix(QQ, 1, dim(C)^2, vec(collect(x))), ZZ)[1] for x = h]...)
H = reduce(vcat, [integral_split(matrix(QQ, 1, dim(C)^2, vec(collect(x))), ZZ)[1] for x = h])
H = Hecke.saturate(H)
return [matrix(ZZ, dim(C), dim(C), vec(collect(H[i, :]))) for i=1:nrows(H)]
end
Expand Down Expand Up @@ -1332,7 +1332,7 @@ end
function invariant_forms(C::GModule{<:Any, <:AbstractAlgebra.FPModule})
D = Oscar.dual(C)
h = hom_base(C, D)
r, k = kernel(transpose(vcat([matrix(base_ring(C), 1, dim(C)^2, vec(x-transpose(x))) for x = h]...)))
r, k = kernel(transpose(reduce(vcat, [matrix(base_ring(C), 1, dim(C)^2, vec(x-transpose(x))) for x = h])))
return [sum(h[i]*k[i, j] for i=1:length(h)) for j=1:r]
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ function realization_space(
q::Union{Int,Nothing}=nothing,
ground_ring::Ring=ZZ
)::MatroidRealizationSpace
if char != nothing && !isprime(char) && char != 0
if char != nothing && !is_prime(char) && char != 0
error("The characteristic has to be 0 or a prime number.")
end

Expand Down Expand Up @@ -355,7 +355,7 @@ function realization_space(

if total_degree(col_det) <= 0
if col_det != 0 && col in Bs
if isunit(col_det)
if is_unit(col_det)
continue
end
elseif col_det != 0 # and col is not a basis
Expand Down Expand Up @@ -645,7 +645,7 @@ end
# v is replaced by t in f
function sub_map(v::RingElem, t::RingElem, R::MPolyRing, xs::Vector{<:RingElem})
xs_v = map(x -> x == v ? t : x, xs)
return hom(R, FractionField(R), a -> a, xs_v)
return hom(R, fraction_field(R), a -> a, xs_v)
end

# replace v by t in f, only return the numerator.
Expand Down
6 changes: 3 additions & 3 deletions experimental/MatroidRealizationSpaces/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@
@test Oscar.n_new_Igens(y,t,[y^3-x-2, y+z^3], newSgens ,R,[x,y,z]) == [x^7 + 2*x^6 - z^9 + 18*z^6 - 108*z^3 + 216, x^2*z^3 + z^3 - 6]
end

X = matrix(FractionField(R), [x//(z-1) y//(x+1) z; -y+1 x//z 2*x*y ])
X = matrix(fraction_field(R), [x//(z-1) y//(x+1) z; -y+1 x//z 2*x*y ])

@testset "matrix_clear_den_in_col" begin
@test Oscar.matrix_clear_den_in_col(X, 2) == matrix(FractionField(R), [x//(z-1) y*z z; -y+1 x^2+x 2*x*y])
@test Oscar.matrix_clear_den_in_col(X, 2) == matrix(fraction_field(R), [x//(z-1) y*z z; -y+1 x^2+x 2*x*y])
end

@testset "matrix_clear_den" begin
@test Oscar.matrix_clear_den(X) == matrix(FractionField(R), [x y*z z; (-y+1)*(z-1) x^2+x 2*x*y])
@test Oscar.matrix_clear_den(X) == matrix(fraction_field(R), [x y*z z; (-y+1)*(z-1) x^2+x 2*x*y])
end


Expand Down
6 changes: 3 additions & 3 deletions experimental/ModStd/ModStdQt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -604,16 +604,16 @@ function Oscar.factor_absolute(f::MPolyRingElem{Generic.Frac{QQMPolyRingElem}})
Qt = base_ring(base_ring(Qtx)) # Q[t1,t2]
Rx, x = polynomial_ring(QQ, ngens(Qtx) + ngens(Qt)) # Q[x1,x2,t1,t2]
# write f = cont*F, cont in Qt, F in Rx
F, cont = Oscar._remove_denominators(Rx, f)
F, cont = Oscar.AbstractAlgebra._remove_denominators(Rx, f)
lF = factor(F)
an = []
push!(an, Qtx(cont)*Oscar._restore_numerators(Qtx, lF.unit))
push!(an, Qtx(cont)*Oscar.AbstractAlgebra._restore_numerators(Qtx, lF.unit))
K = base_ring(f)
Kt, t = polynomial_ring(K, "t", cached = false)
for (k, e) = sort(collect(lF), lt = (a,b) -> _cmp(a[1], b[1]) <= 0)
res = afact(k, collect(ngens(Qtx)+1:ngens(Qtx)+ngens(Qt)))
if res === nothing
push!(an, (Oscar._restore_numerators(Qtx, k), parent(k)(1), e))
push!(an, (Oscar.AbstractAlgebra._restore_numerators(Qtx, k), parent(k)(1), e))
continue
end
p, c, ex = res
Expand Down
2 changes: 0 additions & 2 deletions experimental/Schemes/ProjectiveModules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ function annihilator(M::SubquoModule)
return I
end

iszero(I::Ideal) = all(x->(iszero(x)), gens(I))

@doc raw"""
is_projective(M::SubquoModule)
Expand Down
2 changes: 1 addition & 1 deletion experimental/SymmetricIntersections/src/representations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1059,7 +1059,7 @@ function _has_pfr(G::Oscar.GAPGroup, dim::Int)
G_gap = G.X
f_gap = GG.EpimorphismSchurCover(G_gap)
H_gap = GG.Source(f_gap)
n, p = ispower(GG.Size(H_gap))
n, p = is_power(GG.Size(H_gap))
if is_prime(p)
fff_gap = GG.EpimorphismPGroup(H_gap, p)
E_gap = fff_gap(H_gap)
Expand Down
4 changes: 2 additions & 2 deletions src/AlgebraicGeometry/Surfaces/K3Auto.jl
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ function separating_hyperplanes(gram::QQMatrix, v::QQMatrix, h::QQMatrix, d)
S = QQMatrix[]
h = change_base_ring(QQ, h)
rho = abs(d)*ch^-1
t,sqrtho = issquare_with_sqrt(rho)
t,sqrtho = is_square_with_sqrt(rho)
if t
r = sqrtho*h
if denominator(r)==1 && (r*gram*transpose(h))[1,1]>0 && (r*gram*transpose(v))[1,1] < 0
Expand All @@ -641,7 +641,7 @@ function separating_hyperplanes(gram::QQMatrix, v::QQMatrix, h::QQMatrix, d)
for (x,_) in short_vectors_iterator(LQ, abs(d*denominator(Q)))
rp = matrix(ZZ, 1, nrows(Q), x)*bW
rho = abs(d - (rp*gram*transpose(rp))[1,1])*ch^-1
t,rho = issquare_with_sqrt(rho)
t,rho = is_square_with_sqrt(rho)
if !t
continue
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ function normal_toric_variety_from_star_triangulation(P::Polyhedron)
max_cones = IncidenceMatrix([[c[i]-1 for i in 2:length(c)] for c in _find_full_star_triangulation(pts)])

# Rays are all but the zero vector at the first position of pts
integral_rays = vcat([pts[k,:] for k in 2:nrows(pts)])
integral_rays = reduce(vcat, [pts[k,:] for k in 2:nrows(pts)])

# construct the variety
return normal_toric_variety(max_cones, integral_rays; non_redundant = true)
Expand Down Expand Up @@ -290,7 +290,7 @@ function normal_toric_varieties_from_star_triangulations(P::Polyhedron)
trias = star_triangulations(pts; full = true)

# rays are all but the zero vector at the first position of pts
integral_rays = vcat([pts[k,:] for k in 2:nrows(pts)])
integral_rays = reduce(vcat, [pts[k,:] for k in 2:nrows(pts)])

# trias contains the max_cones as list of lists
# (a) needs to be converted to incidence matrix
Expand Down Expand Up @@ -406,7 +406,7 @@ function normal_toric_varieties_from_glsm(charges::ZZMatrix)
pts = vcat(matrix(QQ, transpose(zero)), matrix(QQ, pts))

# construct varieties
integral_rays = vcat([pts[k,:] for k in 2:nrows(pts)])
integral_rays = reduce(vcat, [pts[k,:] for k in 2:nrows(pts)])
max_cones = [IncidenceMatrix([[c[i]-1 for i in 2:length(c)] for c in t]) for t in star_triangulations(pts; full = true)]
varieties = [normal_toric_variety(cones, integral_rays; non_redundant = true) for cones in max_cones]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Map
for i in 1:nrows(images)
v = [images[i,k] for k in 1:ncols(images)]
j = findfirst(x -> x == true, [(v in maximal_cones(cod)[j]) for j in 1:n_maximal_cones(cod)])
m = vcat([Int(ray_indices(maximal_cones(cod))[j, k]) * cod_rays[k, :] for k in 1:nrays(cod)])
m = reduce(vcat, [Int(ray_indices(maximal_cones(cod))[j, k]) * cod_rays[k, :] for k in 1:nrays(cod)])
mapping_matrix = hcat(mapping_matrix, solve(transpose(m), transpose(images[i, :])))
end
return hom(torusinvariant_weil_divisor_group(d), torusinvariant_weil_divisor_group(cod), transpose(mapping_matrix))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function turn_denominator_into_polyhedron(variety::NormalToricVarietyType, monom

# (2) compute generators of the semigroup
weights = [k.coeff for k in Oscar._cox_ring_weights(variety)]
gens = vcat(unique([(-1)^Int(present_variables[i])*weights[i] for i in 1:length(present_variables)]))
gens = reduce(vcat, unique([(-1)^Int(present_variables[i])*weights[i] for i in 1:length(present_variables)]))

# (3) compute offset
offset = zero(parent(weights[1]))
Expand Down
10 changes: 5 additions & 5 deletions src/Groups/matrices/form_group.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function invariant_bilinear_forms(G::MatrixGroup{S,T}) where {S,T}
push!(M,MM)
end

r,K = nullspace(vcat(M))
r,K = nullspace(reduce(vcat, M))

return [matrix(F,n,n,[K[i,j] for i in 1:n^2]) for j in 1:r]
end
Expand Down Expand Up @@ -67,7 +67,7 @@ function invariant_sesquilinear_forms(G::MatrixGroup{S,T}) where {S,T}
push!(M,MM)
end

r,K = nullspace(vcat(M))
r,K = nullspace(reduce(vcat, M))

return [matrix(F,n,n,[K[i,j] for i in 1:n^2]) for j in 1:r]
end
Expand Down Expand Up @@ -100,7 +100,7 @@ function invariant_quadratic_forms(G::MatrixGroup{S,T}) where {S,T}
push!(M,MM)
end

r,K = nullspace(vcat(M))
r,K = nullspace(reduce(vcat, M))
M = T[]
for i in 1:r
push!(M,upper_triangular_matrix(K[1:div(n*(n+1),2),i]))
Expand Down Expand Up @@ -155,7 +155,7 @@ function invariant_alternating_forms(G::MatrixGroup{S,T}) where {S,T}
push!(M,MM)
end

r,K = nullspace(vcat(M))
r,K = nullspace(reduce(vcat, M))

L = T[]
for j in 1:r
Expand Down Expand Up @@ -373,7 +373,7 @@ function invariant_hermitian_forms(G::MatrixGroup{S,T}) where {S,T}
end
end

n_gens,K = nullspace(vcat(M))
n_gens,K = nullspace(reduce(vcat, M))
N = div(n*(n-1),2)
L = T[]

Expand Down
2 changes: 1 addition & 1 deletion src/Modules/UngradedModules/FreeModElem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ end

# A special method for the case where we can safely assume
# that the coordinates of elements allow hashing.
function hash(a::AbstractFreeModElem{<:MPolyElem{<:FieldElem}}, h::UInt)
function hash(a::AbstractFreeModElem{<:MPolyRingElem{<:FieldElem}}, h::UInt)
b = 0xaa2ba4a32dd0b431 % UInt
h = hash(typeof(a), h)
h = hash(parent(a), h)
Expand Down
2 changes: 1 addition & 1 deletion src/Modules/UngradedModules/SubQuoHom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function (==)(f::ModuleFPHom, g::ModuleFPHom)
return true
end

function Base.hash(f::ModuleFPHom{T}, h::UInt) where {U<:FieldElem, S<:MPolyElem{U}, T<:ModuleFP{S}}
function Base.hash(f::ModuleFPHom{T}, h::UInt) where {U<:FieldElem, S<:MPolyRingElem{U}, T<:ModuleFP{S}}
b = 0x535bbdbb2bc54b46 % UInt
h = hash(typeof(f), h)
h = hash(domain(f), h)
Expand Down
6 changes: 3 additions & 3 deletions src/Modules/UngradedModules/SubquoModuleElem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ end

#######################################################

function simplify(el::SubquoModuleElem{<:MPolyElem{<:FieldElem}})
function simplify(el::SubquoModuleElem{<:MPolyRingElem{<:FieldElem}})
el.is_reduced && return el
!isdefined(parent(el), :quo) && return el
iszero(parent(el).quo) && return el
Expand All @@ -105,7 +105,7 @@ function simplify(el::SubquoModuleElem{<:MPolyElem{<:FieldElem}})
return result
end

function simplify!(el::SubquoModuleElem{<:MPolyElem{<:FieldElem}})
function simplify!(el::SubquoModuleElem{<:MPolyRingElem{<:FieldElem}})
el.is_reduced && return el
!isdefined(parent(el), :quo) && return el
iszero(parent(el).quo) && return el
Expand Down Expand Up @@ -387,7 +387,7 @@ function Base.hash(a::SubquoModuleElem)
return xor(h, b)
end

function Base.hash(a::SubquoModuleElem{<:MPolyElem{<:FieldElem}}, h::UInt)
function Base.hash(a::SubquoModuleElem{<:MPolyRingElem{<:FieldElem}}, h::UInt)
b = 0xaa2ba4a32dd0b431 % UInt
h = hash(typeof(a), h)
h = hash(parent(a), h)
Expand Down
4 changes: 4 additions & 0 deletions src/Rings/AbelianClosure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
# as a primitive n-th root. to change between these two options, use
# PCharSaturateAll with allroots or allrootsNew (change this in the code)

abstract type CyclotomicField end

export CyclotomicField

module AbelianClosure

using ..Oscar
Expand Down
Loading

0 comments on commit 503d48c

Please sign in to comment.