diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4991c31d..530d7c39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: - pull_request jobs: test: - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} + name: Julia ${{ matrix.version }} - ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -14,19 +14,12 @@ jobs: - '1' os: - ubuntu-latest -# - macOS-latest - arch: - - x86 - - x64 - exclude: - - os: macOS-latest - arch: x86 + - macOS-latest steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v2 + - uses: actions/checkout@v6 + - uses: julia-actions/setup-julia@v3 with: version: ${{ matrix.version }} - arch: ${{ matrix.arch }} show-versioninfo: true - uses: actions/cache@v3 env: @@ -38,10 +31,10 @@ jobs: ${{ runner.os }}-test-${{ env.cache-name }}- ${{ runner.os }}-test- ${{ runner.os }}- - - uses: julia-actions/julia-buildpkg@latest - - uses: julia-actions/julia-runtest@latest + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} file: lcov.info diff --git a/src/libfasttransforms.jl b/src/libfasttransforms.jl index 3ce492d9..dd694b15 100644 --- a/src/libfasttransforms.jl +++ b/src/libfasttransforms.jl @@ -49,6 +49,34 @@ function renew!(x::AbstractArray{BigFloat}) return x end +# Obtain a raw C pointer to the mpfr_t struct underlying a BigFloat. +# In Julia < 1.12, BigFloat was a mutable struct whose fields matched mpfr_t directly, +# so pointer_from_objref gives us the mpfr_t*. +# In Julia >= 1.12, BigFloat is an immutable struct wrapping Memory{Limb}, and the +# mpfr_t struct is stored at the start of that Memory. +@static if VERSION >= v"1.12" + _mpfr_ptr(b::BigFloat) = Ptr{mpfr_t}(pointer(getfield(b, :d))) +else + _mpfr_ptr(b::BigFloat) = Ptr{mpfr_t}(pointer_from_objref(b)) +end + +function _mpfr_ptrs(x::StridedVector{BigFloat}) + return [_mpfr_ptr(xi) for xi in x] +end + +function _mpfr_ptrs(x::StridedMatrix{BigFloat}) + m, n = size(x) + s = stride(x, 2) + len = n > 0 ? s * (n - 1) + m : 0 + ptrs = Vector{Ptr{mpfr_t}}(undef, len) + for j in 0:n-1 + for i in 0:m-1 + @inbounds ptrs[i + j*s + 1] = _mpfr_ptr(x[i+1, j+1]) + end + end + return ptrs +end + function horner!(f::Vector{Float64}, c::StridedVector{Float64}, x::Vector{Float64}) @assert length(x) == length(f) ccall((:ft_horner, libfasttransforms), Cvoid, (Cint, Ptr{Float64}, Cint, Cint, Ptr{Float64}, Ptr{Float64}), length(c), c, stride(c, 1), length(x), x, f) @@ -983,19 +1011,31 @@ for (fJ, fC) in ((:lmul!, :ft_mpfr_trmv_ptr), function $fJ(p::FTPlan{BigFloat, 1}, x::StridedVector{BigFloat}) checksize(p, x) checkstride(p, x) - ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{BigFloat}, Int32), 'N', p.n, p, p.n, renew!(x), Base.MPFR.ROUNDING_MODE[]) + renew!(x) + GC.@preserve x begin + ptrs = _mpfr_ptrs(x) + ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{Ptr{mpfr_t}}, Int32), 'N', p.n, p, p.n, ptrs, Base.MPFR.ROUNDING_MODE[]) + end return x end function $fJ(p::AdjointFTPlan{BigFloat, FTPlan{BigFloat, 1, K}}, x::StridedVector{BigFloat}) where K checksize(p, x) checkstride(p, x) - ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{BigFloat}, Int32), 'T', p.parent.n, p, p.parent.n, renew!(x), Base.MPFR.ROUNDING_MODE[]) + renew!(x) + GC.@preserve x begin + ptrs = _mpfr_ptrs(x) + ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{Ptr{mpfr_t}}, Int32), 'T', p.parent.n, p, p.parent.n, ptrs, Base.MPFR.ROUNDING_MODE[]) + end return x end function $fJ(p::TransposeFTPlan{BigFloat, FTPlan{BigFloat, 1, K}}, x::StridedVector{BigFloat}) where K checksize(p, x) checkstride(p, x) - ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{BigFloat}, Int32), 'T', p.parent.n, p, p.parent.n, renew!(x), Base.MPFR.ROUNDING_MODE[]) + renew!(x) + GC.@preserve x begin + ptrs = _mpfr_ptrs(x) + ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{Ptr{mpfr_t}}, Int32), 'T', p.parent.n, p, p.parent.n, ptrs, Base.MPFR.ROUNDING_MODE[]) + end return x end end @@ -1083,19 +1123,31 @@ for (fJ, fC) in ((:lmul!, :ft_mpfr_trmm_ptr), function $fJ(p::FTPlan{BigFloat, 1}, x::StridedMatrix{BigFloat}) checksize(p, x) checkstride(p, x) - ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{BigFloat}, Cint, Cint, Int32), 'N', p.n, p, p.n, renew!(x), stride(x, 2), size(x, 2), Base.MPFR.ROUNDING_MODE[]) + renew!(x) + GC.@preserve x begin + ptrs = _mpfr_ptrs(x) + ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{Ptr{mpfr_t}}, Cint, Cint, Int32), 'N', p.n, p, p.n, ptrs, stride(x, 2), size(x, 2), Base.MPFR.ROUNDING_MODE[]) + end return x end function $fJ(p::AdjointFTPlan{BigFloat, FTPlan{BigFloat, 1, K}}, x::StridedMatrix{BigFloat}) where K checksize(p, x) checkstride(p, x) - ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{BigFloat}, Cint, Cint, Int32), 'T', p.parent.n, p, p.parent.n, renew!(x), stride(x, 2), size(x, 2), Base.MPFR.ROUNDING_MODE[]) + renew!(x) + GC.@preserve x begin + ptrs = _mpfr_ptrs(x) + ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{Ptr{mpfr_t}}, Cint, Cint, Int32), 'T', p.parent.n, p, p.parent.n, ptrs, stride(x, 2), size(x, 2), Base.MPFR.ROUNDING_MODE[]) + end return x end function $fJ(p::TransposeFTPlan{BigFloat, FTPlan{BigFloat, 1, K}}, x::StridedMatrix{BigFloat}) where K checksize(p, x) checkstride(p, x) - ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{BigFloat}, Cint, Cint, Int32), 'T', p.parent.n, p, p.parent.n, renew!(x), stride(x, 2), size(x, 2), Base.MPFR.ROUNDING_MODE[]) + renew!(x) + GC.@preserve x begin + ptrs = _mpfr_ptrs(x) + ccall(($(string(fC)), libfasttransforms), Cvoid, (Cint, Cint, Ptr{mpfr_t}, Cint, Ptr{Ptr{mpfr_t}}, Cint, Cint, Int32), 'T', p.parent.n, p, p.parent.n, ptrs, stride(x, 2), size(x, 2), Base.MPFR.ROUNDING_MODE[]) + end return x end end