Split out integer functions from the math module

The docs should just be updated to reflect the actual module scope which has evolved over time.

Moving functions between modules is unnecessarily disruptive for the entire python ecosystem and no one would actually be better off in the end. They would just have to look in two places to find what they want. From a user point-of-view, it is all just math (stuff you would find on a calculator). They really don’t care about how closely it is tied to C math library.

Also there are functions like ceil and floor that have become divorced from the C standard. The Python versions are just ways to convert floats to integers. The C version is double to double.

ISTM the only problem being solved by the proposal is that you feel some definitional dissonance. In the world of Python users, there isn’t an actual problem. People just use the math module as is. The only problem I’ve ever had the with module is that a star-import brings in math.pow which shadows the builtin pow function. It would be nice to have that one renamed to fpow.

5 Likes

I’m assuming that the functions would still be importable as they are now so there would be no immediate disruption.

As I noted in the initial post, supporting backward-compatible aliases has essentially 0-maintenance cost. We can do this forever, i.e. soft-deprecate them.

It depends. If they look for functions over integers — there will be a logical place. Same from libm’s wrappers (current math module).

I’m not sure you find gcd or comb (whatever it may be named) on a calculator.

I don’t think it’s true. Keep in mind, that C versions also return integers (float type with integer value). The Python versions just utilize the bigint type (missing in C): C can’t return some integer type, because all they will all overflow eventually.

I would say that star import is the problem.

BTW, I would rather buy a powmod() function as builtin. Two-arg form actually aren’t that useful.

1 Like

This is complicated by that slamming unrelated functions into a single module makes careful docs more verbose and/or hard to follow. For example, the current math module docs still say:

Except when explicitly noted otherwise, all return values are floats.

Which used to be true, but which has become nonsense. None of comb. factorial, gcd, isqrt, lcm, perm, floor, or ceil returns a float, but the docs don’t say so. In a hypothetical imath, where they belong, a similar catch-all:

Except when explicitly noted otherwise, all return values are ints.

could tell the truth just once. Shared context is … shared. Cuts the verbosity of the docs and reduces the conceptual load. As is, we’ve settled for docs that stopped being truthful years ago.

Splitting functions into related groups also aids discoverability. For example, I don’t believe anyone has ever suggested pushing the statistics module functions into math, and such a thing was never considered to begin with, despite that those too are “just math”. If you’re working with statistics, that’s the module you work with, and your IDE will suggest helpful completions when you ask it what starts with statistics.xyz...

Same thing for any module with focus. When I’m, .e.g., working on a problem in combinatorics, I have 0 interest in seeing an IDE suggesting any float functions. I’m working with ints then, and anything having to do with floats is pure noise for the duration.

Similarly, if I’m working with trig functions then anything having to do with ints is pure noise for the duration. I actively, e.g., do not want to see comb come up when what I want is cos.

Little things like that matter too. They add up :smile:.

6 Likes

See previous attempt: Add a module for integer related math functions · Issue #81313 · python/cpython · GitHub.

7 Likes

Wow - thanks for sharing that link! I have no memory of it. Seems that I’ve changed my mind in the last 6 years :smile:.

2 Likes

+1. I was would have preferred that issue above had been implemented, before more int functions were added, but I missed it or said nothing. Only 4 people particupated. We already have more here.

I would like to see a PEP aimed at 3.15 that only proposes new module and soft deprecation. Issue included 2 new functions which gave more motivation then (2019) but also muddied discussion. Leave isqrt as is. I think being able to enter, for instance, imath.<tab> and get a coherent list of possible attributes is an important point (one I did not think of), so include it. len(dir(math)) is 67 – and likely to grow in any case.

3 Likes

Ok, here is a draft, waiting for a sponsor/co-author: Draft PEP: imath --- module for number-theoretic functions by skirpichev · Pull Request #6 · skirpichev/peps · GitHub

Sorry, it’s not rendered in my fork. I hope it’s still readable enough in the rst form.

I think new pep should describe also module scope and suggest which extensions are possible and which aren’t.

Thanks, I included that in Post-History. Unfortunately, linter doesn’t like urls, that points to github.

1 Like

Note: imath is a project on PyPI, but only with two releases (0.0.1 & 0.0.2), most recently 4 years ago in 2021. You may want to contact the authors to see if they are willing to donate the namespace. Not strictly a requirement, as a PEP can be approved notwithstanding PyPI, but it would probably help the proposal.

imaths is unreserved, as is intmath integermath, etc

A

3 Likes

But the versions in math will be deprecated, and eventually removed, causing disruption in a few years, because developers ignore warnings, because they wanted to support older Pythons, or because libraries using those functions are no longer maintained.

Why? The suggestion is to keep aliases.

@skirpichev is suggesting “soft deprecation”, which is defined in PEP 387. Such things are NOT scheduled for removal, and don’t even generate warnings.

Instead the docs discourage their use, point to the preferred alternative, and no further development will be done on them.

5 Likes

