Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Vector_double_dense: Factor through new class Vector_numpy_dense
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Koeppe committed Oct 12, 2021
1 parent cde4e54 commit 2ffb118
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 267 deletions.
14 changes: 3 additions & 11 deletions src/sage/modules/vector_double_dense.pxd
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
from .free_module_element cimport FreeModuleElement
cimport numpy
from .vector_numpy_dense cimport Vector_numpy_dense

cdef class Vector_double_dense(FreeModuleElement):
cdef object _numpy_dtype
cdef int _numpy_dtypeint
cdef object _python_dtype
cdef object _sage_dtype
cdef object _sage_vector_dtype
cdef numpy.ndarray _vector_numpy
cdef Vector_double_dense _new(self, numpy.ndarray vector_numpy)
cdef _replace_self_with_numpy(self, numpy.ndarray numpy_array)
cdef class Vector_double_dense(Vector_numpy_dense):
pass
258 changes: 2 additions & 256 deletions src/sage/modules/vector_double_dense.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ AUTHORS:

cimport numpy
import numpy
from .free_module_element import FreeModuleElement

from sage.structure.element cimport Element, ModuleElement, RingElement, Vector
from sage.structure.element cimport Element, Vector

from sage.rings.real_double import RDF
from sage.rings.complex_double import CDF
Expand All @@ -61,7 +60,7 @@ from sage.rings.complex_double import CDF
numpy.import_array()


cdef class Vector_double_dense(FreeModuleElement):
cdef class Vector_double_dense(Vector_numpy_dense):
"""
Base class for vectors over the Real Double Field and the Complex
Double Field. These are supposed to be fast vector operations
Expand All @@ -79,204 +78,6 @@ cdef class Vector_double_dense(FreeModuleElement):
sage: v*v
30.0
"""
def __cinit__(self, parent, entries, coerce=True, copy=True):
"""
Set up a new vector
EXAMPLES::
sage: v = vector(RDF, range(3))
sage: v.__new__(v.__class__, v.parent(), [1,1,1]) # random output
(3.00713073107e-261, 3.06320700422e-322, 2.86558074588e-322)
sage: v = vector(CDF, range(3))
sage: v.__new__(v.__class__, v.parent(), [1,1,1]) # random output
(-2.26770549592e-39, 5.1698223615e-252*I, -5.9147262602e-62 + 4.63145528786e-258*I)
"""
self._is_immutable = 0
self._degree = parent.degree()
self._parent = parent

cdef Vector_double_dense _new(self, numpy.ndarray vector_numpy):
"""
Return a new vector with same parent as self.
"""
cdef Vector_double_dense v
v = self.__class__.__new__(self.__class__,self._parent,None,None,None)
v._is_immutable = 0
v._parent = self._parent
v._degree = self._parent.degree()

v._vector_numpy = vector_numpy
return v

def __create_vector__(self):
"""
Create a new uninitialized numpy array to hold the data for the class.
This function assumes that self._numpy_dtypeint and
self._nrows and self._ncols have already been initialized.
EXAMPLES:
In this example, we throw away the current array and make a
new uninitialized array representing the data for the class. ::
sage: a=vector(RDF, range(9))
sage: a.__create_vector__()
"""
cdef numpy.npy_intp dims[1]
dims[0] = self._degree
self._vector_numpy = numpy.PyArray_SimpleNew(1, dims, self._numpy_dtypeint)
return

cdef bint is_dense_c(self):
"""
Return True (i.e., 1) if self is dense.
"""
return 1

cdef bint is_sparse_c(self):
"""
Return True (i.e., 1) if self is sparse.
"""
return 0


def __copy__(self, copy=True):
"""
Return a copy of the vector
EXAMPLES::
sage: a = vector(RDF, range(9))
sage: a == copy(a)
True
"""
if self._degree == 0:
return self
from copy import copy
return self._new(copy(self._vector_numpy))

def __init__(self, parent, entries, coerce = True, copy = True):
"""
Fill the vector with entries.
The numpy array must have already been allocated.
EXAMPLES::
sage: vector(RDF, range(9))
(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0)
sage: vector(CDF, 5)
(0.0, 0.0, 0.0, 0.0, 0.0)
TESTS::
sage: vector(CDF, 0)
()
sage: vector(RDF, 0)
()
sage: vector(CDF, 4)
(0.0, 0.0, 0.0, 0.0)
sage: vector(RDF, 4)
(0.0, 0.0, 0.0, 0.0)
sage: vector(CDF, [CDF(1+I)*j for j in range(4)])
(0.0, 1.0 + 1.0*I, 2.0 + 2.0*I, 3.0 + 3.0*I)
sage: vector(RDF, 4, range(4))
(0.0, 1.0, 2.0, 3.0)
sage: V = RDF^2
sage: V.element_class(V, 5)
Traceback (most recent call last):
...
TypeError: entries must be a list or 0
sage: V.element_class(V, 0)
(0.0, 0.0)
"""
cdef Py_ssize_t i,j
if isinstance(entries,(tuple, list)):
if len(entries)!=self._degree:
raise TypeError("entries has wrong length")

