[pypy-commit] pypy numpy-complex: Initial start. It leaks memory like a seive. We need lltype.malloc(flavor="stack") I think.

alex_gaynor noreply at buildbot.pypy.org
Fri Oct 14 21:29:20 CEST 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy-complex
Changeset: r48065:a973209a2d26
Date: 2011-10-14 15:28 -0400
http://bitbucket.org/pypy/pypy/changeset/a973209a2d26/

Log:	Initial start. It leaks memory like a seive. We need
	lltype.malloc(flavor="stack") I think.

diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -18,6 +18,7 @@
 SIGNEDLTR = "i"
 BOOLLTR = "b"
 FLOATINGLTR = "f"
+COMPLEXLTR = "c"
 
 class W_Dtype(Wrappable):
     def __init__(self, space):
@@ -118,9 +119,19 @@
     W_LowLevelDtype.name = name
     W_LowLevelDtype.aliases = aliases
     W_LowLevelDtype.applevel_types = applevel_types
-    W_LowLevelDtype.num_bytes = rffi.sizeof(T)
-    if expected_size is not None:
-        assert W_LowLevelDtype.num_bytes == expected_size
+
+    if hasattr(T, "_arrayfld"):
+        # Hack for structs (read: complex), rffi.sizeof(Struct) returns a
+        # symbolic, which can't be compared
+        assert T._arrayfld is None
+        primitive_size = sum(rffi.sizeof(VT) for VT in T._flds.itervalues())
+    else:
+        primitive_size = rffi.sizeof(T)
+    if expected_size is None:
+        expected_size = primitive_size
+    assert expected_size == primitive_size
+    W_LowLevelDtype.num_bytes = expected_size
+
     return W_LowLevelDtype
 
 
@@ -465,12 +476,55 @@
 class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype):
     pass
 
+ComplexDouble = lltype.Struct("Complex Double",
+    ("real", lltype.Float),
+    ("imag", lltype.Float),
+)
+W_Complex128Dtype = create_low_level_dtype(
+    num = 15, kind = COMPLEXLTR, name = "complex128",
+    aliases = [],
+    applevel_types = ["complex"],
+    T = ComplexDouble,
+    valtype = ComplexDouble,
+    expected_size = 16,
+)
+class W_Complex128Dtype(W_Complex128Dtype):
+    def _create_complex_struct(self, real, imag):
+        # Really we want to stack alloc it, doesn't seem possible though.
+        # Unforutnately a raw alloc means we'll leak memory (no gc) and it
+        # can't be a GcStruct because the array storage isn't a GcArray.
+        # So basically we need stack allocs.
+        c = lltype.malloc(ComplexDouble, flavor="raw")
+        c.real = real
+        c.imag = imag
+        return c
+
+    @specialize.argtype(1)
+    def adapt_val(self, val):
+        if hasattr(val, "_T"):
+            assert val._T is ComplexDouble
+        else:
+            val = self._create_complex_struct(rffi.cast(lltype.Float, val), 0.0)
+        return self.box(val)
+
+    def unwrap(self, space, w_item):
+        real, imag = space.unpackcomplex(w_item)
+        return self.adapt_val(self._create_complex_struct(real, imag))
+
+    def setitem(self, storage, i, item):
+        val = self.unbox(item)
+        # You can't set a full struct, gotta do it one field at a time.
+        self.unerase(storage)[i].real = val.real
+        self.unerase(storage)[i].imag = val.imag
+
+
 ALL_DTYPES = [
     W_BoolDtype,
     W_Int8Dtype, W_UInt8Dtype, W_Int16Dtype, W_UInt16Dtype,
     W_Int32Dtype, W_UInt32Dtype, W_LongDtype, W_ULongDtype,
     W_Int64Dtype, W_UInt64Dtype,
     W_Float32Dtype, W_Float64Dtype,
+    W_Complex128Dtype,
 ]
 
 dtypes_by_alias = unrolling_iterable([
@@ -496,6 +550,7 @@
     __str__ = interp2app(W_Dtype.descr_str),
 
     num = interp_attrproperty("num", cls=W_Dtype),
+    name = interp_attrproperty("name", cls=W_Dtype),
     kind = interp_attrproperty("kind", cls=W_Dtype),
     itemsize = interp_attrproperty("num_bytes", cls=W_Dtype),
     shape = GetSetProperty(W_Dtype.descr_get_shape),
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -38,8 +38,6 @@
             w_dtype = None
             for w_item in l:
                 w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_item, w_dtype)
-                if w_dtype is space.fromcache(interp_dtype.W_Float64Dtype):
-                    break
             if w_dtype is None:
                 w_dtype = space.w_None
 
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -241,6 +241,7 @@
     bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
     long_dtype = space.fromcache(interp_dtype.W_LongDtype)
     int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
+    complex128_dtype = space.fromcache(interp_dtype.W_Complex128Dtype)
 
     if space.is_w(w_type, space.w_bool):
         if current_guess is None or current_guess is bool_dtype:
@@ -256,6 +257,8 @@
             current_guess is long_dtype or current_guess is int64_dtype):
             return int64_dtype
         return current_guess
+    elif space.is_w(w_type, space.w_complex):
+        return complex128_dtype
     return space.fromcache(interp_dtype.W_Float64Dtype)
 
 
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -161,3 +161,12 @@
 
         # You can't subclass dtype
         raises(TypeError, type, "Foo", (dtype,), {})
+
+    def test_complex_dtype(self):
+        from numpy import dtype
+
+        d = dtype(complex)
+        assert d.kind == "c"
+        assert d.name == "complex128"
+        assert d.num == 15
+        assert d.itemsize == 16
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -558,6 +558,8 @@
         assert array([1.2, True]).dtype is dtype(float)
         assert array([1.2, 5]).dtype is dtype(float)
         assert array([]).dtype is dtype(float)
+        assert array([1 + 2j]).dtype is dtype(complex)
+        assert array([1.0, 1 + 2j]).dtype is dtype(complex)
 
     def test_comparison(self):
         import operator


More information about the pypy-commit mailing list