(I made this observation in the ceiling division thread, and @oscarbenjamin redirected me here)

For folks suggesting imath as the module name: remember that j is the electrical engineering spelling of the square root of negative 1. The normal mathematical spelling is i, making imath more ambiguous than we might like it to be (I’m personally not a huge fan of math.isqrt for the same reason).

intmath (as suggested by @AA-Turner above) wouldn’t be much longer, would be pretty self-explanatory (unlike ntheory) even for beginners first encountering the concept of arithmetic that’s explicitly limited to integer values, and wouldn’t conflict with any package name on PyPI.

11 Likes

I hope my draft take this variant into account. The imath version seems to be most supported so far.

I think naming is a minor point, this can be decided later if the math split does make sense at all.

2 Likes

Python isn’t only for rank newbies :wink:. “isqrt” has been in very widespread use for many years in software, dating back at least to Macsyma (late 1960s).

So it would be a disservice to its primary audience to name it something else. Anyway, that ship already sailed.

The same audience won’t be confused by “imath” either. Imaginary numbers on their own aren’t much of “a thing” - they’re subsumed by complex numbers, and cmath is their natural home.

As someone with substantial numeric experience, my first thought at seeing intmath is that it’s probably a collection of functions for doing numerical integration, which is a deep pit all on its own.

“First impressions” vary widely by audience, and I don’t much care about them. What I do care about a lot is whether something is easy to remember and hard to forget after the initial learning curve has been climbed.

Although, admittedly, the learning curve in this case is trivially shallow for imath or intmath. Which do people prefer?

  • intmath
  • imath
  • something else
0 voters

[EDIT] A meta-comment about DIscourse polls. It’s well known that people are biased toward voting for the top-listed candidate in any election. That’s why the voting software the PSF uses randomizes candidate order on ballots, per voter, in PSF elections. So I tried to counter my own mild preference for imath by listing intmath first when I created the poll. But Discourse appears to dynamically reorder the choices from most-votes-so-far to least. That leaves imath at the top now, as I type.

Response to meta-comment, collapsed to hopefully avoid going further off-topic:

I haven’t voted yet, and intmath is on top for me:

It might differ for you since you have, or since you’re the poll creator. intmath is also on top for a logged-out session.

1 Like

It could be that the dynamic reordering in only done when looking at the results. intmath is on top in both views for me now.

I voted for imath, it’s the logical choice due to it being a well known naming convention already, but that’s only if splitting the functions into another module is the correct rectification. Has there been any thought on moving cmath and statistics into the math module as submodules?

2 Likes

Hmm, given my math background I would first think: “Hey, interval arithmetic finally made it into Python.” :slight_smile:

On the topic, I don’t think splitting the integer math function off into a separate module buys us anything.

The reason we have the cmath module is to avoid adding lots of type checks and special casing to the math functions of the same names and thus slowing down the more regular use cases of e.g. sin() et al.

The same reason does not necessarily apply to integers vs. floats - I doubt many people would want to use an integer version of sin() :slight_smile:

11 Likes

Yup. intmath on its own has several plausible readings too.

That’s overstated. Several benefits were already identified. None are dispositive, though:

  • Simplifying, and improving coherence of, the docs. For example. the docs have been lying for years about that all math module functions return floats unless explicitly noted otherwise. But none of the int-valued functions are documented as being exceptions to that statement.

  • Improving discoverability, & especially in IDEs. Again an example was given that when I’m looking for comb(), I don’t want to be bothered with suggestions that maybe I want “cosh()” or “copysign()” (etc) after I type the initial “c”. I can spend a month writing combinatorics-heavy apps that only ever want integer functions, almost never float ones. There are dozens and dozens of math functions that are irrelevant to me for the duration. YMMV. I expect many others are mildly but persistently annoyed by seeing their IDE endlessly suggesting int-valued functions when they go for months only wanting the float-valued ones.

  • Ending the argument that “well, we can’t add that to math, because that’s for libm’s float functions”. Which, in fact, it was intended to be. That same objection has been raised for decades, for every suggested addition to math that goes beyond C’s libm. It’s tiresome. Although, to be fair, it carries almost no weight anymore, since it’s been overruled so often by now.

It wasn’t about speed at first. There were multiple reasons at work.

The pragmatic one was that std C at the time had no support for complex, and Guido didn’t want to be in the math library business - development resources were extremely limited, and there were far more important things to do. Wrap the platform libm with a minimum of fuss and move on.

The “principled” one was that Guido judged most potential users didn’t have sufficient background to make head or tail of what getting back 1j from sqrt(-1) could possibly mean, or what to do about it. Far more likely it was pointing to an error in their earlier code.

So, fine, introduce cmath for those comfortable in that world, but don’t impose it on everyone.

I agree that the existence, and history, of cmath, is mostly irrelevant here.

Even now that std C does support complex, the original reason (“don’t impose it on everyone”) still applies. Plus now it would also be partially about speed.

2 Likes