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

Template for modulo operations #40

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

bjorn-martinsson
Copy link
Collaborator

One of the most common codes that I've looked up over time is a mod template that I wrote many years ago for a private repository. It is useful enough to be used around once every second competition.

I cleaned up my old code, and added some extra features to it. I think this could be a super useful template to have on PyRival!

Note that I have yet to add tests to it, I will do that tomorrow.

@cheran-senthil What do you think about this template? I think it is both very simple and super useful to have.

@bjorn-martinsson
Copy link
Collaborator Author

As a small note on the fast mod mul. Locally on my windows computer using PyPy the code runs around a factor of 10 faster with modmul compared to doing a * b % MOD.

Copy link
Owner

@cheran-senthil cheran-senthil left a comment

Choose a reason for hiding this comment

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

I think we can move this to the misc folder, and probably decide on naming later. Overall, I'm quite happy with the code, and we can merge whenever you think this is ready.

pyrival/algebra/mod_template.py Outdated Show resolved Hide resolved
or calculate matrix multiplication mod MOD.
"""

def fast_modder(MOD):
Copy link
Owner

Choose a reason for hiding this comment

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

Perhaps call this make_modmul?


def fast_modder(MOD):
""" Returns function modmul(a,b) that quickly calculates a * b % MOD, assuming 0 <= a,b < MOD """
import sys, platform
Copy link
Owner

Choose a reason for hiding this comment

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

I'm tempted to move this up, to the top of the file, even though this is specific.

pyrival/algebra/mod_template.py Outdated Show resolved Hide resolved
pyrival/algebra/mod_template.py Outdated Show resolved Hide resolved
def redu(x):
return x if x < MOD else x - MOD

def matrix_modmul(A, B):
Copy link
Owner

Choose a reason for hiding this comment

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

We have something for this elsewhere, so let's remove that too.

import sys, platform
impl = platform.python_implementation()
maxs = sys.maxsize
if 'PyPy' in impl and MOD <= maxs and MOD ** 2 > maxs:
Copy link
Owner

Choose a reason for hiding this comment

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

You can actually check impl == 'PyPy'. Seems to work on PyPy3 as well.

@cheran-senthil
Copy link
Owner

With the new version of PyPy on Windows, what are your thoughts on this moving forward?

@bjorn-martinsson
Copy link
Collaborator Author

With the new version of PyPy on Windows, what are your thoughts on this moving forward?

Once CF updates (assuming it ever updates) then we can remove all the fast modmul stuff from the template. But I still think this template has its uses even after that.

""" Calculate n choose k in O(1) time """
if k < 0 or k > n:
return 0
return modmul(modmul(fac[n], fac_inv[k]), fac_inv[n - k])
Copy link
Contributor

Choose a reason for hiding this comment

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

fac_inv should be inv_fac here. 🙂

@cheran-senthil
Copy link
Owner

This is probably not necessary anymore since 64bit has become the standard

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.

3 participants