Skip to content
This repository has been archived by the owner on Oct 14, 2023. It is now read-only.

Bitwise ops for integers #1665

Closed
wants to merge 7 commits into from
Closed

Bitwise ops for integers #1665

wants to merge 7 commits into from

Conversation

digama0
Copy link
Contributor

@digama0 digama0 commented Jun 13, 2017

Expansion of the previous commit to include VM implementations of integer bitwise operations.

@@ -382,4 +417,10 @@ by rw -int.sub_nat_nat_eq_coe; exact sub_nat_nat_elim m n
(λi n, by rw [nat.add_sub_cancel_left]; refl)
(λi n, by rw [add_assoc, nat.sub_eq_zero_of_le (nat.le_add_right _ _)]; refl)

#eval do m ← list.range 5,
Copy link
Member

Choose a reason for hiding this comment

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

Debugging code should not be in the library files.

| (m : ℕ) n := nat.test_bit m n
| -[1+ m] n := bnot (nat.test_bit m n)

def nat_bitwise (f : bool → bool → bool) (m n : ℕ) : ℤ :=
Copy link
Member

Choose a reason for hiding this comment

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

This function (and bitwise) doesn't seem to be used anywhere. Is there a reason we can't use it for lor, land, etc.?

Copy link
Contributor Author

@digama0 digama0 Jun 13, 2017

Choose a reason for hiding this comment

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

I'm torn on whether the definitional equality should be the reduction into positive/negative cases as I've done here, or the theorems bitwise or = lor etc. Either way we will have both, but definitional reduction can be important here.

Copy link
Member

Choose a reason for hiding this comment

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

I see, they are used in the theorems at the end of the file.


def div2 (n : ℕ) : ℕ := (bodd_div2 n).2

def bodd (n : ℕ) : bool := (bodd_div2 n).1
Copy link
Member

Choose a reason for hiding this comment

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

What was wrong with n % 2 = 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Dependence on WF definitions makes it more complicated for the kernel to reduce the definition. I didn't think it would be important, but it kept breaking proofs in weird ways.

Copy link
Member

Choose a reason for hiding this comment

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

I didn't think it would be important, but it kept breaking proofs in weird ways.

Do you still remember what it broke? As far as I can tell, bodd_div2 n only reduces if n is a numeral. But in this case I would have expected the WF definition to reduce as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not that it can't reduce; it reduces but only when unfold_lemmas is enabled. This causes a problem for binary_rec_eq, because the type of the theorem includes f ff 0 z = z (where the left side has type C (bit ff 0) and the right side has type C 0), so that any users of this theorem must also have unfold_lemmas enabled in order to reduce bit ff 0 := 0. If they don't, we are in the strange circumstance of having equalities embedded in constants whose type-correctness is not verifiable, and I have no idea what kind of guarantees lean can give in this situation.

Copy link
Member

Choose a reason for hiding this comment

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

Oooh, I see. Yes, this is really, really ugly. And we will probably see this again in the future, since it happens with every WF definition...

I see two potential solutions:

  1. Use equational rfl-lemmas for reduction in the type_context. This is a bit of work, and Leo has mentioned that there are lots of issues here.
  2. As a quick hack, we could special-case acc.rec (and maybe eq.rec and heq.rec?) in the type_context by reducing the major premise using transparency_mode::All.

BTW, we have exactly the same issue with attribute [irreducible].


/- gcd -/

def gcd.F : Π (y : ℕ), (Π (y' : ℕ), y' < y → nat → nat) → nat → nat
Copy link
Member

Choose a reason for hiding this comment

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

Can we define gcd using the equation compiler now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. We should probably also define div and mod using the equation compiler.

@gebner
Copy link
Member

gebner commented Jun 13, 2017

BTW, this PR doesn't build.

@digama0
Copy link
Contributor Author

digama0 commented Jun 14, 2017

Errors in the last commit were fixed, and it has been build-tested this time.


def div2 (n : ℕ) : ℕ := (bodd_div2 n).2

def bodd (n : ℕ) : bool := (bodd_div2 n).1
Copy link
Member

Choose a reason for hiding this comment

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

I didn't think it would be important, but it kept breaking proofs in weird ways.

Do you still remember what it broke? As far as I can tell, bodd_div2 n only reduces if n is a numeral. But in this case I would have expected the WF definition to reduce as well.

@[simp] lemma bodd_one : bodd 1 = tt := rfl
@[simp] lemma bodd_two : bodd 2 = ff := rfl

@[simp] def bodd_succ (n : ℕ) : bodd (succ n) = bnot (bodd n) :=
Copy link
Member

Choose a reason for hiding this comment

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

s/def/lemma/g

| (m : ℕ) n := nat.test_bit m n
| -[1+ m] n := bnot (nat.test_bit m n)

def nat_bitwise (f : bool → bool → bool) (m n : ℕ) : ℤ :=
Copy link
Member

Choose a reason for hiding this comment

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

I see, they are used in the theorems at the end of the file.

@gebner
Copy link
Member

gebner commented Jun 19, 2017

@digama0 This PR still has build errors.

@digama0
Copy link
Contributor Author

digama0 commented Jun 21, 2017

I think this PR is ready for merge (or at least ready for others to try to find issues with it) now.

@digama0 digama0 force-pushed the bitwise branch 3 times, most recently from 517a8c2 to c93b2c7 Compare June 22, 2017 23:51
@digama0
Copy link
Contributor Author

digama0 commented Jun 27, 2017

@gebner Is the "request changes" finished?

@gebner
Copy link
Member

gebner commented Jun 27, 2017

Is the "request changes" finished?

I still think that bodd_div2 is hideous, but I get why we need it.

We should define gcd using the equations compiler, but that can be done later. I don't think we can use the equations compiler for div and mod for bootstrapping reasons, since they are required by the tactics framework (more precisely init.data.repr) and the well-founded recursion support requires tactics.

@digama0
Copy link
Contributor Author

digama0 commented Jun 27, 2017

@gebner Actually the latest version of this PR does define gcd using the equation compiler. It did involve changing the definition so that it did induction on the left argument instead of the right, but I suppose gcd is commutative anyway so all the proofs are simply left-right mirrored.

The other reason for bodd_div2, which would remain even if WF definitions worked perfectly, is that it has different definitional equalities. I wanted bodd (succ n) = bnot (bodd n) to be a definitional equality instead of whatever you get with the mod definition.

@leodemoura
Copy link
Member

Merged based on @gebner approval.

@leodemoura leodemoura closed this Jun 28, 2017
@digama0 digama0 deleted the bitwise branch June 28, 2017 02:56
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants