Skip to content
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

Binary XGCD #761

Draft
wants to merge 161 commits into
base: master
Choose a base branch
from
Draft

Binary XGCD #761

wants to merge 161 commits into from

Conversation

erik-3milabs
Copy link
Contributor

Continuation of the work started in #755

@erik-3milabs erik-3milabs mentioned this pull request Feb 14, 2025
Comment on lines +87 to +91
/// **Warning**: this algorithm is only guaranteed to work for `self` and `rhs` for which the
/// msb is **not** set. May panic otherwise.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you elaborate a bit on where this restriction comes from and if it's a hard requirement or not? Skimming the example code for the paper doesn't seem to mention this.

It's a pretty limiting restriction; I think many applications will want to use full-fat uints with the MSB set.

Copy link
Contributor Author

@erik-3milabs erik-3milabs Mar 20, 2025

Choose a reason for hiding this comment

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

Can you elaborate a bit on where this restriction comes from and if it's a hard requirement or not? Skimming the example code for the paper doesn't seem to mention this.

It's a pretty limiting restriction; I think many applications will want to use full-fat uints with the MSB set.

I was encountering integer overflows whenever the top bit was set. However, in the past two days I learned a fact and a trick that we can use:

The trick

Currently, I'm using an Ints inside the matrix representing the xgcd state. However, I learned this interesting fact that the signs of this state matrix will always occur in one of the following two patterns:

[ + - ]       [ - + ]
[ - + ]   or  [ + - ]

Because of this, I can refactor this matrix to use Uints instead, as long as it also holds a pattern: ConstChoice. Then, the multiplication M3 = M1 x M2 is computed as a standard matrix multiplication and M3.pattern = M1.pattern.eq(M2.pattern).

This saves one bit in the representation and, as a result, should prevent overflows.

The fact.

This morning, I learned that if a does not divide b (or the other way around), then the Bézout coefficients x,y such that ax + by = gcd are such that $$|x| \leq \lfloor\frac{b}{2 * gcd}\rfloor$$ and $$|y| \leq \lfloor\frac{a}{2 * gcd}\rfloor$$.

These two things combined should give us ample bits to compute the Bézout coefficients without overflowing.

I hope to work on this soon!

Copy link
Contributor

Choose a reason for hiding this comment

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

That is good news! Thank you for explaining.

Can you point me to a source on “the fact”?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But of course! It is stated as fact on Extended GCD Wikipedia page, at the end of the Description section. Not the world's greatest source, but all my experiments point in the same direction 🙈

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.

2 participants