JuliaMath / Quadmath.jl

Float128 and libquadmath for the Julia language
Other
40 stars 11 forks source link

How to add functions? #48

Open JeffreySarnoff opened 4 years ago

JeffreySarnoff commented 4 years ago

I'm not sure what you are doing with the local version of @ccall. I'd like to add some functions via PR. I know how to do it this way:

const LibQM = dlopen(find_library(Quadmath.libquadmath))

Base.rem(x::Float128,y::Float128) = 
   ccall(dlsym(LibQM, :fmodq), Float128, (Float128, Float128), x, y)

How is this best done in keeping with the structure of the package?

simonbyrne commented 4 years ago

I think it should be

Float128(@ccall(libquadmath.fmodq(x::Cfloat128, y::Cfloat128)::Cfloat128))
JeffreySarnoff commented 4 years ago

Same question for complex functions libquadmath supports.

quadmath.h: __complex128 clogq (__complex128 x) is used through Julia in one of these two ways:

--- from quadmath.jl ---

# we use this slightly cumbersome definition to ensure
# that the value is 128-bit aligned
# and passed on the xmm registers,
# matching the x86_64 ABI for __float128.
const Cfloat128 = NTuple{2,VecElement{Float64}}

struct Float128 <: AbstractFloat
    data::Cfloat128
end
convert(::Type{Float128}, x::Number) = Float128(x)

const ComplexF128 = Complex{Float128}

Base.cconvert(::Type{Cfloat128}, x::Float128) = x.data
Base.cconvert(::Type{Ref{Cfloat128}}, x::Float128) =
  Ref{Cfloat128}(x.data)

I think defining Ccomplex128 would be more robust and performant when using Complex elementary functions from libquadmath. Which def is best?

amontoison commented 2 months ago

Hi @JeffreySarnoff @simonbyrne Do you know how to adapt the cconvert / unsafe_convert such we can pass a reference / vector of Float128 from Julia to the following wrappers?

# f(x)
function cutest_ufn_q_(status, n, x, f)
  ptr_cutest_ufn_q_ = Libdl.dlsym(cutest_lib_quadruple, :cutest_ufn_q_)
  @ccall $ptr_cutest_ufn_q_(status::Ptr{Cint}, n::Ptr{Cint}, x::Ptr{Cfloat128},
                            f::Ptr{Cfloat128})::Cvoid
end

# gradient(x)
function cutest_ugr_q_(status, n, x, g)
  ptr_cutest_ugr_q_ = Libdl.dlsym(cutest_lib_quadruple, :cutest_ugr_q_)
  @ccall $ptr_cutest_ugr_q_(status::Ptr{Cint}, n::Ptr{Cint}, x::Ptr{Cfloat128},
                            g::Ptr{Cfloat128})::Cvoid
end

function cutest_cint_uofg_q_(status, n, x, f, g, grad)
  ptr_cutest_cint_uofg_q_ = Libdl.dlsym(cutest_lib_quadruple, :cutest_cint_uofg_q_)
  @ccall $ptr_cutest_cint_uofg_q_(status::Ptr{Cint}, n::Ptr{Cint}, x::Ptr{Cfloat128}, f::Ptr{Cfloat128},
                                  g::Ptr{Cfloat128}, grad::Ptr{Bool})::Cvoid
end

I'm working on a new version of CUTEst.jl that supports quadruple precision. We recently added the support of __float128 in the Fortran library.

JeffreySarnoff commented 2 months ago

I do not how to do that.

RalphAS commented 2 months ago

Have you tried using the generic Array -> Ptr method of unsafe_convert (or a replica for whatever you use for f, g, etc.)?