text:
module OnedWrapper

using JavaCall

const AbstractRegion = @jimport org.hipparchus.geometry.partitioning.AbstractRegion
const AbstractSubHyperplane = @jimport org.hipparchus.geometry.partitioning.AbstractSubHyperplane
const Arc = @jimport org.hipparchus.geometry.spherical.oned.Arc
const ArcsSet = @jimport org.hipparchus.geometry.spherical.oned.ArcsSet
const ArcsSet_Split = @jimport org.hipparchus.geometry.spherical.oned.ArcsSet$Split
const BSPTree = @jimport org.hipparchus.geometry.partitioning.BSPTree
const BoundaryProjection = @jimport org.hipparchus.geometry.partitioning.BoundaryProjection
const Class = @jimport java.lang.Class
const Collection = @jimport java.util.Collection
const Consumer = @jimport java.util.function.Consumer
const Hyperplane = @jimport org.hipparchus.geometry.partitioning.Hyperplane
const Iterable = @jimport java.lang.Iterable
const JIterator = @jimport java.util.Iterator
const JString = @jimport java.lang.String
const JVector = @jimport org.hipparchus.geometry.Vector
const LimitAngle = @jimport org.hipparchus.geometry.spherical.oned.LimitAngle
const List = @jimport java.util.List
const Object = @jimport java.lang.Object
const Point = @jimport org.hipparchus.geometry.Point
const Region = @jimport org.hipparchus.geometry.partitioning.Region
const Region_Location = @jimport org.hipparchus.geometry.partitioning.Region$Location
const S1Point = @jimport org.hipparchus.geometry.spherical.oned.S1Point
const Space = @jimport org.hipparchus.geometry.Space
const Sphere1D = @jimport org.hipparchus.geometry.spherical.oned.Sphere1D
const Spliterator = @jimport java.util.Spliterator
const SubHyperplane = @jimport org.hipparchus.geometry.partitioning.SubHyperplane
const SubHyperplane_SplitSubHyperplane = @jimport org.hipparchus.geometry.partitioning.SubHyperplane$SplitSubHyperplane
const SubLimitAngle = @jimport org.hipparchus.geometry.spherical.oned.SubLimitAngle
const Transform = @jimport org.hipparchus.geometry.partitioning.Transform
const Vector2D = @jimport org.hipparchus.geometry.euclidean.twod.Vector2D

export Arc
export ArcsSet
export LimitAngle
export S1Point
export Sphere1D
export SubLimitAngle
export apply_transform
export as_list
export build_new
export check_point
export check_tolerance
export contains
export copy_self
export distance
export empty_hyperplane
export equals
export for_each
export get_alpha
export get_barycenter
export get_boundary_size
export get_class
export get_dimension
export get_hyperplane
export get_inf
export get_instance
export get_location
export get_offset
export get_remaining_region
export get_reverse
export get_size
export get_space
export get_sub_space
export get_sup
export get_tolerance
export get_tree
export get_vector
export hash_code
export intersection
export is_direct
export is_empty
export is_full
export is_na_n
export iterator
export notify
export notify_all
export project
export project_to_boundary
export reunite
export same_orientation_as
export split
export spliterator
export to_string
export wait
export whole_hyperplane
export whole_space

include("arc.jl")
include("arcs_set.jl")
include("limit_angle.jl")
include("s1_point.jl")
include("sphere1_d.jl")
include("sub_limit_angle.jl")

end


text:
"""
agent_stock_interaction.jl
Functions for interaction between the structured stock-level and agent-level model components
"""

function spawn!(agent_db::DataFrame, StockDB::StockDB, StockAssumptions::StockAssumptions, EnvironmentAssumptions::EnvironmentAssumptions, cohort::Int, carryingcapacity::Float64)
  """
  This function creates a new cohort of agents based on an structured adult population, spawning area information contained in a `EnvironmentAssumptions`, and `StockAssumptions`.
  """
  if isnan(StockAssumptions.fecunditycompensation)
    compensation_factor_a = 1
  else
    compensation_factor_a = 2*(1-cdf(Normal(carryingcapacity, carryingcapacity/StockAssumptions.fecunditycompensation), sum(StockDB.population[end,:][1,])))
  end
  @assert(0.01 < compensation_factor_a < 1.99, "Population regulation has failed, respecify simulation parameters")
  if isnan(StockAssumptions.maturitycompensation)
    compensation_factor_b = 1
  else
    compensation_factor_b = 2*(cdf(Normal(carryingcapacity, carryingcapacity/StockAssumptions.maturitycompensation), sum(StockDB.population[end,:][1,])))
  end
  @assert(0.01 < compensation_factor_b < 1.99, "Population regulation has failed, respecify simulation parameters")
  brood_size = rand(Poisson(compensation_factor_a*StockAssumptions.broodsize[1]), rand(Binomial(StockDB.population[end,1], cdf(Binomial(length(StockAssumptions.broodsize)+2, min(1, compensation_factor_b*StockAssumptions.halfmature/(length(StockAssumptions.broodsize)+2))), 2)*0.5)))
  for i = 2:length(StockAssumptions.broodsize)
    append!(brood_size, rand(Poisson(compensation_factor_a*StockAssumptions.broodsize[i]), rand(Binomial(StockDB.population[end,i], cdf(Binomial(length(StockAssumptions.broodsize)+2, min(1, compensation_factor_b*StockAssumptions.halfmature/(length(StockAssumptions.broodsize)+2))), i+1)*0.5))))
  end
  brood_location = sample(find(EnvironmentAssumptions.spawning), length(brood_size))
  agent_db[cohort,1] = DataFrame(stage=fill(1, length(brood_size)), location=brood_location, alive=brood_size, dead_natural=fill(0, length(brood_size)), dead_risk=fill(0, length(brood_size)))
  return agent_db
end

function graduate!(agent_db::DataFrame, StockDB::StockDB, AgentAssumptions::AgentAssumptions, cohort::Int, week::Int, column::Int)
  """
  This function will advance an agent currently in a specified stage to its next life stage. If this function is applied to juveniles, it will also add their information to the StockDB
  """
  if any(AgentAssumptions.growth .== week)
    for i = 1:length(agent_db[cohort, column][:stage])
      if week == AgentAssumptions.growth[agent_db[cohort, column][:stage][i]]
        agent_db[cohort, column][:stage][i] += 1
        if week == AgentAssumptions.growth[end]
          StockDB.population[end, 1] += agent_db[cohort, column][:alive][i]
        end
      end
    end
  end
end

ext: jl


text:
@testset "ResidueRingMultGrp" begin

  function verify_order(g::Hecke.NfOrdQuoRingElem,o)
    g == 0 && return false
    g^o == 1 || return false
    for l in keys(factor(o).fac)
      g^div(o,l) == 1 && return false
    end
    return true
  end

  function verify_order(g,i,o)
    iszero(g) && return false
    powermod(g,o,i.gen_one) - 1 in i || return false
    for l in keys(factor(o).fac)
      powermod(g,div(o,l),i.gen_one) - 1  in i && return false
    end
    return true
  end

  @testset "multiplicative_group" begin
     Qx,  x = PolynomialRing(FlintQQ, "x");

    @testset "K = Q" begin
      K,  a = NumberField(x,"a");
      O = maximal_order(K)

      @testset "m0 = <$n>" for n in 1:50
        m0 = O(n)*O
        Q = NfOrdQuoRing(O, m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i],SNF[i])
        end
        H = Hecke.multgrp_of_cyclic_grp(n)
        @test Hecke.isisomorphic(G, H)
        @test M(G(G.snf)) == Q(1)
        for g in gens
          for exp in -5:10
            el = g^exp
            @test M(M\el) == el
          end
        end
      end

      @testset "m0 = <1361>^3000" begin
        m0 = ideal(O,O(1361))^100
        Q = NfOrdQuoRing(O,m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i],SNF[i])
        end
        @test M(G(G.snf)) == Q(O(1))
        for g in gens
          for exp in -5:10
            el = g^exp
            @test M(M\el) == el
          end
        end
      end

    end

    @testset "K = Q[√2]" begin
       K,  a = NumberField(x^2 - 2,"a")
      O = maximal_order(K)

      @testset "m0 = <$n>" for n in 1:100
        m0 = ideal(O,O(n))
        Q = NfOrdQuoRing(O,m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i], SNF[i])
        end
        @test M(G(G.snf)) == Q(O(1))
        for g in gens
          for exp in -5:10
            el = g^exp
            @test M(M\el) == el
          end
        end
      end
    end

    @testset "f = x^2-x+15" begin
      f = x^2-x+15
       K,  a = NumberField(f,"a");
      O = maximal_order(K)

      @testset "m0 = <2>" begin
        m0 = ideal(O,O(2))
        Q = NfOrdQuoRing(O,m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i],SNF[i])
        end
        @test order(G) == 3
        H = abelian_group([ 3 ])
        @test Hecke.isisomorphic(G,H)
        @test M(G(G.snf)) == Q(O(1))
        for g in gens
          for exp in -5:10
            el = g^exp
            @test M(M\el) == el
          end
        end
      end

      @testset "m0 = <4>" begin
        m0 = ideal(O,O(4))
        Q = NfOrdQuoRing(O,m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i],SNF[i])
        end
        @test order(G) == 12
        H = abelian_group([ 3, 2, 2 ])
        @test Hecke.isisomorphic(G,H)
        @test M(G(G.snf)) == Q(O(1))
        for g in gens
          for exp in -5:10
            el = g^exp
            @test M(M\el) == el
          end
          el = g^(-8)
          @test M(M\el) == el
        end
      end

      @testset "m0 = <5>" begin
        m0 = ideal(O,O(5))
        Q = NfOrdQuoRing(O,m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i], SNF[i])
        end
        @test M(G(G.snf)) == Q(O(1))
        @test order(G) == 16
        H = abelian_group([4, 4])
        @test Hecke.isisomorphic(G,H)
        for g in gens
          for exp in [ -3, 2, 4 ]
            el = g^exp
            @test M(M\el) == el
          end
        end
      end

      @testset "m0 = <20>" begin
        m0 = ideal(O,O(20))
        Q = NfOrdQuoRing(O,m0)
        G, M = multiplicative_group(Q)
        @test issnf(G)
        SNF = G.snf
        gens = M.generators
        @test length(SNF) == length(gens)
        for i in 1:length(gens)
          @test verify_order(gens[i],SNF[i])
        end
        @test M(G(G.snf)) == Q(O(1))
        @test order(G) == 192
        H = abelian_group([3, 2, 2, 4, 4])
        @test Hecke.isisomorphic(G,H)
        for g in gens
          for exp in [ -4, 1, 7 ]
            el = g^exp
            @test M(M\el) == el
          end
        end
      end
    end

    @testset "x^12+..." begin
      #= f = x^12+7*x^11-97*x^10-859*x^9+2558*x^8+38839*x^7+30012*x^6-710649*x^5-2189082*x^4+2534629*x^3+25314673*x^2+43623088*x+28168151 =#
      #=  K,  a = NumberField(f,"a"); =#
      #= O = maximal_order(K) =#

      #= @testset "m0 = <3>" begin =#
      #=   println("m0 = <3>") =#
      #=   m0 = ideal(O,O(3)) =#
      #=   Q = NfOrdQuoRing(O,m0) =#
      #=   G = domain(Hecke.multiplicative_group(Q)) =#
      #=   println(snf(G)[1].snf) =#
      #=   @test order(G) == 512000 =#
      #=   structt = [80,80,80] =#
      #=   H = abelian_group(structt) =#
      #=   @test Hecke.is_isomorphic(G,H) =#
      #=   @test M(G(G.snf)) == Q(O(1)) =#
      #=   for g in gens =#
      #=     for exp in -5:10 =#
      #=       el = g^exp =#
      #=       @assert M(M\el) == el =#
      #=     end =#
      #=   end =#
      #= end =#

      #= @testset "m0 = <4>" begin =#
      #=   println("m0 = <4>") =#
      #=   m0 = ideal(O,O(4)) =#
      #=   Q = NfOrdQuoRing(O,m0) =#
      #=   G = domain(Hecke.multiplicative_group(Q)) =#
      #=   println(snf(G)[1].snf) =#
      #=   @test order(G) == 14745600 =#
      #=   structt = [15,2,2,2,2,15,4,4,4,4,2,2,2,2] =#
      #=   H = abelian_group(structt) =#
      #=   @test Hecke.is_isomorphic(G,H) =#
      #=   @test M(G(G.snf)) == Q(O(1)) =#
      #=   for g in gens =#
      #=     for exp in -5:10 =#
      #=       el = g^exp =#
      #=       @assert M(M\el) == el =#
      #=     end =#
      #=   end =#
      #= end =#

      #= @testset "m0 = <5>" begin =#
      #=   println("m0 = <5>") =#
      #=   m0 = ideal(O,O(5)) =#
      #=   Q = NfOrdQuoRing(O,m0) =#
      #=   G = domain(Hecke.multiplicative_group(Q)) =#
      #=   println(snf(G)[1].snf) =#
      #=   @test order(G) == 187500000 =#
      #=   structt = [24,5,5,5,5,5,5,4,5,5,5] =#
      #=   H = abelian_group(structt) =#
      #=   @test Hecke.is_isomorphic(G,H) =#
      #=   @test M(G(G.snf)) == Q(O(1)) =#
      #=   for g in gens =#
      #=     for exp in -5:10 =#
      #=       el = g^exp =#
      #=       @assert M(M\el) == el =#
      #=     end =#
      #=   end =#
      #= end =#

      #= @testset "m0 = <60>" begin =#
      #=   println("m0 = <60>") =#
      #=   m0 = ideal(O,O(60)) =#
      #=   Q = NfOrdQuoRing(O,m0) =#
      #=   G = domain(Hecke.multiplicative_group(Q)) =#
      #=   println(snf(G)[1].snf) =#
      #=   @test order(G) == 14155776*fmpz(10)^14 =#
      #=   structt = [15,2,2,2,2,15,4,4,4,4,2,2,2,2,80,80,80,24,5,5,5,5,5,5,4,5,5,5] =#
      #=   H = abelian_group(structt) =#
      #=   @test Hecke.is_isomorphic(G,H) =#
      #=   @test M(G(G.snf)) == Q(O(1)) =#
      #=   for g in gens =#
      #=     for exp in -5:10 =#
      #=       el = g^exp =#
      #=       @assert M(M\el) == el =#
      #=     end =#
      #=   end =#
      #= end =#
    end
  end

  @testset "_multgrp_mod_pv" begin
     Qx,  x = PolynomialRing(FlintQQ, "x");

    @testset "K = Q" begin
       K,  a = NumberField(x,"a");
      O = maximal_order(K)

      @testset "i = <$pnum>^$v" for (pnum,v) in [(pnum,v) for pnum in [ x for x in 1:50 if isprime(fmpz(x))], v in [1,2,4,17]]
        #p = ideal(O,O(pnum))
        p = prime_decomposition(O, pnum)[1][1]
        #p = collect(keys(factor(p)))[1]
        pv = p^v
        G, mG = Hecke._multgrp_mod_pv(p, v, pv)
        S, StoG, mS = snf(G, mG)
        gens = mS.generators
        d = S.snf
        @test length(gens) == length(d)
        for i in 1:length(gens)
          @test verify_order(gens[i].elem, pv, d[i])
        end
        H = Hecke.multgrp_of_cyclic_grp(fmpz(pnum)^v)
        @test Hecke.isisomorphic(S, H)
        # Test discrete logarithm
        Q = NfOrdQuoRing(O, pv)
        for g in mG.generators
          for exp in [ -1, 1, 6 ]
            el = g^exp
            @test mG(mG\el) == el
          end
        end
      end
    end

    @testset "f = x^2-x+15" begin
      f = x^2-x+15
       K,  a = NumberField(f,"a");
      O = maximal_order(K)
      I = O(20)*O

      @testset "p = <$(p.gen_one),$(p.gen_two)>, v = $v" for (p,v) in factor(I)
        pv = p^v
        G, mG = Hecke._multgrp_mod_pv(p, v, pv)
        S, StoG, mS = snf(G, mG)
        gens = mS.generators
        structure = S.snf
        @test length(gens) == length(structure)
        for i in 1:length(gens)
          @test verify_order(gens[i].elem, pv, structure[i])
        end
        # Test discrete logarithm
        Q = NfOrdQuoRing(O, pv)
        for g in mG.generators
          for exp in [ -1, 0, 1, 2 ]
            el = g^exp
            @test mG(mG\el) == el
          end
        end
      end
    end

    @testset "f = x^3+8*x^2+6*x-17" begin
      f = x^3+8*x^2+6*x-17
       K,  a = NumberField(f,"a");
      O = maximal_order(K)
      p = O(3)*O
      p = collect(keys(factor(p)))[1]
      structures = Vector{fmpz}[[26],[26,3,3,3],[26,9,9,9],[26,27,27,27]]
      @testset "v = $v" for v in 1:length(structures)
        pv = p^v
        G, mG = Hecke._multgrp_mod_pv(p, v, pv)
        S, StoG, mS = snf(G, mG)
        gens = mS.generators
        d = S.snf
        @test length(gens) == length(d)
        for i in 1:length(gens)
          @test verify_order(gens[i].elem, pv, d[i])
        end
        @test order(G) == prod(structures[v])
        H = abelian_group(structures[v])
        @test Hecke.isisomorphic(S, H)
        # Test discrete logarithm
        Q = NfOrdQuoRing(O, pv)
        for g in mG.generators
          for exp in [ -2, 1, 3 ]
            el = g^exp
            @test mG(mG\el) == el
          end
        end
      end
    end

    @testset "f = x^4+11*x^3-19*x^2-8*x+7" begin
      f = x^4+11*x^3-19*x^2-8*x+7
       K,  a = NumberField(f,"a");
      O = maximal_order(K)
      p = ideal(O, fmpz(3), O(2+a+a^2))
      p = collect(keys(factor(p)))[1]
      structures = Vector{fmpz}[[8],[8,3,3],[8,3,3,3,3],[8,3,3,3,3,9],[8,3,3,9,9,9],[8,3,9,9,9,27]]
      @testset "v = $v" for v in 1:length(structures)
        pv = p^v
        G, mG = Hecke._multgrp_mod_pv(p, v, pv)
        S, StoG, mS = snf(G, mG)
        gens = mS.generators
        d = S.snf
        @test length(gens) == length(d)
        for i in 1:length(gens)
          @test verify_order(gens[i].elem, pv, d[i])
        end
        @test order(G) == prod(structures[v])
        H = abelian_group(structures[v])
        @test Hecke.isisomorphic(S, H)
        # Test discrete logarithm
        Q = NfOrdQuoRing(O,pv)
        for g in mG.generators
          for exp in [ -4, 1, 6 ]
            el = g^exp
            @test mG(mG\el) == el
          end
        end
      end
    end

    @testset "f = x^6+6x^5-12*x^4-x^3-6*x^2+9*x+20" begin
      f = x^6+6x^5-12*x^4-x^3-6*x^2+9*x+20
       K,  a = NumberField(f,"a");
      O = maximal_order(K)
      p = ideal(O, fmpz(3), O(2+2*a+a^2))
      p = collect(keys(factor(p)))[1]
      structures = Vector{fmpz}[[8],[8,3,3],[8,3,3,3,3],[8,9,9,3,3],[8,9,9,3,3,3,3],[8,9,9,9,9,3,3]]
      @testset "v = $v" for v in 1:length(structures)
        pv = p^v
        G, mG = Hecke._multgrp_mod_pv(p, v, pv)
        S, StoG, mS = snf(G, mG)
        gens = mS.generators
        d = S.snf
        @test length(gens) == length(d)
        for i in 1:length(gens)
          @test verify_order(gens[i].elem, pv, d[i])
        end
        @test order(G) == prod(structures[v])
        H = abelian_group(structures[v])
        @test Hecke.isisomorphic(S, H)
        # Test discrete logarithm
        Q = NfOrdQuoRing(O, pv)
        for g in mG.generators
          for exp in [ -1, 0, 1, 6 ]
            el = g^exp
            @test mG(mG\el) == el
          end
        end
      end
    end
  end

  @testset "_multgrp_mod_p" begin
     Qx,  x = PolynomialRing(FlintQQ, "x");

    @testset "K = Q" begin
       K,  a = NumberField(x, "a");
      O = maximal_order(K)

      @testset "p = <$(pnum)>" for pnum in [ x for x in 1:50 if isprime(fmpz(x))]
        p = O(pnum)*O
        @test isprime(p)
        #p = collect(keys(factor(p)))[1]
        G, mG = Hecke._multgrp_mod_p(p)
        @test length(mG.generators) == 1
        g = mG.generators[1]
        n = exponent(G)
        @test n == pnum - 1
        @test verify_order(g, p, n)
        for exp in [ 0, 1, 2, n - 2, n - 1, n, 3234239 ]
          @test mG.discrete_logarithm(g^exp)[1] == mod(fmpz(exp), n)
        end
      end
    end

    @testset "K = Q[√2]" begin
       K,  a = NumberField(x^2-2,"a");
      O = maximal_order(K)

      primeideals = Vector{Hecke.NfOrdIdl}()
      for pnum in [ x for x in 1:40 if isprime(fmpz(x))]
        append!(primeideals, collect(keys(factor(O(pnum)*O))))
      end

      @testset "p = <$(p.gen_one), $(p.gen_two)>" for p in primeideals
        @test isprime(p)
        G, mG = Hecke._multgrp_mod_p(p)
        @test length(mG.generators) == 1
        g = mG.generators[1]
        n = exponent(G)
        @test !iszero(g)
        @test !(g in p)
        @test verify_order(g, p, n)
        Q = NfOrdQuoRing(O, p)
        for exp in [ 0, 1, 2, n - 2, n - 1, n ]
          @test mG.discrete_logarithm((Q(g)^exp).elem)[1] == mod(fmpz(exp), n)
        end
      end
    end

    @testset "K = Q[x]/<x^6+6*x^5-12*x^4-x^3-6*x^2+9*x+20>" begin
       K,  a = NumberField(x^6+6*x^5-12*x^4-x^3-6*x^2+9*x+20,"a");
      O = maximal_order(K)

      primeideals = Vector{Hecke.NfOrdIdl}()
      for pnum in [ x for x in 1:20 if isprime(fmpz(x)) ]
        append!(primeideals, collect(keys(factor(O(pnum)*O))))
      end

      @testset "p = <$(p.gen_one), $(p.gen_two)>" for p in primeideals
        @test isprime(p)
        G, mG = Hecke._multgrp_mod_p(p)
        @test length(mG.generators) == 1
        g = mG.generators[1]
        n = exponent(G)
        @test !iszero(g)
        @test !(g in p)
        @test verify_order(g, p, n)
        Q = NfOrdQuoRing(O, p)
        for exp in [ 24, n - 345 ]
          @test mG.discrete_logarithm((Q(g)^exp).elem)[1] == mod(fmpz(exp), n)
        end
      end
    end

    @testset "K = Q[x]/<x^10-x^9+x^8-x^7+x^6-x^5+x^4-x^3+x^2-x+1>" begin
       K,  a = NumberField(x^10-x^9+x^8-x^7+x^6-x^5+x^4-x^3+x^2-x+1,"a");
      O = maximal_order(K)

      primeideals = Vector{Hecke.NfOrdIdl}()
      for pnum in [ 2, 3, 5, 11 ]
        append!(primeideals, collect(keys(factor(O(pnum)*O))))
      end

      @testset "p = <$(p.gen_one), $(p.gen_two)>" for p in primeideals
        @test isprime(p)
        G, mG = Hecke._multgrp_mod_p(p)
        @test length(mG.generators) == 1
        g = mG.generators[1]
        n = exponent(G)
        @test !iszero(g)
        @test !(g in p)
        @test verify_order(g, p, n)
        Q = NfOrdQuoRing(O, p)
        for exp in [ 50, n - 30 ]
          @test mG.discrete_logarithm((Q(g)^exp).elem)[1] == mod(fmpz(exp), n)
        end
      end
    end
  end

  @testset "_1_plus_p_mod_1_plus_pv" begin
     Qx,  x = PolynomialRing(FlintQQ, "x");

    @testset "Method: $method" for method in [:quadratic,:artin_hasse,:p_adic]

      @testset "K = Q" begin
         K,  a = NumberField(x,"a");
        O = maximal_order(K)

        @testset "p = <$(pnum)>, v = $(v)" for pnum in [ x for x in 1:30 if isprime(fmpz(x))], v in [1,2,3,4,11,30]
          p = O(pnum)*O
          @test isprime(p)
          pv = p^v
          #p = collect(keys(factor(i)))[1]
          G, mG = Hecke._1_plus_p_mod_1_plus_pv(p, v, pv, fmpz(pnum)^v; method = method)
          @test issnf(G)
          @test length(mG.generators) == ngens(G)
          # Test generators
          for i in 1:length(mG.generators)
            if G.snf[i] != 1
              @test parent(mG.generators[i]) == O
              @test mG.generators[i] - 1 in p
              @test verify_order(mG.generators[i], pv, G.snf[i])
            end
          end
          # Test structure/relations
          H = Hecke.multgrp_of_cyclic_grp(fmpz(pnum)^v)
          I = Hecke._multgrp_mod_p(p)[1]
          @test order(G) == div(order(H), order(I))
          check, J = Hecke._1_plus_pa_mod_1_plus_pb_structure(p, 1, v)
          if check
            @test Hecke.isisomorphic(G, J)
          end
          # Test discrete logarithm
          Q = NfOrdQuoRing(O, pv)
          for g in mG.generators
            for exp in -1:2
              el = Q(g)^exp
              @test Q(mG(mG\el.elem)) == el
            end
          end
        end
      end

      @testset "K = Q[√2]" begin
         K,  a = NumberField(x^2 - 2,"a")
        O = maximal_order(K)

        primeideals = Vector{Hecke.NfOrdIdl}()
        for pnum in [2,3,5,7,19]
          fac = factor(ideal(O,O(pnum)))
          ks = collect(keys(fac))
          vs = collect(values(fac))
          all(isone,vs) && append!(primeideals,ks)
        end

        @testset "p = <$(p.gen_one), $(p.gen_two)>, v = $(v)" for p in primeideals, v in [1,4,11]
          pv = p^v
          G, mG = Hecke._1_plus_p_mod_1_plus_pv(p, v, pv, minimum(p, copy = false)^v; method = method)
          @test issnf(G)
          @test length(mG.generators) == ngens(G)
          # Test generators
          for i in 1:length(mG.generators)
            if G.snf[i] != 1
              @test parent(mG.generators[i]) == O
              @test mG.generators[i] - 1 in p
              @test verify_order(mG.generators[i], pv, G.snf[i])
            end
          end
          # Test structure
          check, J = Hecke._1_plus_pa_mod_1_plus_pb_structure(p, 1, v)
          if check
            @test Hecke.isisomorphic(G, J)
          end
          # Test discrete logarithm
          Q = NfOrdQuoRing(O, pv)
          for g in mG.generators
            for exp in [ -1, 1, 2 ]
              el = Q(g)^exp
              @test Q(mG(mG\el.elem)) == el
            end
          end
        end
      end

      @testset "K = Q[x]/<f = x^6+...>" begin
        f = x^6 + 6*x^5 - 12*x^4 - x^3 - 6*x^2 + 9*x + 20
         K,  a = NumberField(f,"a")
        O = maximal_order(K)

        primeideals = Vector{Hecke.NfOrdIdl}()
        for pnum in [2,11,13]
          fac = factor(ideal(O,O(pnum)))
          ks = collect(keys(fac))
          vs = collect(values(fac))
          all(isone,vs) && append!(primeideals,ks)
        end

        @testset "p = <$(p.gen_one), $(p.gen_two)>, v = $(v)" for p in primeideals, v in [2,9]
          pv = p^v
          G, mG = Hecke._1_plus_p_mod_1_plus_pv(p, v, pv, minimum(p, copy = false)^v; method = method)
          @test issnf(G)
          @test length(mG.generators) == ngens(G)
          # Test generators
          for i in 1:length(mG.generators)
            if G.snf[i] != 1
              @test parent(mG.generators[i]) == O
              @test mG.generators[i] - 1 in p
              @test verify_order(mG.generators[i], pv, G.snf[i])
            end
          end
          # Test structure
          check, J = Hecke._1_plus_pa_mod_1_plus_pb_structure(p, 1, v)
          if check
            @test Hecke.isisomorphic(G, J)
          end
          # Test discrete logarithm
          Q = NfOrdQuoRing(O, pv)
          for g in mG.generators
            for exp in [-1, 2]
              el = Q(g)^exp
              @test Q(mG(mG\el.elem)) == el
            end
          end
        end
      end
    end
  end

  @testset "Non-maximal orders" begin
    Qx, x = FlintQQ["x"]

    K1, a1 = number_field(x^3 - 2, "a1")
    OK1 = maximal_order(K1)
    O1 = Order(K1, [K1(1), 10*a1, 100*a1^2])
    F1 = conductor(O1, OK1)
    Q1, mQ1 = quo(O1, F1)
    G1, mG1 = multiplicative_group(Q1)
    @test G1.snf == [ fmpz(2), fmpz(10), fmpz(20) ]
    for i = 1:10
      g = G1(map(fmpz, rand(-100:100, ngens(G1))))
      h = G1(map(fmpz, rand(-100:100, ngens(G1))))
      @test mG1(g)*mG1(h) == mG1(g + h)
    end

    K2, a2 = number_field(x^3 - 12*x^2 - 6324*x + 459510, "a2")
    O2 = EquationOrder(K2)
    OK2 = maximal_order(O2)
    F2 = conductor(O2, OK2)
    Q2, mQ2 = quo(O2, F2)
    G2, mG2 = multiplicative_group(Q2)
    @test G2.snf == [ fmpz(2), fmpz(4), fmpz(4), fmpz(4368) ]
    for i = 1:10
      g = G2(map(fmpz, rand(-100:100, ngens(G2))))
      h = G2(map(fmpz, rand(-100:100, ngens(G2))))
      @test mG2(g)*mG2(h) == mG2(g + h)
    end

    K3, a3 = number_field(x^5 - 1389*x^4 + 512066*x^3 - 11859166*x^2 + 83453925*x - 211865821, "a3")
    OK3 = maximal_order(K3)
    O3 = EquationOrder(K3)
    F3 = conductor(O3, OK3)
    Q3, mQ3 = quo(O3, F3)
    G3, mG3 = multiplicative_group(Q3)
    @test G3.snf == [ fmpz(2), fmpz(2), fmpz(2), fmpz(2), fmpz(4), fmpz(36100148955782880) ]
    for i = 1:10
      g = G3(map(fmpz, rand(-100:100, ngens(G3))))
      h = G3(map(fmpz, rand(-100:100, ngens(G3))))
      @test mG3(g)*mG3(h) == mG3(g + h)
    end
  end
end


text:
using HDF5
file = h5open(tempname(), "w")

arr1 = rand((10 for i in 1:5)...)
arr2 = rand(Int, 5, (10 for i in 1:4)...)
arr3 = rand(Float32, 10, 10, 11, 10, 10, 10)
arr4 = rand(UInt8, 10, 10, 10, 20, 10)

make_init_args(::Type{Muon.AlignedMapping}, d::Dict) = (d,)
function make_init_args(::Type{Muon.BackedAlignedMapping}, d::Dict)
    path = "test"
    Muon.write_attr(file, path, d)
    return (file, path)
end

@testset "$name" for (name, T) in (
    ("AlignedMapping", Muon.AlignedMapping),
    ("BackedAlignedMapping", Muon.BackedAlignedMapping),
)
    @testset "ref: $ndims dimensions" for ndims in 1:5
        ref = Array{Bool}(undef, (10 for i in 1:ndims)...)
        @test_throws DimensionMismatch T{Tuple{2 => 1, 1 => ndims, 3 => ndims}}(
            ref,
            make_init_args(T, Dict("test" => arr2))...,
        )
        @test_throws DimensionMismatch T{Tuple{2 => 1, 1 => ndims, 3 => ndims}}(
            ref,
            make_init_args(T, Dict("test" => arr3))...,
        )
        mapping = T{Tuple{2 => 1, 1 => ndims, 3 => ndims}}(
            ref,
            make_init_args(T, Dict("arr1" => arr1))...,
        )
        mapping["arr4"] = arr4
        @test_throws DimensionMismatch mapping["arr2"] = arr2
        @test_throws DimensionMismatch mapping["arr3"] = arr3
        @test mapping["arr1"] == arr1
        @test mapping["arr4"] == arr4
    end
