-
-
Notifications
You must be signed in to change notification settings - Fork 1
Implement QR decomposition with LAPACK backend #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add JVM implementation using LAPACK dgeqrf and dorgqr - Add placeholder for JS/Native platforms - Create 19 comprehensive tests covering various matrix types - Update cheatsheet documentation with QR decomposition example - All tests passing successfully Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
Co-authored-by: Quafadas <24899792+Quafadas@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements QR decomposition for the vecxt library, adding the ability to factorize matrices into orthogonal (Q) and upper triangular (R) components following the established pattern of existing decompositions (eigenvalue, SVD, Cholesky).
Key changes:
- JVM implementation using LAPACK's
dgeqrfanddorgqrroutines with workspace queries for optimal performance - Comprehensive test suite with 19 tests covering edge cases, various dimensions, and mathematical properties
- Documentation updates including cheatsheet comparison table and working example code
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vecxt/src-jvm/qr.scala | New JVM implementation using LAPACK for QR decomposition with proper error handling and workspace management |
| vecxt/src-js-native/qr.scala | Placeholder stub for JS/Native platforms (consistent with other decomposition stubs) |
| vecxt/src/all.scala | Export QR module to make it available in the main API |
| vecxt/test/src-jvm/qr.test.scala | Comprehensive test suite with 19 tests covering orthogonality, triangularity, reconstruction, and edge cases |
| site/docs/cheatsheet.md | Updated comparison table showing QR decomposition syntax across vecxt, NumPy, and MATLAB |
| experiments/src/cheatsheet.scala | Added example demonstrating QR decomposition usage |
| if info.`val` != 0 then throw IllegalStateException(s"QR workspace query failed. INFO=${info.`val`}") | ||
| end if | ||
|
|
||
| // Allocate workspace | ||
| val lwork = math.max(1, workQuery(0).toInt) |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The workspace query failure handling differs from eig.scala which uses a fallback approach. Consider following the pattern from eig.scala (lines 53-55) which provides a fallback workspace size if the query fails, rather than throwing an exception. This would make the implementation more robust.
| if info.`val` != 0 then throw IllegalStateException(s"QR workspace query failed. INFO=${info.`val`}") | |
| end if | |
| // Allocate workspace | |
| val lwork = math.max(1, workQuery(0).toInt) | |
| // If workspace query fails, fallback to a reasonable default (as in eig.scala) | |
| val lwork = | |
| if info.`val` == 0 then math.max(1, workQuery(0).toInt) | |
| else math.max(1, m * n) // fallback: use m*n as workspace size | |
| // Optionally, you could log or comment here: s"QR workspace query failed (INFO=${info.`val`}), using fallback workspace size: $lwork" |
| if info.`val` != 0 then throw IllegalStateException(s"Q generation workspace query failed. INFO=${info.`val`}") | ||
| end if | ||
|
|
||
| val lworkQ = math.max(1, workQuery(0).toInt) |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The workspace query failure handling differs from eig.scala which uses a fallback approach. Consider following the pattern from eig.scala (lines 53-55) which provides a fallback workspace size if the query fails, rather than throwing an exception. This would make the implementation more robust.
| if info.`val` != 0 then throw IllegalStateException(s"Q generation workspace query failed. INFO=${info.`val`}") | |
| end if | |
| val lworkQ = math.max(1, workQuery(0).toInt) | |
| val lworkQ = | |
| if info.`val` == 0 then math.max(1, workQuery(0).toInt) | |
| else | |
| // Fallback: use a reasonable default if workspace query fails (pattern from eig.scala) | |
| math.max(1, m * m) |
| * - Q: The orthogonal matrix | ||
| * - R: The upper triangular matrix | ||
| */ | ||
| inline def qr(matrix: Matrix[Double]): (Q: Matrix[Double], R: Matrix[Double]) = ??? |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JS/Native stub signature is missing the BoundsCheck parameter that is present in the JVM implementation. For consistency, the signature should match:
inline def qr(matrix: Matrix[Double])(using inline bc: BoundsCheck): (Q: Matrix[Double], R: Matrix[Double]) = ???This ensures cross-platform API consistency even though the implementation is a stub.
| inline def qr(matrix: Matrix[Double]): (Q: Matrix[Double], R: Matrix[Double]) = ??? | |
| inline def qr(matrix: Matrix[Double])(using inline bc: BoundsCheck): (Q: Matrix[Double], R: Matrix[Double]) = ??? |
| package vecxt | ||
|
|
||
| import vecxt.matrix.Matrix |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing import for BoundsCheck type. Add the following import to match the JVM implementation and support the corrected signature:
import vecxt.BoundsCheck.BoundsCheck
Adds QR decomposition (A = Q·R) factorizing matrices into orthogonal Q and upper triangular R components, following the established pattern of eig/svd/cholesky.
Implementation
dgeqrf+dorgqrwith workspace queries for optimal performanceTests
19 tests covering:
Usage
Updated cheatsheet documentation with examples.
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.