[Use Case]: Recursively calculating determinant of Matrix<M, M>

Open
#49 0 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
30/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
rust
Domain
compilers

Research direction

Start with the two linked nightly Rust Playground examples, then inspect the recursive determinant code and the simplified get_one() case described in src/lib.rs. Reproduce the unconstrained generic constant error and review the linked Zulip discussion. Done means establishing the expected compiler behavior and identifying a concrete, agreed path to address it.

Written by the indexing model from the issue text.

Description

A-generic_const_exprs C-experience-report
Code description

I've been enjoying using const generics to implement a simple struct Matrix<const M: usize, const N: usize>.

I successfully implemented a fn submatrix(&self, row: usize, column: usize) -> Matrix<{ M - 1 }, { N - 1 }> using feature(generic_const_exprs).

Next, I wanted to calculate the determinant using recursion. For the determinant of a generic square Matrix<M, M> it needs to calculate the cofactors of the matrix, and they require calculating the determinants of submatrices Matrix<M - 1, M - 1>. This happens recursively until you have a 2x2 matrix, at which point you can calculate the determinant of that directly and the recursion can unwind.

What worked well

I was able to successfully implement most of the supporting functions for calculating the determinant.

What worked less well

Once the recursive aspect was in place, I received a compiler error:

error: unconstrained generic constant
  --> src/lib.rs:64:19
   |
64 |         submatrix.determinant()
   |                   ^^^^^^^^^^^
   |
   = help: try adding a `where` bound using this expression: `where [(); M - 1]:`
note: required by a bound in `Matrix::<M, M>::determinant`
  --> src/lib.rs:45:14
   |
43 |     pub fn determinant(&self) -> f32
   |            ----------- required by a bound in this
44 |     where
45 |         [(); M - 1]:,
   |              ^^^^^ required by this bound in `Matrix::<M, M>::determinant`

However the suggested where bound already exists on the function.

I have one code sample showing the specific matrix case:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=143d8b7005a53b59d8a91953e41e1121

I have another simplified example showing the same error with less code:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=2151c05d5e451fd14929fb16792520ff

Here the problematic function is get_one(). The idea is that when you call get_one() on an A<S> it will use recursion to return you an A<1>. This is dumb, but it shows the issue.

There has been some discussion on Zulip:

https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/Recursive.20method.20calls.20with.20generic_const_exprs

Dominant language
No language data
Stars
54
Forks
11
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-lang/project-const-generics

All issues in rust-lang/project-const-generics

Similar issues

More Compilers issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.