end


text:
using Cambrian
using Test
using RDatasets
using YAML
using Statistics

function data_setup()
    iris = dataset("datasets", "iris")
    X = convert(Matrix, iris[:, 1:4])'
    X = X ./ maximum(X; dims=2)
    r = iris[:, 5].refs
    Y = zeros(maximum(r), size(X, 2))
    for i in 1:length(r)
        Y[r[i], i] = 1.0
    end
    X, Y
end

function interpret(ind::Cambrian.Individual)
    w = reshape(ind.genes, (4, 3))
    function F(x::Array{Float64})
        (x' * w)'
    end
end

@testset "Lexicase Selection" begin
    X, Y = data_setup()

    cfg = YAML.load_file("../cfg/oneplus.yaml")
    cfg["n_genes"] = size(X, 1) * size(Y, 1)
    e = Evolution(Cambrian.FloatIndividual, cfg; id="test", populate=Cambrian.oneplus_populate!)
    e.evaluate = x::Evolution->Cambrian.lexicase_evaluate!(x, X, Y, interpret;
                                                         valid=Cambrian.classify_valid,
                                                         verify_best=false)

    step!(e)

    print("lexicase step")
    @timev step!(e)
    for i in 1:length(e.population)
        @test e.population[i].fitness[1] >= 0
        @test e.population[i].fitness[1] <= size(X, 2)
    end
    best_fit = sort(e.population)[end].fitness[1]

    for i in 1:10
        step!(e)
        best = sort(e.population)[end]
        @test best.fitness[1] >= 0.0
        best_fit = best.fitness[1]
    end
end


text:
"""
    {{ name }}

Lorem ipsum dolor sit amet.
"""
const {{ name }} = Nullable()


text:
using Test
using DelimitedFiles
import PolyLog

include("Li2.jl")
include("Li3.jl")
include("Li4.jl")
include("Li5.jl")
include("Li6.jl")


text:
@testset "SingleHistogramThreshold" begin
    @info "Test: SingleHistogramThreshold"

    threshold_methods = [
        ("Balanced", Balanced()),
        ("Entropy", Entropy()),
        ("Intermodes", Intermodes()),
        ("MinimumError", MinimumError()),
        ("MinimumIntermodes", MinimumIntermodes()),
        ("Moments", Moments()),
        ("Otsu", Otsu()),
        ("UnimodalRosin", UnimodalRosin()),
        ("Yen", Yen()),
    ]

    @testset "API" begin
        img_gray = imresize(testimage("cameraman"); ratio=0.25)
        img = copy(img_gray)

        for (fname, f) in threshold_methods
            binarized_img = binarize(img, f)
            @test img == img_gray # img unchanged
            @test eltype(binarized_img) == Gray{N0f8}

            ref = copy(binarized_img)

            g = SingleHistogramThreshold(f, nbins=256)
            binarized_img = binarize(img, g)
            @test ref == binarized_img
            @test eltype(binarized_img) == Gray{N0f8}

            for alg in [f, g]
                binarized_img = binarize(Gray{Bool}, img, alg)
                @test img == img_gray # img unchanged
                @test eltype(binarized_img) == Gray{Bool}
                @test ref == binarized_img

                binarized_img = similar(img, Bool)
                binarize!(binarized_img, img, alg)
                @test img == img_gray # img unchanged
                @test eltype(binarized_img) == Bool
                @test ref == binarized_img

                binarized_img = copy(img_gray)
                binarize!(binarized_img, alg)
                @test eltype(binarized_img) == Gray{N0f8}
                @test ref == binarized_img
            end

            # binarize for SingleHistogramThreshold does not accept keyword `nbins`
            binarized_img = binarize(img, f, nbins=256)
            @test img == img_gray
            @test eltype(binarized_img) == Gray{N0f8}
            @test ref == binarized_img

            for T in generate_test_types([Float32, N0f8, Bool], [Gray])
                @test eltype(binarize(T, img, f)) == T
            end
        end
    end

    @testset "Types" begin
        # Gray
        img_gray = imresize(testimage("lena_gray_256"); ratio=0.25)
        for (fname, f) in threshold_methods
            type_list = generate_test_types([Float32, N0f8], [Gray])
            for T in type_list
                img = T.(img_gray)
                reffile = joinpath("References", fname*"_Gray.png")
                @test_reference reffile Gray.(binarize(img, f)) by=binarization_equality()
            end
        end

        # Color3
        img_color = imresize(testimage("lena_color_256"); ratio=0.25)
        for (fname, f) in threshold_methods
            type_list = generate_test_types([Float32, N0f8], [RGB, Lab])
            for T in type_list
                img = T.(img_gray)
                reffile = joinpath("References", fname*"_Color3.png")
                @test_reference reffile Gray.(binarize(img, f)) by=binarization_equality()
            end
        end

        # issue #83
        @testset "explicit Bool type" begin
            img_ori = imresize(testimage("cameraman"); ratio=0.25)
            for T in [RGB, Gray]
                img = T.(img_ori)
                for (fname, f) in threshold_methods
                    for out_T in [Gray{Bool}, Bool]
                        @test binarize(out_T, img, f) == out_T.(binarize(img, f))
                    end
                end
            end
        end
    end

    @testset "Numerical" begin
        # Check that the image only has ones or zeros.
        img = imresize(testimage("lena_gray_256"); ratio=0.25)
        for (fname, f) in threshold_methods
            img₀₁ = binarize(img, f)
            non_zeros = findall(x -> x != 0.0 && x != 1.0, img₀₁)
            @test length(non_zeros) == 0

            # Check that ones and zeros have been assigned to the correct side of the threshold.
            maxval, maxpos = findmax(Gray.(img))
            @test img₀₁[maxpos] == 1
            minval, minpos = findmin(Gray.(img))
            @test img₀₁[minpos] == 0
        end
    end

    @testset "Offset Arrays" begin
        # Verify that the algorithms give equivalent results on OffsetArrays
        img = imresize(testimage("cameraman"); ratio=0.25)
        offset_img = OffsetArray(img, OffsetArrays.Origin(0))
        for (fname, f) in threshold_methods
            img₀₁ = binarize(img, f)
            offset_img₀₁ = binarize(offset_img, f)
            @test axes(offset_img₀₁) == axes(offset_img)
            @test img₀₁ == OffsetArrays.no_offset_view(offset_img₀₁)
        end
    end
end


text:
@testset "Transition" begin

@testset "Constructor" begin
    transition = Transition( "Transition", "Node A", "Node B" )
    @test all( [transition.name == "Transition",
        transition.sourceNode == "Node A", transition.targetNode == "Node B",
        !transition.isOutTransition, transition.freq == 1.0,
        transition.offset == 0.0, transition.maxAttempts == 1,
        transition.minFlux == 0, transition.maxFlux == -1,
        !transition.hasPriority] )
    transition = Transition( "Transition", "Node A" )
    @test ( transition.sourceNode == "Node A" ) &&
        ( transition.targetNode == "dummy" ) && transition.isOutTransition
end  # @testset "Constructor"

transition = Transition( "Transition", "dummy", "dummy" )

@testset "function setTransitionNode!" begin
    setTransitionNode!( transition, "Node A" )
    @test transition.sourceNode == "Node A"
    setTransitionNode!( transition, "Node B", true )
    @test transition.targetNode == "Node B"
end  # @testset "function setTransitionNode!"

@testset "function setTransitionIsOut!" begin
    setTransitionIsOut!( transition, true )
    @test transition.isOutTransition
    setTransitionIsOut!( transition, false )
    @test !transition.isOutTransition
end  # @testset "function setTransitionIsOut!"

@testset "function setTransitionSchedule!" begin
    setTransitionSchedule!( transition, 12, 4 )
    @test ( transition.freq == 12.0 ) && ( transition.offset == 4.0 )
    setTransitionSchedule!( transition, 6 )
    @test ( transition.freq == 6.0 ) && ( transition.offset == 0.0 )
    setTransitionSchedule!( transition, 6, 10 )
    @test transition.offset == 4.0
    setTransitionSchedule!( transition, 6, -3 )
    @test transition.offset == 3.0
    @test !setTransitionSchedule!( transition, -9 ) &&
        ( transition.freq == 6.0 )
end  # @testset "function setTransitionSchedule!"

@testset "function setTransitionMaxAttempts!" begin
    setTransitionMaxAttempts!( transition, 5 )
    @test transition.maxAttempts == 5
    setTransitionMaxAttempts!( transition, -10 )
    @test transition.maxAttempts == -1
end  # @testset "function setTransitionMaxAttempts!"

@testset "function setTransitionFluxLimits!" begin
    setTransitionFluxLimits!( transition, 10, 100 )
    @test ( transition.minFlux == 10 ) && ( transition.maxFlux == 100 )
    setTransitionFluxLimits!( transition, -50, -10 )
    @test ( transition.minFlux == 0 ) && ( transition.maxFlux == -1 )
    @test !setTransitionFluxLimits!( transition, 25, 10 )
    setTransitionFluxLimits!( transition, 20, 100 )
end  # @testset "function setTransitionFluxLimits!"

@testset "function setTransitionHasPriority!" begin
    setTransitionHasPriority!( transition, true )
    @test transition.hasPriority && ( transition.priority < 0 )
    setTransitionHasPriority!( transition, false )
    @test !transition.hasPriority && ( transition.priority > 0 )
end  # @testset "function setTransitionHasPriority!"

@testset "function addTransitionCondition!" begin
    cond = MPcondition( "rank", ==, "captain" )
    addTransitionCondition!( transition, cond )
    @test ( length( transition.extraConditions ) == 1 ) &&
        ( cond ∈ transition.extraConditions )
    cond = MPcondition( "branch", ∈, ["air", "navy"] )
    addTransitionCondition!( transition, cond )
    @test cond ∈ transition.extraConditions
end  # @testset "function addTransitionCondition!"

@testset "function clearTransitionConditions!" begin
    clearTransitionConditions!( transition )
    @test isempty( transition.extraConditions )
end  # @testset "function clearTransitionConditions!"

@testset "function setTransitionConditions!" begin
    cond1 = MPcondition( "rank", ==, "adjutant" )
    cond2 = MPcondition( "branch", ∈, ["air", "medical"] )
    setTransitionConditions!( transition, [cond1, cond2] )
    @test ( length( transition.extraConditions ) == 2 ) &&
        ( [cond1, cond2] ⊆ transition.extraConditions )
end  # @testset "function setTransitionConditions!"

@testset "function addTransitionAttributeChange!" begin
    addTransitionAttributeChange!( transition, ("rank", "chief adjutant") )
    @test haskey( transition.extraChanges, "rank" ) &&
        ( transition.extraChanges["rank"] == "chief adjutant" )
    addTransitionAttributeChange!( transition, ("branch", "navy"),
        ("rank", "lieutenant") )
    @test all( [transition.extraChanges["rank"] == "lieutenant",
        haskey( transition.extraChanges, "branch" ),
        transition.extraChanges["branch"] == "navy"] )
    @test !addTransitionAttributeChange!( transition, ("rank", "captain"), ("career", "limited"), ("rank", "major") )
end  # @testset "function addTransitionAttributeChange!"

@testset "function clearTransitionAttributeChanges!" begin
    clearTransitionAttributeChanges!( transition )
    @test isempty( transition.extraChanges )
end  # @testset "function clearTransitionAttributeChanges!"

@testset "function setTransitionAttributeChanges!" begin
    setTransitionAttributeChanges!( transition, Dict( "rank" => "captain",
        "grade" => "A" ) )
    @test all( [length( transition.extraChanges ) == 2,
        haskey( transition.extraChanges, "rank" ),
        haskey( transition.extraChanges, "grade" ),
        transition.extraChanges["rank"] == "captain",
        transition.extraChanges["grade"] == "A"] )
    setTransitionAttributeChanges!( transition, ("rank", "corporal"),
        ("branch", "air") )
    @test all( [length( transition.extraChanges ) == 2,
        haskey( transition.extraChanges, "rank" ),
        haskey( transition.extraChanges, "branch" ),
        transition.extraChanges["rank"] == "corporal",
        transition.extraChanges["branch"] == "air"] )
    setTransitionAttributeChanges!( transition, ["grade"], ["D"] )
    @test all( [length( transition.extraChanges ) == 1,
        haskey( transition.extraChanges, "grade" ),
        transition.extraChanges["grade"] == "D"] )
    @test !setTransitionAttributeChanges!( transition, ("rank", "private"),
        ("grade", "D"), ("rank", "corporal") )
    @test !setTransitionAttributeChanges!( transition,
        ["rank", "grade", "rank"], ["lieutenant", "A", "colonel"] )
    @test !setTransitionAttributeChanges!( transition, ["rank"],
        ["colonel", "A"] )
end  # @testset "function setTransitionAttributeChanges!"

@testset "function setTransitionProbabilities!" begin
    setTransitionProbabilities!( transition, [0.3, 1.2, -0.5, 0.9, 1.0] )
    @test transition.probabilityList == [0.3, 0.9, 1.0]
    setTransitionProbabilities!( transition, [0.2, 0.5, 1.0] )
    @test transition.probabilityList == [0.2, 0.5, 1.0]
    @test !setTransitionProbabilities!( transition, [1.2, 1.3, -0.5] )
end  # @testset "function setTransitionProbabilities!"

end  # @testset "Transition"


text:
"""
    TemplateName <: Any
Represent a template name.

Note that, the underlying pointer is NOT a *pointer* to a `clang::TemplateName` object.
Instead, it's the opaque pointer representation of the `clang::TemplateName` itself.
"""
struct TemplateName
    ptr::CXTemplateName
end

Base.unsafe_convert(::Type{CXTemplateName}, x::TemplateName) = x.ptr
Base.cconvert(::Type{CXTemplateName}, x::TemplateName) = x


text:
using Documenter, Egal

makedocs(;
    modules=[Egal],
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/kolia/Egal.jl/blob/{commit}{path}#L{line}",
    sitename="Egal.jl",
    authors="Kolia Sadeghi <ksadeghi@princeton.edu>",
    assets=String[],
)

deploydocs(;
    repo="github.com/kolia/Egal.jl",
)