Including elementary mathematical functions in the python data model
Hi,
It would be really nice if elementary mathematical operations such as sin/cosine (via __sin__ and __cos__) were available as base parts of the python data model [0]. This would make it easier to write new math classes, and it would eliminate the ugliness of things like self.exp().
This would also eliminate the need for separate math and cmath libraries since those could be built into the default float and complex types. Of course if those libs were removed, that would be a potential backwards compatibility issue.
It would also help new users who just want to do math and don't know that they need to import separate classes just for elementary math functionality.
I think full coverage of the elementary function set would be the goal (i.e. exp, sqrt, ln, trig, and hyperbolic functions). This would not include special functions since that would be overkill, and they are already handled well by scipy and numpy.
Anyway, just a thought.
Best wishes, Mike
On Wed, Sep 22, 2010 at 4:44 AM, Michael Gilbert michael.s.gilbert@gmail.com wrote:
Hi,
It would be really nice if elementary mathematical operations such as sin/cosine (via __sin__ and __cos__) were available as base parts of the python data model [0]. This would make it easier to write new math classes, and it would eliminate the ugliness of things like self.exp().
This would also eliminate the need for separate math and cmath libraries since those could be built into the default float and complex types. Of course if those libs were removed, that would be a potential backwards compatibility issue.
It would also help new users who just want to do math and don't know that they need to import separate classes just for elementary math functionality.
I think full coverage of the elementary function set would be the goal (i.e. exp, sqrt, ln, trig, and hyperbolic functions). This would not include special functions since that would be overkill, and they are already handled well by scipy and numpy.
I think the basic problem here is that, by comparison to the basic syntaxdriven options, the additional functionality covered by the math, cmath and decimal modules is much harder to implement both correctly and efficiently. It's hard enough making good algorithms that work on a single data type with a known representation, let alone ones which work on arbitrary data types.
Also, needing exp, sqrt, ln, trig and hyperbolic functions is *significantly* less common than the core mathematical options, so telling people to do "from math import *" if they want to do a lot of mathematical operations at the interactive prompt isn't much of a hurdle.
Cheers, Nick.
On Tue, Sep 21, 2010 at 7:44 PM, Michael Gilbert michael.s.gilbert@gmail.com wrote:
It would be really nice if elementary mathematical operations such as sin/cosine (via __sin__ and __cos__) were available as base parts of the python data model [0]. This would make it easier to write new math classes, and it would eliminate the ugliness of things like self.exp().
This would also eliminate the need for separate math and cmath libraries since those could be built into the default float and complex types.
Hmm. Are you proposing adding 'sin', 'cos', etc. as new builtins? If so, I think this is a nonstarter: the number of Python builtins is deliberately kept quite small, and adding all these functions (we could argue about which ones, but it seems to me that you're talking about around 18 new builtinse.g., 6 trig and inverse trig, 6 hyperbolic and inverse hyperbolic, exp, expm1, log, log10, log1p, sqrt) would enlarge it considerably. For many users, those functions would just be additional bloat in builtins, and there's possibility of confusion with existing variables with the same name ('log' seems like a particular candidate for this; 'sin' less likely, but who knows ;).
A less invasive proposal would be just to introduce __sin__, etc. magic methods and have math.sin delegate to <type>.__sin__; i.e., have math.sin work in exactly the same way that math.floor and math.ceil currently work. That would be quite nice for e.g., the decimal module: you'd be able to write something like:
from math import sqrt root = (b + sqrt(b*b  4*a*c)) / (2*a)
to compute the root of a quadratic equation, and it would work regardless of whether a, b, c were Decimal instances or floats.
I'm not sure how I feel about the entailed magic method explosion, though.
Mark
On Sun, Sep 26, 2010 at 9:05 PM, Mark Dickinson dickinsm@gmail.com wrote:
A less invasive proposal would be just to introduce __sin__, etc. magic methods and have math.sin delegate to <type>.__sin__; i.e., have math.sin work in exactly the same way that math.floor and math.ceil currently work. That would be quite nice for e.g., the decimal module: you'd be able to write something like:
from math import sqrt root = (b + sqrt(b*b  4*a*c)) / (2*a)
to compute the root of a quadratic equation, and it would work regardless of whether a, b, c were Decimal instances or floats.
I'm not sure how I feel about the entailed magic method explosion, though.
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
Cheers, Nick.
On Sun, 26 Sep 2010 22:07:50 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
On Sun, Sep 26, 2010 at 9:05 PM, Mark Dickinson dickinsmRe5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
A less invasive proposal would be just to introduce __sin__, etc. magic methods and have math.sin delegate to <type>.__sin__; i.e., have math.sin work in exactly the same way that math.floor and math.ceil currently work. That would be quite nice for e.g., the decimal module: you'd be able to write something like:
from math import sqrt root = (b + sqrt(b*b  4*a*c)) / (2*a)
to compute the root of a quadratic equation, and it would work regardless of whether a, b, c were Decimal instances or floats.
I'm not sure how I feel about the entailed magic method explosion, though.
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
At the cost of even more execution overhead? :)
Regards
Antoine.
On Sun, Sep 26, 2010 at 10:25 PM, Antoine Pitrou solipsis@pitrou.net wrote:
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
At the cost of even more execution overhead? :)
I did put that "efficient" in there for a reason! Now, I'm not saying anything about how *reasonable* that idea is, but I can dream ;)
Cheers, Nick.
On Sun, 26 Sep 2010 22:34:06 +1000 Nick Coghlan ncoghlan@gmail.com wrote:
On Sun, Sep 26, 2010 at 10:25 PM, Antoine Pitrou solipsis@pitrou.net wrote:
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
At the cost of even more execution overhead? :)
I did put that "efficient" in there for a reason! Now, I'm not saying anything about how *reasonable* that idea is, but I can dream ;)
Well, I can't see how it could be less than the overhead involved in a sqrt(x) > x.__sqrt__() indirection anyway.
When I read Mark's example, I wondered why he didn't simply write x**0.5 instead of sqrt(x), but it turns out it doesn't work on decimals.
cheers
Antoine.
On 20100926, at 14:07 , Nick Coghlan wrote:
On Sun, Sep 26, 2010 at 9:05 PM, Mark Dickinson dickinsm@gmail.com wrote:
A less invasive proposal would be just to introduce __sin__, etc. magic methods and have math.sin delegate to <type>.__sin__; i.e., have math.sin work in exactly the same way that math.floor and math.ceil currently work. That would be quite nice for e.g., the decimal module: you'd be able to write something like:
from math import sqrt root = (b + sqrt(b*b  4*a*c)) / (2*a)
to compute the root of a quadratic equation, and it would work regardless of whether a, b, c were Decimal instances or floats.
I'm not sure how I feel about the entailed magic method explosion, though.
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
Cheers, Nick.
Couldn't that also be managed via ABCs for numerical types? Make sqrt & al methods of those types, and roll out in the sunset, no? The existing `math` functions could check on the presence of those methods (or the input types being instances of the ABCs they need), and fall back on the current implementations if they don't match.
On Sun, Sep 26, 2010 at 7:07 AM, Nick Coghlan ncoghlan@gmail.com wrote:
On Sun, Sep 26, 2010 at 9:05 PM, Mark Dickinson dickinsm@gmail.com wrote:
A less invasive proposal would be just to introduce __sin__, etc. magic methods [...]
I'm not sure how I feel about the entailed magic method explosion, though.
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
This could certainly be implemented so as to be fast for floats and flexible for everything else.
j
Nick Coghlan wrote:
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
Could a generic function mechanism be made to have any less overhead, though?
On Mon, Sep 27, 2010 at 8:29 AM, Greg Ewing greg.ewing@canterbury.ac.nz wrote:
Nick Coghlan wrote:
Couple that with the extra function call overhead (since these wouldn't have real typeslots) and it still seems like a less than stellar idea.
As another use case for solid, efficient generic function support though... great idea :)
Could a generic function mechanism be made to have any less overhead, though?
See my response to Antoine  probably not. Although, as has been pointed out by others, by doing the check for PyFloat_CheckExact early and running the fast path immediately if that check passes, you can avoid most of the overhead in the common case, even when using pseudotypeslots. So performance impact likely isn't a major factor here after all.
Cheers, Nick.
participants (7)

Antoine Pitrou

Greg Ewing

Jason Orendorff

Mark Dickinson

Masklinn

Michael Gilbert

Nick Coghlan