if coerce:
for i from 0<=i<self._degree:
self.set_unsafe(i,self._python_dtype(entries[i]))
else:
for i from 0<=i<self._degree:
self.set_unsafe(i,entries[i])

elif isinstance(entries, numpy.ndarray):
self._replace_self_with_numpy(entries)
else:
numpy.PyArray_FILLWBYTE(self._vector_numpy, 0)
if entries is None:
return
else:
try:
z = self._python_dtype(entries)
except TypeError:
raise TypeError("unable to convert {!r} to {}".format(entries, self._python_dtype))
if z != 0:
raise TypeError("entries must be a list or 0")
else:
# Set all entries to z=0.
for i from 0<=i<self._degree:
self.set_unsafe(i,z)

def __len__(self):
"""
Return the length of the vector.
EXAMPLES::
sage: v = vector(RDF, 5); v
(0.0, 0.0, 0.0, 0.0, 0.0)
sage: len(v)
5
"""
return self._degree

cdef int set_unsafe(self, Py_ssize_t i, value) except -1:
"""
EXAMPLES::
sage: v = vector(CDF, [1,CDF(3,2), -1]); v
(1.0, 3.0 + 2.0*I, -1.0)
sage: v[1] = 2
sage: v[-1] = I
sage: v
(1.0, 2.0, 1.0*I)
sage: v[1:3] = [1, 1]; v
(1.0, 1.0, 1.0)
"""
# We assume that Py_ssize_t is the same as npy_intp

# We call the self._python_dtype function on the value since
# numpy does not know how to deal with complex numbers other
# than the built-in complex number type.
cdef int status
status = numpy.PyArray_SETITEM(self._vector_numpy,
numpy.PyArray_GETPTR1(self._vector_numpy, i),
self._python_dtype(value))
#TODO: Throw an error if status == -1

cdef get_unsafe(self, Py_ssize_t i):
"""
EXAMPLES::
sage: v = vector(CDF, [1,CDF(3,2), -1]); v
(1.0, 3.0 + 2.0*I, -1.0)
sage: v[1]
3.0 + 2.0*I
sage: v[-1]
-1.0
sage: v[1:3]
(3.0 + 2.0*I, -1.0)
"""
# We assume that Py_ssize_t is the same as npy_intp
return self._sage_dtype(numpy.PyArray_GETITEM(self._vector_numpy,
numpy.PyArray_GETPTR1(self._vector_numpy, i)))


cpdef _add_(self, right):
"""
Expand Down Expand Up @@ -487,19 +288,6 @@ cdef class Vector_double_dense(FreeModuleElement):
else:
return Vector_complex_double_dense(V, ifft(self._vector_numpy))


cdef _replace_self_with_numpy(self, numpy.ndarray numpy_array):
"""
Replace the underlying numpy array with numpy_array.
"""
if self._degree == 0:
return
if numpy_array.ndim != 1 or len(self._vector_numpy) != numpy_array.shape[0]:
raise ValueError("vector lengths are not the same")

self._vector_numpy = numpy_array.astype(self._numpy_dtype)


def complex_vector(self):
"""
Return the associated complex vector, i.e., this vector but with
Expand Down Expand Up @@ -804,45 +592,3 @@ cdef class Vector_double_dense(FreeModuleElement):
36.0 + 45.0*I
"""
return self._sage_dtype(self._vector_numpy.sum())

# Put this method last, otherwise it overrides the "numpy" cimport
def numpy(self, dtype=None):
"""
Return numpy array corresponding to this vector.
INPUT:
- ``dtype`` -- if specified, the `numpy dtype <http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html>`_
of the returned array.
EXAMPLES::
sage: v = vector(CDF,4,range(4))
sage: v.numpy()
array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j])
sage: v = vector(CDF,0)
sage: v.numpy()
array([], dtype=complex128)
sage: v = vector(RDF,4,range(4))
sage: v.numpy()
array([0., 1., 2., 3.])
sage: v = vector(RDF,0)
sage: v.numpy()
array([], dtype=float64)
A numpy dtype may be requested manually::
sage: import numpy
sage: v = vector(CDF, 3, range(3))
sage: v.numpy()
array([0.+0.j, 1.+0.j, 2.+0.j])
sage: v.numpy(dtype=numpy.float64)
array([0., 1., 2.])
sage: v.numpy(dtype=numpy.float32)
array([0., 1., 2.], dtype=float32)
"""
if dtype is None or dtype is self._vector_numpy.dtype:
from copy import copy
return copy(self._vector_numpy)
else:
return super(Vector_double_dense, self).numpy(dtype)
12 changes: 12 additions & 0 deletions src/sage/modules/vector_numpy_dense.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from .free_module_element cimport FreeModuleElement
cimport numpy

cdef class Vector_numpy_dense(FreeModuleElement):
cdef object _numpy_dtype
cdef int _numpy_dtypeint
cdef object _python_dtype
cdef object _sage_dtype
cdef object _sage_vector_dtype
cdef numpy.ndarray _vector_numpy
cdef Vector_numpy_dense _new(self, numpy.ndarray vector_numpy)
cdef _replace_self_with_numpy(self, numpy.ndarray numpy_array)
Loading

0 comments on commit 2ffb118

Please sign in to comment.