Skip to content

integration #32

@kalmarek

Description

@kalmarek

Arb has acb_calc, where acb_calc_integrate is provided.
I tried to wrap the function as follows

#src/float/integrate.jl
struct acb_calc_integrate_opt_struct
    deg_limit::Cint #slong
    eval_limit::Cint #slong
    depth_limit::Cint #slong
    use_heap::Cint #int
    verbose::Cint #int

    function acb_calc_integrate_opt_struct(deg_limit::Integer, eval_limit::Integer,
      depth_limit::Integer, use_heap::Integer=0, verbose::Integer=0)
      return new(deg_limit, eval_limit, depth_limit, use_heap, verbose)
    end

    function acb_calc_integrate_opt_struct()
      opts = new()
      ccall(@libarb(acb_calc_integrate_opt_init), Cvoid,
        (Ref{acb_calc_integrate_opt_struct},), opts)
      return opts
    end
end

function acb_calc_func(out::Ptr{ArbComplex}, inp::Ptr{ArbComplex},
    param::Ptr{Cvoid}, order::Cint, prec::Cint)
    @assert iszero(order) # || isone(order) ← we'd need to verify holomorphicity
    x = unsafe_load(inp)
    f = unsafe_pointer_to_objref(param)
    ccall(@libarb(acb_set), Cvoid, (Ptr{ArbComplex}, Ref{ArbComplex}), out, f(x))
    return zero(Cint)
end

acb_calc_func_cfun() = @cfunction(acb_calc_func, Cint,
        (Ptr{ArbComplex}, Ptr{ArbComplex}, Ptr{Cvoid}, Cint, Cint))

function acb_calc_integrate(res::ArbComplex, cfun, param,
    a::ArbComplex, b::ArbComplex, rel_goal::Integer, abs_tol::Mag,
    options::acb_calc_integrate_opt_struct, prec::Integer)
    status = ccall(@libarb(acb_calc_integrate), Cint,
        (Ref{ArbComplex}, # res
        Ptr{Cvoid}, # cfun
        Any, # param
        Ref{ArbComplex}, # a
        Ref{ArbComplex}, # b
        Cint, # rel_goal
        Ref{Mag}, # abs_tol
        Ref{acb_calc_integrate_opt_struct}, # options
        Cint, # prec
        ),
        res, cfun, param, a, b, rel_goal, abs_tol, options, prec)
    return status
end

function integrate(f, a::Number, b::Number;
    rel_tol=0.0, abs_tol=precision(ArbComplex),
    opts::acb_calc_integrate_opt_struct = acb_calc_integrate_opt_struct())
    res = zero(ArbComplex)

    status = integrate!(res, f, ArbComplex(a), ArbComplex(b);
        rel_tol=rel_tol, abs_tol=abs_tol, opts=opts)

    # status:
    # ARB_CALC_SUCCESS = 0
    # ARB_CALC_NO_CONVERGENCE = 2
    if status == 2
        @warn "Arb integrate did not achived convergence, the result might be incorrect"
    end
    return res
end

function integrate!(res::ArbComplex, f, a::ArbNumber, b::ArbNumber;
    rel_tol=0.0, abs_tol=abs_tol=max(precision(a), precision(b)),
    opts::acb_calc_integrate_opt_struct=acb_calc_integrate_opt_struct())

    prec = max(workingprecision(a), workingprecision(b))

    if rel_tol <= zero(rel_tol)
        crel_goal = prec
    else
        # crel_goal = r where rel_tol ~2^-r
        crel_goal = -(ArbFloat(rel_tol).exp)
    end

    return acb_calc_integrate(res, acb_calc_func_cfun(),
        f, ArbComplex(a), ArbComplex(b),
        crel_goal, Mag(abs_tol), opts, prec)
end

but the function evaluation segfaults at line y = f(x)
modifying the function to

function acb_calc_func(out::Ptr{ArbComplex}, inp::Ptr{ArbComplex},
    param::Ptr{Cvoid}, order::Cint, prec::Cint)
    @assert iszero(order) # || isone(order) ← we'd need to verify holomorphicity
    x = unsafe_load(inp)
    f = unsafe_pointer_to_objref(param)
    println("f(2) = $(f(ArbComplex(2)))")
    println("Loaded x from $inp")
    println("x = $x")
    y = f(x)
   println("y = $y")
    ccall(@libarb(acb_set), Cvoid, (Ptr{ArbComplex}, Ref{ArbComplex}), out, y)
    return zero(Cint)
end

now segfaults at first access of the value of x, i.e. at println("x = $x") (f works correctly).

I'm quite confused, since similar code in Nemo https://github.com/wbhart/Nemo.jl/blob/5f96afc4af415df5985432b56bd1a972a0025d4b/src/arb/acb_calc.jl#L2 works as expected.

Probably crel_goal and the default values here and there need adjusting as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions