diff --git a/sklearn/utils/fixes.py b/sklearn/utils/fixes.py index e0f10bcae8e4e..3f9d2317538de 100644 --- a/sklearn/utils/fixes.py +++ b/sklearn/utils/fixes.py @@ -103,7 +103,7 @@ def divide(x1, x2, out=None, dtype=None): except TypeError: # Compat where astype accepted no copy argument def astype(array, dtype, copy=True): - if array.dtype == dtype: + if not copy and array.dtype == dtype: return array return array.astype(dtype) else: diff --git a/sklearn/utils/tests/test_fixes.py b/sklearn/utils/tests/test_fixes.py index 3580aa6acbff7..4494f87b5feb4 100644 --- a/sklearn/utils/tests/test_fixes.py +++ b/sklearn/utils/tests/test_fixes.py @@ -6,10 +6,13 @@ import numpy as np from nose.tools import assert_equal +from nose.tools import assert_false +from nose.tools import assert_true from numpy.testing import (assert_almost_equal, assert_array_almost_equal) from sklearn.utils.fixes import divide, expit +from sklearn.utils.fixes import astype def test_expit(): @@ -28,3 +31,25 @@ def test_expit(): def test_divide(): assert_equal(divide(.6, 1), .600000000000) + + +def test_astype_copy_memory(): + a_int32 = np.ones(3, np.int32) + + # Check that dtype conversion works + b_float32 = astype(a_int32, dtype=np.float32, copy=False) + assert_equal(b_float32.dtype, np.float32) + + # Changing dtype forces a copy even if copy=False + assert_false(np.may_share_memory(b_float32, a_int32)) + + # Check that copy can be skipped if requested dtype match + c_int32 = astype(a_int32, dtype=np.int32, copy=False) + assert_true(c_int32 is a_int32) + + # Check that copy can be forced, and is the case by default: + d_int32 = astype(a_int32, dtype=np.int32, copy=True) + assert_false(np.may_share_memory(d_int32, a_int32)) + + e_int32 = astype(a_int32, dtype=np.int32) + assert_false(np.may_share_memory(e_int32, a_int32))