@@ -25,6 +25,9 @@ import sage.modules.free_module
25
25
from sage.structure.coerce cimport coercion_model
26
26
27
27
28
+ _MISSING = object ()
29
+
30
+
28
31
cdef class Matrix(Matrix0):
29
32
# ##################################################
30
33
# Coercion to Various Systems
@@ -670,7 +673,7 @@ cdef class Matrix(Matrix0):
670
673
entries = [[sib(v, 2 ) for v in row] for row in self .rows()]
671
674
return sib.name(' matrix' )(self .base_ring(), entries)
672
675
673
- def numpy (self , dtype = None , copy = True ):
676
+ def numpy (self , dtype = None , copy = _MISSING ):
674
677
"""
675
678
Return the Numpy matrix associated to this matrix.
676
679
@@ -680,14 +683,6 @@ cdef class Matrix(Matrix0):
680
683
then the type will be determined as the minimum type required
681
684
to hold the objects in the sequence.
682
685
683
- - ``copy`` -- if `self` is already an `ndarray`, then this flag
684
- determines whether the data is copied (the default), or whether
685
- the internal array is returned. Note that this is incompatible
686
- with the behavior of ``copy`` argument to ``__array__`` method
687
- in numpy 2.0, see `Adapting to changes in the copy keyword
688
- <https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keyword>`_.
689
- Currently SageMath is using numpy 1.26.
690
-
691
686
EXAMPLES::
692
687
693
688
sage: # needs numpy
@@ -713,7 +708,7 @@ cdef class Matrix(Matrix0):
713
708
typecodes::
714
709
715
710
sage: import numpy # needs numpy
716
- sage: numpy.typecodes.items() # needs numpy
711
+ sage: numpy.typecodes.items() # needs numpy # random
717
712
[('All', '?bhilqpBHILQPefdgFDGSUVOMm'), ('AllFloat', 'efdgFDG'),
718
713
...
719
714
@@ -738,40 +733,69 @@ cdef class Matrix(Matrix0):
738
733
sage: b.shape
739
734
(3, 4)
740
735
741
- TESTS:
742
-
743
- This ensures the docstring above is correct. It needs to be changed
744
- when numpy version in SageMath is updated to 2.0.0::
736
+ TESTS::
745
737
746
738
sage: # needs numpy
747
- sage: import numpy as np
748
- sage: np.__version__
749
- '1.26.4'
739
+ sage: matrix(3, range(12)).numpy(copy=False)
740
+ doctest:warning...
741
+ DeprecationWarning: passing copy argument to numpy() is deprecated
742
+ See https://github.com/sagemath/sage/issues/39152 for details.
743
+ array([[ 0, 1, 2, 3],
744
+ [ 4, 5, 6, 7],
745
+ [ 8, 9, 10, 11]])
750
746
"""
747
+ if copy is not _MISSING:
748
+ from sage.misc.superseded import deprecation
749
+ deprecation(39152 , " passing copy argument to numpy() is deprecated" )
751
750
import numpy
752
751
return numpy.asarray(self .list(), dtype = dtype).reshape(self .nrows(), self .ncols())
753
752
754
- def __array__ (self , dtype = None ):
753
+ def __array__ (self , dtype = None , copy = None ):
755
754
"""
756
755
Define the magic ``__array__`` function so that ``numpy.array(m)`` can convert
757
756
a matrix ``m`` to a numpy array. See
758
757
`Interoperability with NumPy <https://numpy.org/doc/1.26/user/basics.interoperability.html>`_.
759
758
760
759
Note that subclasses should override :meth:`numpy`, but usually not this method.
761
760
762
- SageMath is using Numpy 1.26, so there is no ``copy`` argument.
761
+ INPUT:
763
762
764
- TESTS:
763
+ - ``dtype`` -- the desired data-type for the array. If not given,
764
+ then the type will be determined automatically.
765
765
766
- This ensures the docstring above is correct. It needs to be changed
767
- when numpy version in SageMath is updated to 2.0.0::
766
+ - ``copy`` -- required for numpy 2.0 compatibility.
767
+ See <https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keyword>`_.
768
+ Note that ``copy=False`` is not supported.
769
+
770
+ TESTS::
768
771
769
772
sage: # needs numpy
770
773
sage: import numpy as np
771
- sage: np.__version__
772
- '1.26.4'
773
- """
774
- return self .numpy(dtype, copy = False )
774
+ sage: a = matrix(3, range(12))
775
+ sage: if np.lib.NumpyVersion(np.__version__) >= '2.0.0':
776
+ ....: try:
777
+ ....: np.array(a, copy=False) # in numpy 2.0, this raises an error
778
+ ....: except ValueError:
779
+ ....: pass
780
+ ....: else:
781
+ ....: assert False
782
+ ....: else:
783
+ ....: b = np.array(a, copy=False) # in numpy 1.26, this means "avoid copy if possible"
784
+ ....: # https://numpy.org/doc/1.26/reference/generated/numpy.array.html#numpy.array
785
+ ....: # but no-copy is not supported so it will copy anyway
786
+ ....: a[0,0] = 1
787
+ ....: assert b[0,0] == 0
788
+ ....: b = np.asarray(a)
789
+ ....: a[0,0] = 2
790
+ ....: assert b[0,0] == 1
791
+ """
792
+ import numpy as np
793
+ if np.lib.NumpyVersion(np.__version__) >= ' 2.0.0' :
794
+ if copy is False :
795
+ raise ValueError (" Sage matrix cannot be converted to numpy array without copying" )
796
+ else :
797
+ assert copy is None # numpy versions before 2.0 should not pass copy argument
798
+ return self .numpy(dtype)
775
799
776
800
# ##################################################
777
801
# Construction functions
0 commit comments