8000 Merge pull request #8190 from charris/add-fpower-ufunc · numpy/numpy@62046aa · GitHub
[go: up one dir, main page]

Skip to content

Commit 62046aa

Browse files
authored
Merge pull request #8190 from charris/add-fpower-ufunc
ENH: Add a float_power function with at least float64 precision.
2 parents 9589a5a + af32cce commit 62046aa

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

doc/release/1.12.0-notes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,15 @@ values. There are two different propagation modes. The default causes masked
261261
values to contaminate the result with masks, but the other mode only outputs
262262
masks if there is no alternative.
263263

264+
New ``float_power`` ufunc
265+
~~~~~~~~~~~~~~~~~~~~~~~~~
266+
The new ``float_power`` ufunc is like the ``power`` function except all
267+
computation is done in a minimum precision of float64. There was a long
268+
discussion on the numpy mailing list of how to treat integers to negative
269+
integer powers and a popular proposal was that the ``__pow__`` operator should
270+
always return results of at least float64 precision. The ``float_power``
271+
function implements that option. Note that it does not support object arrays.
272+
264273

265274
Improvements
266275
============

numpy/core/code_generators/generate_umath.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,12 @@ def english_upper(s):
370370
TD(inexact, f='pow', astype={'e':'f'}),
371371
TD(O, f='npy_ObjectPower'),
372372
),
373+
'float_power':
374+
Ufunc(2, 1, None,
375+
docstrings.get('numpy.core.umath.float_power'),
376+
None,
377+
TD('dgDG', f='pow'),
378+
),
373379
'absolute':
374380
Ufunc(1, 1, None,
375381
docstrings.get('numpy.core.umath.absolute'),

numpy/core/code_generators/ufunc_docstrings.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2543,7 +2543,8 @@ def add_newdoc(place, name, doc):
25432543
First array elements raised to powers from second array, element-wise.
25442544
25452545
Raise each base in `x1` to the positionally-corresponding power in
2546-
`x2`. `x1` and `x2` must be broadcastable to the same shape.
2546+
`x2`. `x1` and `x2` must be broadcastable to the same shape. Note that an
2547+
integer type raised to a negative integer power will raise a ValueError.
25472548
25482549
Parameters
25492550
----------
@@ -2557,6 +2558,10 @@ def add_newdoc(place, name, doc):
25572558
y : ndarray
25582559
The bases in `x1` raised to the exponents in `x2`.
25592560
2561+
See Also
2562+
--------
2563+
float_power : power function that promotes integers to float
2564+
25602565
Examples
25612566
--------
25622567
Cube each element in a list.
@@ -2585,6 +2590,63 @@ def add_newdoc(place, name, doc):
25852590
25862591
""")
25872592

2593+
add_newdoc('numpy.core.umath', 'float_power',
2594+
"""
2595+
First array elements raised to powers from second array, element-wise.
2596+
2597+
Raise each base in `x1` to the positionally-corresponding power in `x2`.
2598+
`x1` and `x2` must be broadcastable to the same shape. This differs from
2599+
the power function in that integers, float16, and float32 are promoted to
2600+
floats with a minimum precision of float64 so that the result is always
2601+
inexact. The intent is that the function will return a usable result for
2602+
negative powers and seldom overflow for positive powers.
2603+
2604+
.. versionadded:: 1.12.0
2605+
2606+
Parameters
2607+
----------
2608+
x1 : array_like
2609+
The bases.
2610+
x2 : array_like
2611+
The exponents.
2612+
2613+
Returns
2614+
-------
2615+
y : ndarray
2616+
The bases in `x1` raised to the exponents in `x2`.
2617+
2618+
See Also
2619+
--------
2620+
power : power function that preserves type
2621+
2622+
Examples
2623+
--------
2624+
Cube each element in a list.
2625+
2626+
>>> x1 = range(6)
2627+
>>> x1
2628+
[0, 1, 2, 3, 4, 5]
2629+
>>> np.float_power(x1, 3)
2630+
array([ 0., 1., 8., 27., 64., 125.])
2631+
2632+
Raise the bases to different exponents.
2633+
2634+
>>> x2 = [1.0, 2.0, 3.0, 3.0, 2.0, 1.0]
2635+
>>> np.float_power(x1, x2)
2636+
array([ 0., 1., 8., 27., 16., 5.])
2637+
2638+
The effect of broadcasting.
2639+
2640+
>>> x2 = np.array([[1, 2, 3, 3, 2, 1], [1, 2, 3, 3, 2, 1]])
2641+
>>> x2
2642+
array([[1, 2, 3, 3, 2, 1],
2643+
[1, 2, 3, 3, 2, 1]])
2644+
>>> np.float_power(x1, x2)
2645+
array([[ 0., 1., 8., 27., 16., 5.],
2646+
[ 0., 1., 8., 27., 16., 5.]])
2647+
2648+
""")
2649+
25882650
add_newdoc('numpy.core.umath', 'radians',
25892651
"""
25902652
Convert angles from degrees to radians.

numpy/core/tests/test_umath.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,17 @@ def test_integer_to_negative_power(self):
465465
assert_raises(ValueError, np.power, one, minusone)
466466

467467

468+
class TestFloat_power(TestCase):
469+
def test_type_conversion(self):
470+
arg_type = '?bhilBHILefdgFDG'
471+
res_type = 'ddddddddddddgDDG'
472+
for dtin, dtout in zip(arg_type, res_type):
473+
msg = "dtin: %s, dtout: %s" % (dtin, dtout)
474+
arg = np.ones(1, dtype=dtin)
475+
res = np.float_power(arg, arg)
476+
assert_(res.dtype.name == np.dtype(dtout).name, msg)
477+
478+
468479
class TestLog2(TestCase):
469480
def test_log2_values(self):
470481
x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]

0 commit comments

Comments
 (0)
0