You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
+1. This is part of C99, so if it's also supported by Visual Studio, then this seems like a no-brainer. If it's _not_ also supported by Visual Studio, or if there are implementations that have serious numerical problems (as was the case with fma) we'll need to write our own fallback implementation, which is less simple.
In principle it should be relatively easy for a math library to provide a correctly-rounded cbrt.
BTW, to forestall questions about adding cmath.cbrt: it's not obvious how to extend the real cube root function to a complex cube root, so it might make sense to wait for actual use-cases before doing so.
The issue is that the most natural way to define a complex cube root would use a branch cut along the negative real axis (the same branch cut that cmath.sqrt and cmath.log use). But then the principal branch would *not* be an extension of math.cbrt: it would return non-real values on the negative real axis. (The *real* cube roots of negative numbers would fall on the two non-principal branches.)
When I needed a function to find cube root, I couldn't find one in the math module. Also found the cbrt() function in C. I didn't account for the complex numbers. I didn't wanted to make it a complex function unnecessarily. So I used the cbrt() function directly and it was working well for my test cases. And it is supported by visual studio.
I am surprised that this was not proposed before. Perhaps because it is so easy to write x**(1/3), and if you want a real root of negative argument, it is -(-x)**(1/3). It can be slightly less accurate that the result of C library function cbrt(), but good enough for any practical applications.
Ajith, was you aware of x**(1/3)?
AjithRamachandran commented on Jun 9, 2021
AjithRamachandranmannequin
MannequinAuthor
More actions
Yes I was aware of x**(1/3) and used that. I just thought it would be useful if it was present in math module as it is also used in many situations like sqrt().
Perhaps because it is so easy to write x**(1/3), and if you want a real root of negative argument, it is -(-x)**(1/3).
I consider x**(1/3) to be a trap and a bug magnet: many people won't realise that the correct spelling for their situation is actually def f(x): return -((-x)**(1/3)) if x < 0 else x**(1/3) and the failure mode of x**(1/3) for negative x seems suboptimal, in that it happily returns a complex number rather than raising a ValueError with a clear message indicating what was wrong. I've seen a good number of Stack Overflow questions from users confused about this exact thing.
And not only is that correct spelling unwieldy, but it still doesn't do the right thing for -0.0, and if you care about getting that corner case right then the right spelling becomes even more unwieldy.
Of course, even with math.cbrt in the standard library people will still fall into the x**(1/3) trap, but at least we then have a decent replacement to point them to.
If we *really* wanted to bikeshed on the name, back in 1991 Kahan wrote:
Perhaps the last problem is the hardest: choosing the program's name. Ideally it should need no explanation, but a limitation upon its length may preclude that. Although "CBRT" has seen use, I prefer "QBRT" in order that the prefix "C" may be reserved for use with complex-valued functions.
Activity
serhiy-storchaka commentedon Jun 9, 2021
See also bpo-27353.
mdickinson commentedon Jun 9, 2021
+1. This is part of C99, so if it's also supported by Visual Studio, then this seems like a no-brainer. If it's _not_ also supported by Visual Studio, or if there are implementations that have serious numerical problems (as was the case with fma) we'll need to write our own fallback implementation, which is less simple.
In principle it should be relatively easy for a math library to provide a correctly-rounded cbrt.
mdickinson commentedon Jun 9, 2021
BTW, to forestall questions about adding cmath.cbrt: it's not obvious how to extend the real cube root function to a complex cube root, so it might make sense to wait for actual use-cases before doing so.
The issue is that the most natural way to define a complex cube root would use a branch cut along the negative real axis (the same branch cut that cmath.sqrt and cmath.log use). But then the principal branch would *not* be an extension of math.cbrt: it would return non-real values on the negative real axis. (The *real* cube roots of negative numbers would fall on the two non-principal branches.)
See for example https://math.stackexchange.com/questions/71775/extending-the-cube-root-function-to-mathbbc
AjithRamachandran commentedon Jun 9, 2021
When I needed a function to find cube root, I couldn't find one in the math module. Also found the
cbrt()function in C. I didn't account for the complex numbers. I didn't wanted to make it a complex function unnecessarily. So I used thecbrt()function directly and it was working well for my test cases. And it is supported by visual studio.serhiy-storchaka commentedon Jun 9, 2021
I am surprised that this was not proposed before. Perhaps because it is so easy to write x**(1/3), and if you want a real root of negative argument, it is -(-x)**(1/3). It can be slightly less accurate that the result of C library function cbrt(), but good enough for any practical applications.
Ajith, was you aware of x**(1/3)?
AjithRamachandran commentedon Jun 9, 2021
Yes I was aware of x**(1/3) and used that. I just thought it would be useful if it was present in math module as it is also used in many situations like
sqrt().mdickinson commentedon Jun 9, 2021
I consider
x**(1/3)to be a trap and a bug magnet: many people won't realise that the correct spelling for their situation is actuallydef f(x): return -((-x)**(1/3)) if x < 0 else x**(1/3)and the failure mode ofx**(1/3)for negativexseems suboptimal, in that it happily returns a complex number rather than raising aValueErrorwith a clear message indicating what was wrong. I've seen a good number of Stack Overflow questions from users confused about this exact thing.And not only is that correct spelling unwieldy, but it still doesn't do the right thing for
-0.0, and if you care about getting that corner case right then the right spelling becomes even more unwieldy.Of course, even with
math.cbrtin the standard library people will still fall into thex**(1/3)trap, but at least we then have a decent replacement to point them to.mdickinson commentedon Jun 9, 2021
There's also a decent chance that a libm implementation of cbrt will be correctly rounded, while
x**(1/3)is highly unlikely to be so.vstinner commentedon Jun 9, 2021
I didn't know the "cbrt" function name. It seems like it exists in the libc, but also in numpy. So it's a good idea to reuse this name ;-)
numpy.cbrt(): Return the cube-root of an array, element-wise.
https://numpy.org/doc/stable/reference/generated/numpy.cbrt.html
mdickinson commentedon Jun 9, 2021
@victor: Yep, the name is pretty standard. Not just C, but JavaScript, Java, R, and likely a lot of other languages that I haven't checked.
mdickinson commentedon Jun 9, 2021
If we *really* wanted to bikeshed on the name, back in 1991 Kahan wrote:
Source: https://csclub.uwaterloo.ca/~pbarfuss/qbrt.pdf
But that was 30 years ago, and I think the "CBRT"-shaped ship has long since sailed.
mdickinson commentedon Jun 10, 2021
New changeset ac867f1 by Ajith Ramachandran in branch 'main':
bpo-44357:Add
math.cbrt()function: Cube Root (GH-26622)ac867f1
mdickinson commentedon Jun 10, 2021
All done; closing. Thank you for the contribution!