Skip to content

More conversion in PDMat#212

Merged
devmotion merged 1 commit into
JuliaStats:masterfrom
timholy:teh/coerce
Jan 17, 2025
Merged

More conversion in PDMat#212
devmotion merged 1 commit into
JuliaStats:masterfrom
timholy:teh/coerce

Conversation

@timholy

@timholy timholy commented Dec 10, 2024

Copy link
Copy Markdown
Contributor

This allows one to convert both the eltype and matrix type. In practice, my main use for this is to support generic programming with both Matrix and StaticArrays.SMatrix.

Perhaps the only potentially-controversial aspect is moving the dimensionality check into the inner constructor. If we want to make it impossible to construct an inconsistent PDMat, that's where it has to be.

@devmotion

Copy link
Copy Markdown
Member

Did you check whether this is covered by #188? At least it seems the matrix element type is restricted in the same way in #188.

@timholy

timholy commented Dec 10, 2024

Copy link
Copy Markdown
Contributor Author

Did you check whether this is covered by #188? At least it seems the matrix element type is restricted in the same way in #188.

The eltype restriction is just a small cleanup. The key aspect of this is the "constructor cascade" that supports conversion/coercion via PDMat{T}(args...) or PDMat{T,S}(args...). This is needed to support, e.g., push!(pdmats, pdmat) where eltype(pdmats) may not be identical to typeof(pdmat). #188 doesn't add these methods.

Also, #188 is a pretty deep change, and it's been open for more than a year. I hoped this could get merged quickly and a new release made.

@timholy

timholy commented Dec 10, 2024

Copy link
Copy Markdown
Contributor Author

Concretely, if one runs the test block "test the functionality" from this PR on master, one gets this (with T = Float32):

Testing PDMat{Float32, Matrix{Float32}} of size (3, 3)
PDMat from Matrix: Error During Test at REPL[8]:7
  Got exception outside of a @test
  MethodError: no method matching (PDMat{Float64})(::Matrix{Float32})
  Stacktrace:

and several similar errors.

Comment thread src/pdmat.jl Outdated
@timholy

timholy commented Dec 10, 2024

Copy link
Copy Markdown
Contributor Author

If you're OK with it, I'd plan to solve the failure on Julia 1.0 by dropping support for anything before 1.10. Since this package is still in 0.x releases, we don't have to bump the minor version to do so.

The CI error on nightly is unrelated to this PR.

Comment thread src/pdmat.jl Outdated
Comment thread src/pdmat.jl Outdated
Comment thread src/pdmat.jl Outdated
Comment thread src/pdmat.jl Outdated
Comment thread src/pdmat.jl Outdated
Comment thread src/pdmat.jl Outdated
Comment thread src/chol.jl Outdated
Comment thread src/pdmat.jl Outdated
Comment thread src/pdmat.jl Outdated
@devmotion

Copy link
Copy Markdown
Member

If you're OK with it, I'd plan to solve the failure on Julia 1.0 by dropping support for anything before 1.10.

I'm fine with that but I'm still curious which and why some of the changes are problematic on Julia 1.0.

@timholy

timholy commented Dec 11, 2024

Copy link
Copy Markdown
Contributor Author

I'm fine with that but I'm still curious which and why some of the changes are problematic on Julia 1.0.

I'm a little puzzled about that as well. But it's only the @allocated test that fails and that is indeed pretty sensitive (especially in old Julias) to minor details. Looking at the produced code

julia> @code_typed PDMat(S, C)
CodeInfo(
22 1%1 = %new(PDMat{Float64,SArray{Tuple{4,4},Float64,2,16}}, mat, chol)::PDMat{Float64,SArray{Tuple{4,4},Float64,2,16}}                       │╻ Type
   └──      return %1                                                                                                                             │
) => PDMat{Float64,SArray{Tuple{4,4},Float64,2,16}}

it's a little weird that it allocates at all.

I dunno, I am not personally that interested in pursuing why Julia 1.0 allocates in this circumstance.

@timholy

timholy commented Dec 11, 2024

Copy link
Copy Markdown
Contributor Author

You may want to think about whether we want a5c0ce8, I added it hoping that it would fix the allocations on Julia 1.0. But it doesn't, and it makes the code more verbose; on the other hand, it tightens the applicability of the methods to things that can actually work. Let me know whether you'd prefer to drop it or keep it.

This adds a "constructor cascade" that allows one to coerce the inputs
to the chosen type. This is frequently useful in generic programming
where you want an object to be of the same type as something else,
for example when appending to a list of objects.

Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 83.87097% with 5 lines in your changes missing coverage. Please review.

Project coverage is 91.56%. Comparing base (fb363a3) to head (2785258).

Files with missing lines Patch % Lines
src/pdmat.jl 83.33% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #212      +/-   ##
==========================================
- Coverage   92.12%   91.56%   -0.56%     
==========================================
  Files           9        9              
  Lines         660      676      +16     
==========================================
+ Hits          608      619      +11     
- Misses         52       57       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@timholy

timholy commented Jan 2, 2025

Copy link
Copy Markdown
Contributor Author

This should be ready. Let me know if you want more changes. And thanks for the review, it was very helpful.

@devmotion devmotion merged commit 5e7d88e into JuliaStats:master Jan 17, 2025
@timholy timholy deleted the teh/coerce branch February 16, 2025 13:42
devmotion added a commit that referenced this pull request Jun 24, 2026
Resolve conflicts from master, preserving all master improvements while
keeping the PR's unification of `PDMat`/`PDSparseMat` and the SparseArrays
package extension.

Key resolutions:
- `PDMat` keeps the generalized 3-parameter struct (`mat::S`, `fact::F`);
  master's coercing constructors and `convert` methods are re-expressed
  against `fact`/`cholesky(...)` (with an added 3-parameter `convert`).
- Dense Cholesky operations stay on the general `PDMat`; `cholesky` is the
  only method restricted to the `PDMatCholesky` alias. The sparse extension
  overrides the CHOLMOD-specific methods by dispatch.
- Master's sparse `invwhiten`/`invunwhiten` methods and modernized
  `quad`/`quad!` are folded into the extension's `pdsparsemat.jl`; generic
  sparse operations now flow through the unified core `PDMat` methods.
- `congruence.jl` and `StatsBaseExt.jl` are narrowed to `PDMatCholesky` and
  switched from `.chol` to the `cholesky(...)` accessor (avoids catching
  sparse matrices and resolves dispatch ambiguities).
- Preserved master features: coercing constructors/convert (#212, #210),
  `invwhiten`/`invunwhiten` (#221), `ldiv!` (#228), the `kron` fix (#218),
  ForwardDiff-safe `whiten!`/`unwhiten!` (#217), `congruence.jl`, the
  StatsBase extension, and the Runic formatting (#220).
- Dropped pre-1.9 / Julia-1.0 compat shims (compat is now Julia >= 1.10);
  dropped the now-unused SuiteSparse dependency.
- Fixed a latent dead `quad`/`invquad` specialization (`<:Vector` ->
  `Matrix{T}`).
- Version bumped to 0.12.0 (breaking: `PDMat` struct parameters changed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants