Skip to content

Conversation

@luisacicolini
Copy link
Contributor

@luisacicolini luisacicolini commented Nov 19, 2025

This PR adds the definition of BitVec.cpop, which relies on the more general BitVec.cpopNatRec, and build some theory around it. The name cpop aligns with the RISCV ISA nomenclature.

Co-authored-by: @tobiasgrosser, @bollu

Copy link
Contributor

@tobiasgrosser tobiasgrosser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some early comments. This is going in a great direction.

@luisacicolini luisacicolini changed the title feat: add BitVec.popCount and build theory around it feat: add BitVec.cpop and lemmas around it Nov 20, 2025
@github-actions github-actions bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Nov 20, 2025
@leanprover-community-bot
Copy link
Collaborator

leanprover-community-bot commented Nov 20, 2025

Mathlib CI status (docs):

  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 9fc90488ce239cfe8e4317269d37fe4160787d0d --onto a106ea053fec080a50204b0ad6dadc69bc3f0937. You can force Mathlib CI using the force-mathlib-ci label. (2025-11-20 20:35:04)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 9fc90488ce239cfe8e4317269d37fe4160787d0d --onto 5306a3469d20caa5f9d80384a5c1effdb14e9c67. You can force Mathlib CI using the force-mathlib-ci label. (2025-11-21 11:26:56)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 3772bb8685f2fdf414e8aa4af6f1d2964b2f64af --onto b0e6db322421ce368999f08870fd747e45242f86. You can force Mathlib CI using the force-mathlib-ci label. (2025-11-26 11:21:06)
  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2025-11-27 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. You can force Mathlib CI using the force-mathlib-ci label. (2025-11-27 10:17:58)
  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2025-11-29 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. You can force Mathlib CI using the force-mathlib-ci label. (2025-11-29 17:49:36)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 0e83422fb6337985c3354c263a9510cbcb4b1e05 --onto 5bd331e85d9d110a29fb3367dbb21854010ffcbd. You can force Mathlib CI using the force-mathlib-ci label. (2025-12-02 15:24:03)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 0e83422fb6337985c3354c263a9510cbcb4b1e05 --onto dd28f005889dd2fcca6fe0638133de561a655ad1. You can force Mathlib CI using the force-mathlib-ci label. (2025-12-05 10:25:03)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 0e83422fb6337985c3354c263a9510cbcb4b1e05 --onto 455fd0b4488e2adc85f825a52e2ee7d944a5740a. You can force Mathlib CI using the force-mathlib-ci label. (2025-12-05 15:21:59)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 0e83422fb6337985c3354c263a9510cbcb4b1e05 --onto 2ca3bc28590c5c33f755d3bd18252f25ea266266. You can force Mathlib CI using the force-mathlib-ci label. (2025-12-08 11:12:52)

@leanprover-bot
Copy link
Collaborator

leanprover-bot commented Nov 20, 2025

Reference manual CI status:

  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 9fc90488ce239cfe8e4317269d37fe4160787d0d --onto d3dda9f6d4428a906c096067ecb75e432afc4615. You can force reference manual CI using the force-manual-ci label. (2025-11-20 20:35:06)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 3772bb8685f2fdf414e8aa4af6f1d2964b2f64af --onto d3dda9f6d4428a906c096067ecb75e432afc4615. You can force reference manual CI using the force-manual-ci label. (2025-11-26 11:21:08)
  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2025-11-27 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2025-11-27 10:18:00)
  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2025-11-29 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2025-11-29 17:49:38)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 0e83422fb6337985c3354c263a9510cbcb4b1e05 --onto d3dda9f6d4428a906c096067ecb75e432afc4615. You can force reference manual CI using the force-manual-ci label. (2025-12-02 15:24:05)

Copy link
Contributor

@bollu bollu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going in a nice direction!

I think we should have a definition called cpopAux (x : BitVec w) : Nat := cpopAuxRec x w, and then define cpop in terms of cpopAux. In some sense cpopAux is the "real population count" (as a number), and cpop is a convenience function we provide to coerce the result into a bitvector.


Along similar lines, I would personally decouple the input and output widths of cpop, to have the signature be

def cpop {v : Nat} (w : Nat) (x : BitVec v) : BitVec w := BitVec.ofNat w x

I'm not 100% sure this is the right design, but it feels a lot less arbitrary to me than choosing the output width, when popCount is really counting a natural number.


As always, this is not final, and I'm trying to navigate the design space just as much as you are, so I'm happy to pair on this!

@bollu
Copy link
Contributor

bollu commented Nov 26, 2025

Also, note that popcount is uniquely defined by three equations:

popCount (x ++ y) = popCount x + popCount y
popCount (x#0) = 0
popCount (BitVec.ofBool b) = b.toNat

These tell us that popcount is a monoid homomorphism from bitvectors to naturals, and does the "correct" thing. I'd like us to prove these lemmas, and to define popcount such that these hold with small proofs :) So this would have us replace the if b then 1 else 0 with b.toNat

Copy link
Contributor

@tobiasgrosser tobiasgrosser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the update. A first set of comments.

@tobiasgrosser
Copy link
Contributor

tobiasgrosser commented Nov 27, 2025

  • Update the PR message BitVec.cpopAuxRec to BitVec.cpopNatRec

It would also be nice if the default type conversion theorems are implemented, e.g., toNat, toFin, toInt, as well as getMsb, getLsb, msb. We can potentially do this in a fullow-up PR or after having gotten an initial review.

@luisacicolini luisacicolini marked this pull request as ready for review December 5, 2025 15:29
@luisacicolini luisacicolini requested a review from kim-em as a code owner December 5, 2025 15:29
@luisacicolini
Copy link
Contributor Author

changelog-library

@luisacicolini luisacicolini changed the title feat: add BitVec.cpop and lemmas around it feat: add BitVec.cpop and lemmas Dec 5, 2025
Copy link
Contributor

@hargoniX hargoniX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks quite good! I'll defer to Markus after the two remaining remarks.

omega
· omega

theorem cpop_cons {x : BitVec w} {b : Bool} :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are the toNat versions simp and not these ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the toNat theorem the rhs seems definitely easier than the lhs, for this theorem I don't think that's necessarily true, because of the setWidth. Do you think that is strictly easier even with the setWidth?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIU, the convention is to push toNat inwards. I do not think we have a canonical form for the plain cpop_cons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-library Library toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants