From c5cc362f179914e787cb245a40af964974befce8 Mon Sep 17 00:00:00 2001 From: Mark Wiebe Date: Sun, 20 Apr 2014 13:33:40 -0700 Subject: [PATCH 1/6] Update to reflect types changes in libdynd --- buildscripts/jenkins-build | 4 ++-- dynd/_lowlevel/type_id.py | 8 ++++---- dynd/ndt/__init__.py | 2 +- dynd/tests/test_array_assign.py | 8 ++++---- dynd/tests/test_array_construct.py | 24 +++++++++++------------ dynd/tests/test_computed_fields.py | 6 +++--- dynd/tests/test_ctypes_interop.py | 8 ++++---- dynd/tests/test_dtype_datashape.py | 16 +++++++++------ dynd/tests/test_elwise_map.py | 6 +++--- dynd/tests/test_lowlevel.py | 8 +++++--- dynd/tests/test_nd_fields.py | 8 ++++---- dynd/tests/test_numpy_interop.py | 14 +++++++------- include/ndt_type.pxd | 2 +- include/type_functions.hpp | 2 +- src/array_as_numpy.cpp | 22 ++++++++++----------- src/array_as_pep3118.cpp | 12 ++++++------ src/array_assign_from_py.cpp | 10 +++++----- src/array_from_py.cpp | 4 ++-- src/array_from_py_dynamic.cpp | 2 +- src/array_from_py_typededuction.cpp | 2 +- src/array_functions.cpp | 5 ++++- src/ctypes_interop.cpp | 14 +++++++++----- src/numpy_interop.cpp | 18 ++++++++++------- src/type_functions.cpp | 30 ++++++++++++++++++++++------- 24 files changed, 134 insertions(+), 101 deletions(-) diff --git a/buildscripts/jenkins-build b/buildscripts/jenkins-build index 600133ac..9b253920 100755 --- a/buildscripts/jenkins-build +++ b/buildscripts/jenkins-build @@ -81,7 +81,7 @@ fi export EXTRA="-DDYND_BUILD_TESTS=OFF ${EXTRA}" # Create a fresh makefile with cmake, and do the build/install -cd build +pushd build cmake ${EXTRA} \ -DCMAKE_INSTALL_PREFIX=${PYENV_PREFIX} \ -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \ @@ -100,9 +100,9 @@ if [ '${PYDYND_VERSION}' == '' ]; then exit 1 fi export PYDYND_VERSION=${PYDYND_VERSION//-/_} +popd # Put the conda package by itself in the directory pkgs -cd .. rm -rf pkgs mkdir pkgs cd pkgs diff --git a/dynd/_lowlevel/type_id.py b/dynd/_lowlevel/type_id.py index 699de434..3ef4f938 100644 --- a/dynd/_lowlevel/type_id.py +++ b/dynd/_lowlevel/type_id.py @@ -8,9 +8,9 @@ 'POINTER', 'BYTES', 'FIXEDBYTES', 'CHAR', 'STRING', 'FIXEDSTRING', 'CATEGORICAL', 'DATE', 'TIME', 'DATETIME', 'BUSDATE', - 'JSON', 'STRIDED_DIM', 'FIXED_DIM', + 'JSON', 'STRIDED_DIM', 'CFIXED_DIM', 'OFFSET_DIM', 'VAR_DIM', 'STRUCT', - 'FIXEDSTRUCT', 'TUPLE', 'NDOBJECT', + 'CSTRUCT', 'TUPLE', 'NDOBJECT', 'CONVERT', 'BYTESWAP', 'VIEW', 'CUDA_HOST', 'CUDA_DEVICE', 'PROPERTY', 'EXPR', 'UNARY_EXPR', @@ -51,11 +51,11 @@ BUSDATE = 30 JSON = 31 STRIDED_DIM = 32 -FIXED_DIM = 33 +CFIXED_DIM = 33 OFFSET_DIM = 34 VAR_DIM = 35 STRUCT = 36 -FIXEDSTRUCT = 37 +CSTRUCT = 37 TUPLE = 38 NDOBJECT = 39 CONVERT = 40 diff --git a/dynd/ndt/__init__.py b/dynd/ndt/__init__.py index 61322c66..9173c8e7 100644 --- a/dynd/ndt/__init__.py +++ b/dynd/ndt/__init__.py @@ -5,7 +5,7 @@ make_view, \ make_unaligned, make_fixedstring, make_string, \ make_pointer, make_struct, make_cstruct, \ - make_strided_dim, make_fixed_dim, make_var_dim, \ + make_strided_dim, make_cfixed_dim, make_var_dim, \ make_categorical, replace_dtype, extract_dtype, \ factor_categorical, make_bytes, make_property, \ make_reversed_property, cuda_support diff --git a/dynd/tests/test_array_assign.py b/dynd/tests/test_array_assign.py index 3c37ef94..1b53f977 100644 --- a/dynd/tests/test_array_assign.py +++ b/dynd/tests/test_array_assign.py @@ -33,7 +33,7 @@ def test_nested_struct(self): self.assertEqual(nd.as_py(a.z), [3j]) def test_single_struct_array(self): - a = nd.empty('3 * {x:int32, y:int32}') + a = nd.empty('3 * c{x:int32, y:int32}') a[...] = [(0,0), (3,5), (12,10)] self.assertEqual(nd.as_py(a.x), [0, 3, 12]) self.assertEqual(nd.as_py(a.y), [0, 5, 10]) @@ -42,7 +42,7 @@ def test_single_struct_array(self): self.assertEqual(nd.as_py(a.x), [1, 4, 14]) self.assertEqual(nd.as_py(a.y), [2, 7, 190]) - a = nd.empty('2 * var * {count:int32, size:string[1,"A"]}') + a = nd.empty('2 * var * c{count:int32, size:string[1,"A"]}') a[...] = [[(3, 'X')], [(10, 'L'), (12, 'M')]] self.assertEqual(nd.as_py(a.count), [[3], [10, 12]]) self.assertEqual(nd.as_py(a.size), [['X'], ['L', 'M']]) @@ -61,7 +61,7 @@ def test_single_struct_array(self): self.assertEqual(nd.as_py(a.size), [['A'], ['B', 'B']]) def test_nested_struct_array(self): - a = nd.empty('3 * {x:{a:int16, b:int16}, y:int32}') + a = nd.empty('3 * c{x:c{a:int16, b:int16}, y:int32}') a[...] = [((0,1),0), ((2,2),5), ((100,10),10)] self.assertEqual(nd.as_py(a.x.a), [0, 2, 100]) self.assertEqual(nd.as_py(a.x.b), [1, 2, 10]) @@ -74,7 +74,7 @@ def test_nested_struct_array(self): self.assertEqual(nd.as_py(a.x.b), [2, 6, 110]) self.assertEqual(nd.as_py(a.y), [5, 7, 110]) - a = nd.empty('2 * var * {count:int32, size:{name:string[1,"A"], id: int8}}') + a = nd.empty('2 * var * c{count:int32, size:c{name:string[1,"A"], id: int8}}') a[...] = [[(3, ('X', 10))], [(10, ('L', 7)), (12, ('M', 5))]] self.assertEqual(nd.as_py(a.count), [[3], [10, 12]]) self.assertEqual(nd.as_py(a.size.name), [['X'], ['L', 'M']]) diff --git a/dynd/tests/test_array_construct.py b/dynd/tests/test_array_construct.py index ac10c222..63a055b4 100644 --- a/dynd/tests/test_array_construct.py +++ b/dynd/tests/test_array_construct.py @@ -49,12 +49,12 @@ def test_empty(self): # Constructor from type with fixed dimension a = nd.empty('3 * int32') self.assertEqual(a.access_flags, 'readwrite') - self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) # Constructor from type with fixed dimension, accesskwarg a = nd.empty('3 * int32', access='rw') self.assertEqual(a.access_flags, 'readwrite') - self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) # Can't create with access as immutable self.assertRaises(ValueError, nd.empty, '3 * int32', access='immutable') @@ -91,7 +91,7 @@ def check_constructor(self, cons, value): # Constructor from type with fixed dimension a = cons('3 * int32') self.assertEqual(a.access_flags, 'immutable') - self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) self.assertEqual(nd.as_py(a), [value]*3) # Constructor from shape as single integer @@ -139,7 +139,7 @@ def check_constructor_readwrite(self, cons, value): # Constructor from type with fixed dimension a = cons('3 * int32', access='rw') self.assertEqual(a.access_flags, 'readwrite') - self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) self.assertEqual(nd.as_py(a), [value]*3) # Constructor from shape as single integer @@ -549,27 +549,27 @@ def test_nested_struct_array(self): def test_missing_field(self): self.assertRaises(RuntimeError, nd.array, - [0, 1], type='{x:int32, y:int32, z:int32}') + [0, 1], type='c{x:int32, y:int32, z:int32}') # With dtype= parameter instead of type= self.assertRaises(RuntimeError, nd.array, - [0, 1], dtype='{x:int32, y:int32, z:int32}') + [0, 1], dtype='c{x:int32, y:int32, z:int32}') self.assertRaises(RuntimeError, nd.array, - {'x':0, 'z':1}, type='{x:int32, y:int32, z:int32}') + {'x':0, 'z':1}, type='c{x:int32, y:int32, z:int32}') # With dtype= parameter instead of type= self.assertRaises(RuntimeError, nd.array, - {'x':0, 'z':1}, dtype='{x:int32, y:int32, z:int32}') + {'x':0, 'z':1}, dtype='c{x:int32, y:int32, z:int32}') def test_extra_field(self): self.assertRaises(RuntimeError, nd.array, - [0, 1, 2, 3], type='{x:int32, y:int32, z:int32}') + [0, 1, 2, 3], type='c{x:int32, y:int32, z:int32}') # With dtype= parameter instead of type= self.assertRaises(RuntimeError, nd.array, - [0, 1, 2, 3], dtype='{x:int32, y:int32, z:int32}') + [0, 1, 2, 3], dtype='c{x:int32, y:int32, z:int32}') self.assertRaises(RuntimeError, nd.array, - {'x':0,'y':1,'z':2,'w':3}, type='{x:int32, y:int32, z:int32}') + {'x':0,'y':1,'z':2,'w':3}, type='c{x:int32, y:int32, z:int32}') # With dtype= parameter instead of type= self.assertRaises(RuntimeError, nd.array, - {'x':0,'y':1,'z':2,'w':3}, dtype='{x:int32, y:int32, z:int32}') + {'x':0,'y':1,'z':2,'w':3}, dtype='c{x:int32, y:int32, z:int32}') class TestIteratorConstruct(unittest.TestCase): # Test dynd construction from iterators diff --git a/dynd/tests/test_computed_fields.py b/dynd/tests/test_computed_fields.py index 5eb9afe0..787c5dc1 100644 --- a/dynd/tests/test_computed_fields.py +++ b/dynd/tests/test_computed_fields.py @@ -14,7 +14,7 @@ def test_simple_expr(self): ('onemore', np.int16, 'xyz + 1')]) self.assertEqual(nd.type_of(b).element_type.type_id, 'unary_expr') self.assertEqual(nd.type_of(b).element_type.value_type, - ndt.type('{xyz: int32, twice: int32, onemore: int16}')) + ndt.type('c{xyz: int32, twice: int32, onemore: int16}')) self.assertEqual(nd.as_py(b.xyz), [1, 2, 3, 4, 5]) self.assertEqual(nd.as_py(b.twice), [2, 4, 6, 8, 10]) self.assertEqual(nd.as_py(b.onemore), [2, 3, 4, 5, 6]) @@ -29,7 +29,7 @@ def test_rm_fields(self): ('complex', np.complex64, 'x + 1j*y')], rm_fields=['x', 'y']) self.assertEqual(nd.type_of(b).element_type.value_type, - ndt.type('{sum: float32, difference: float32,' + + ndt.type('c{sum: float32, difference: float32,' + ' product: float32, complex: complex[float32]}')) self.assertEqual(nd.as_py(b.sum), [3, 0, 7]), self.assertEqual(nd.as_py(b.difference), [-1, -2, -3]) @@ -44,7 +44,7 @@ def test_aggregate(self): ('A', 0.5, 9), ('C', 1, 5), ('B', 2, 2)], - dtype='{cat: string, x: float32, y: float32}') + dtype='c{cat: string, x: float32, y: float32}') gb = nd.groupby(a, nd.fields(a, 'cat')).eval() b = nd.make_computed_fields(gb, 1, fields=[('sum_x', ndt.float32, 'sum(x)'), diff --git a/dynd/tests/test_ctypes_interop.py b/dynd/tests/test_ctypes_interop.py index 69595238..1322f8df 100644 --- a/dynd/tests/test_ctypes_interop.py +++ b/dynd/tests/test_ctypes_interop.py @@ -43,16 +43,16 @@ class DATA(ctypes.Structure): ndt.type(DATA)) def test_type_from_ctypes_carray(self): - self.assertEqual(ndt.make_fixed_dim(10, ndt.int32), + self.assertEqual(ndt.make_cfixed_dim(10, ndt.int32), ndt.type(ctypes.c_int32 * 10)) - self.assertEqual(ndt.make_fixed_dim((10, 3), ndt.int32), + self.assertEqual(ndt.make_cfixed_dim((10, 3), ndt.int32), ndt.type((ctypes.c_int32 * 3) * 10)) - self.assertEqual(ndt.make_fixed_dim((10, 3, 4), ndt.int32), + self.assertEqual(ndt.make_cfixed_dim((10, 3, 4), ndt.int32), ndt.type(((ctypes.c_int32 * 4) * 3) * 10)) class POINT(ctypes.Structure): _fields_ = [('x', ctypes.c_int32), ('y', ctypes.c_int32)] - self.assertEqual(ndt.make_fixed_dim(10, ndt.type(POINT)), + self.assertEqual(ndt.make_cfixed_dim(10, ndt.type(POINT)), ndt.type(POINT * 10)) if __name__ == '__main__': diff --git a/dynd/tests/test_dtype_datashape.py b/dynd/tests/test_dtype_datashape.py index d568c0b9..0fecd030 100644 --- a/dynd/tests/test_dtype_datashape.py +++ b/dynd/tests/test_dtype_datashape.py @@ -34,17 +34,21 @@ def test_aliases(self): self.assertEqual(ndt.float64, ndt.type('real')) self.assertEqual(ndt.complex_float64, ndt.type('complex')) - def test_fixed_array(self): + def test_cfixed_array(self): # Tests of datashapes that produce the DyND fixed array type - self.assertEqual(ndt.make_fixed_dim(3, ndt.int32), - ndt.type('3 * int32')) - self.assertEqual(ndt.make_fixed_dim((5, 2), ndt.float64), - ndt.type('5 * 2 * float64')) + self.assertEqual(ndt.make_cfixed_dim(3, ndt.int32), + ndt.type('cfixed[3] * int32')) + self.assertEqual(ndt.make_cfixed_dim((5, 2), ndt.float64), + ndt.type('cfixed[5] * cfixed[2] * float64')) def test_struct(self): + # Tests of cstruct datashape + dt = ndt.type('c{x: 3 * int32, y: string}') + self.assertEqual(dt.type_id, 'cstruct') + self.assertEqual(nd.as_py(dt.field_names), ['x', 'y']) # Tests of struct datashape dt = ndt.type('{x: 3 * int32, y: string}') - self.assertEqual(dt.type_id, 'cstruct') + self.assertEqual(dt.type_id, 'struct') self.assertEqual(nd.as_py(dt.field_names), ['x', 'y']) def test_var_dshape(self): diff --git a/dynd/tests/test_elwise_map.py b/dynd/tests/test_elwise_map.py index ed71e988..d1675675 100644 --- a/dynd/tests/test_elwise_map.py +++ b/dynd/tests/test_elwise_map.py @@ -24,7 +24,7 @@ def multiscale(dst, src): dst.once = src dst.twice = [2 * nd.as_py(x) for x in src] dst.thrice = [3 * nd.as_py(x) for x in src] - b = nd.elwise_map([a], multiscale, ndt.type('{once: int32, twice: int32, thrice: int32}')) + b = nd.elwise_map([a], multiscale, ndt.type('c{once: int32, twice: int32, thrice: int32}')) self.assertEqual(nd.as_py(b), [{'once':0,'twice':0,'thrice':0}, {'once':1,'twice':2,'thrice':3}, {'once':2,'twice':4,'thrice':6}]) @@ -61,11 +61,11 @@ def computed_col(dst, src): d.firstname = s.firstname d.lastname = s.lastname d.country = s.country - a = nd.parse_json('2 * {firstname: string, lastname: string, country: string}', + a = nd.parse_json('2 * c{firstname: string, lastname: string, country: string}', """[{"firstname":"Mike", "lastname":"Myers", "country":"Canada"}, {"firstname":"Seth", "lastname":"Green", "country":"USA"}]""") b = nd.elwise_map([a], computed_col, ndt.type( - '{fullname: string, firstname: string, lastname: string, country: string}')) + 'c{fullname: string, firstname: string, lastname: string, country: string}')) self.assertEqual(nd.as_py(b.fullname), ['Mike Myers', 'Seth Green']) self.assertEqual(nd.as_py(b.firstname), ['Mike', 'Seth']) self.assertEqual(nd.as_py(b.lastname), ['Myers', 'Green']) diff --git a/dynd/tests/test_lowlevel.py b/dynd/tests/test_lowlevel.py index c84b4a7d..7410fc7f 100644 --- a/dynd/tests/test_lowlevel.py +++ b/dynd/tests/test_lowlevel.py @@ -71,7 +71,9 @@ def test_type_id(self): [ndt.int32, ndt.int32], ['x', 'y'])), _lowlevel.type_id.STRUCT) self.assertEqual(self.type_id_of(ndt.type('{x : int32, y : int32}')), - _lowlevel.type_id.FIXEDSTRUCT) + _lowlevel.type_id.STRUCT) + self.assertEqual(self.type_id_of(ndt.type('c{x : int32, y : int32}')), + _lowlevel.type_id.CSTRUCT) # Convert/byteswap/view self.assertEqual(self.type_id_of(ndt.make_convert( ndt.int32, ndt.int8)), @@ -88,8 +90,8 @@ def test_type_id(self): self.assertEqual(self.type_id_of(ndt.type('cuda_host[int32]')), _lowlevel.type_id.CUDA_HOST) # Uniform arrays - self.assertEqual(self.type_id_of(ndt.type('3 * int32')), - _lowlevel.type_id.FIXED_DIM) + self.assertEqual(self.type_id_of(ndt.type('cfixed[3] * int32')), + _lowlevel.type_id.CFIXED_DIM) self.assertEqual(self.type_id_of(ndt.type('strided * int32')), _lowlevel.type_id.STRIDED_DIM) self.assertEqual(self.type_id_of(ndt.type('var * int32')), diff --git a/dynd/tests/test_nd_fields.py b/dynd/tests/test_nd_fields.py index 515f8b00..e127c3f9 100644 --- a/dynd/tests/test_nd_fields.py +++ b/dynd/tests/test_nd_fields.py @@ -51,14 +51,14 @@ def test_fixed_var(self): type='3 * var * {x: int32, y: int32, z: string, w: string}') # Selecting a single field b = nd.fields(a, 'x') - self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.int32], ['x'])))) self.assertEqual(nd.as_py(b.x), nd.as_py(a.x)) # Selecting two fields b = nd.fields(a, 'z', 'y') - self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.string, ndt.int32], ['z', 'y'])))) @@ -66,7 +66,7 @@ def test_fixed_var(self): self.assertEqual(nd.as_py(b.y), nd.as_py(a.y)) # Selecting three fields b = nd.fields(a, 'w', 'y', 'z') - self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.string, ndt.int32, ndt.string], ['w', 'y', 'z'])))) @@ -75,7 +75,7 @@ def test_fixed_var(self): self.assertEqual(nd.as_py(b.z), nd.as_py(a.z)) # Reordering all four fields b = nd.fields(a, 'w', 'y', 'x', 'z') - self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.string, ndt.int32, ndt.int32, ndt.string], ['w', 'y', 'x', 'z'])))) diff --git a/dynd/tests/test_numpy_interop.py b/dynd/tests/test_numpy_interop.py index 0bd7d8ea..e51c35eb 100644 --- a/dynd/tests/test_numpy_interop.py +++ b/dynd/tests/test_numpy_interop.py @@ -78,7 +78,7 @@ def test_ndt_type_from_numpy_dtype_struct(self): # aligned struct tp0 = ndt.type(np.dtype([('x', np.int32), ('y', np.int64)], align=True)) - tp1 = ndt.type('{x : int32, y : int64}') + tp1 = ndt.type('c{x : int32, y : int64}') self.assertEqual(tp0, tp1) # unaligned struct tp0 = ndt.type(np.dtype([('x', np.int32), ('y', np.int64)])) @@ -108,7 +108,7 @@ def test_ndt_type_as_numpy(self): self.assertEqual(ndt.make_byteswap(ndt.float64).as_numpy(), np.dtype(nonnative + 'f8')) # aligned struct - tp0 = ndt.type('{x : int32, y : int64}').as_numpy() + tp0 = ndt.type('c{x : int32, y : int64}').as_numpy() tp1 = np.dtype([('x', np.int32), ('y', np.int64)], align=True) self.assertEqual(tp0, tp1) # unaligned struct @@ -347,7 +347,7 @@ def assign_to(x,y): class TestAsNumpy(unittest.TestCase): def test_cstruct_as_numpy(self): # Aligned cstruct - a = nd.array([[1, 2], [3, 4]], dtype='{x : int32, y: int64}') + a = nd.array([[1, 2], [3, 4]], dtype='c{x : int32, y: int64}') b = nd.as_numpy(a) self.assertEqual(b.dtype, np.dtype([('x', np.int32), ('y', np.int64)], align=True)) @@ -355,7 +355,7 @@ def test_cstruct_as_numpy(self): self.assertEqual(nd.as_py(a.y), b['y'].tolist()) # Unaligned cstruct a = nd.array([[1, 2], [3, 4]], - dtype='{x : unaligned[int32], y: unaligned[int64]}') + dtype='c{x : unaligned[int32], y: unaligned[int64]}') b = nd.as_numpy(a) self.assertEqual(b.dtype, np.dtype([('x', np.int32), ('y', np.int64)])) self.assertEqual(nd.as_py(a.x), b['x'].tolist()) @@ -363,7 +363,7 @@ def test_cstruct_as_numpy(self): def test_cstruct_via_pep3118(self): # Aligned cstruct - a = nd.array([[1, 2], [3, 4]], dtype='{x : int32, y: int64}') + a = nd.array([[1, 2], [3, 4]], dtype='c{x : int32, y: int64}') b = np.asarray(a) self.assertEqual(b.dtype, np.dtype([('x', np.int32), ('y', np.int64)], align=True)) @@ -371,7 +371,7 @@ def test_cstruct_via_pep3118(self): self.assertEqual(nd.as_py(a.y), b['y'].tolist()) # Unaligned cstruct a = nd.array([[1, 2], [3, 4]], - dtype='{x : unaligned[int32], y: unaligned[int64]}') + dtype='c{x : unaligned[int32], y: unaligned[int64]}') b = np.asarray(a) self.assertEqual(b.dtype, np.dtype([('x', np.int32), ('y', np.int64)])) self.assertEqual(nd.as_py(a.x), b['x'].tolist()) @@ -456,7 +456,7 @@ def test_numpy_struct_scalar(self): # Create a NumPy struct scalar object, by indexing into # a structured array a = np.array([(10, 11, 12)], dtype='i4,i8,f8')[0] - aligned_tp = ndt.type('{f0: int32, f1: int64, f2: float64}') + aligned_tp = ndt.type('c{f0: int32, f1: int64, f2: float64}') val = {'f0': 10, 'f1': 11, 'f2': 12} # Construct using nd.array diff --git a/include/ndt_type.pxd b/include/ndt_type.pxd index 715a4374..9951b453 100644 --- a/include/ndt_type.pxd +++ b/include/ndt_type.pxd @@ -135,7 +135,7 @@ cdef extern from "type_functions.hpp" namespace "pydynd": ndt_type dynd_make_pointer_type(ndt_type&) except +translate_exception ndt_type dynd_make_struct_type(object, object) except +translate_exception ndt_type dynd_make_cstruct_type(object, object) except +translate_exception - ndt_type dynd_make_fixed_dim_type(object, ndt_type&, object) except +translate_exception + ndt_type dynd_make_cfixed_dim_type(object, ndt_type&, object) except +translate_exception cdef extern from "numpy_interop.hpp" namespace "pydynd": object numpy_dtype_obj_from_ndt_type(ndt_type&) except +translate_exception diff --git a/include/type_functions.hpp b/include/type_functions.hpp index fe96c851..82115606 100644 --- a/include/type_functions.hpp +++ b/include/type_functions.hpp @@ -114,7 +114,7 @@ dynd::ndt::type dynd_make_pointer_type(const dynd::ndt::type& target_tp); dynd::ndt::type dynd_make_struct_type(PyObject *field_types, PyObject *field_names); dynd::ndt::type dynd_make_cstruct_type(PyObject *field_types, PyObject *field_names); -dynd::ndt::type dynd_make_fixed_dim_type(PyObject *shape, const dynd::ndt::type& element_tp, PyObject *axis_perm); +dynd::ndt::type dynd_make_cfixed_dim_type(PyObject *shape, const dynd::ndt::type& element_tp, PyObject *axis_perm); /** * Implementation of __getitem__ for the wrapped dynd type object. diff --git a/src/array_as_numpy.cpp b/src/array_as_numpy.cpp index e83154c9..280841b1 100644 --- a/src/array_as_numpy.cpp +++ b/src/array_as_numpy.cpp @@ -16,7 +16,7 @@ #include "utility_functions.hpp" #include -#include +#include #include #include #include @@ -122,7 +122,7 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, #endif } case strided_dim_type_id: - case fixed_dim_type_id: { + case cfixed_dim_type_id: { if (ndim > 0) { // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions @@ -132,7 +132,7 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, ndim - 1, sad->get_element_type(), metadata + sizeof(strided_dim_type_metadata)); } else { - const fixed_dim_type *fad = static_cast(dt.extended()); + const cfixed_dim_type *fad = static_cast(dt.extended()); make_numpy_dtype_for_copy(out_numpy_dtype, ndim - 1, fad->get_element_type(), metadata + sizeof(strided_dim_type_metadata)); @@ -158,9 +158,9 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, dim_size = sad->get_dim_size(metadata, NULL); element_tp = sad->get_element_type(); metadata += sizeof(strided_dim_type_metadata); - } else if (dt.get_type_id() == fixed_dim_type_id) { - const fixed_dim_type *fad = - static_cast(element_tp.extended()); + } else if (dt.get_type_id() == cfixed_dim_type_id) { + const cfixed_dim_type *fad = + static_cast(element_tp.extended()); dim_size = fad->get_fixed_dim_size(); element_tp = fad->get_element_type(); } else { @@ -372,8 +372,8 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir } break; } - case fixed_dim_type_id: { - const fixed_dim_type *fad = static_cast(dt.extended()); + case cfixed_dim_type_id: { + const cfixed_dim_type *fad = static_cast(dt.extended()); if (ndim > 0) { // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions @@ -389,9 +389,9 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir ndt::type element_tp = dt; while(ndim > 0) { size_t dim_size = 0; - if (dt.get_type_id() == fixed_dim_type_id) { - const fixed_dim_type *fad = - static_cast(element_tp.extended()); + if (dt.get_type_id() == cfixed_dim_type_id) { + const cfixed_dim_type *fad = + static_cast(element_tp.extended()); element_tp = fad->get_element_type(); if (fad->get_data_size() != element_tp.get_data_size() * dim_size) { diff --git a/src/array_as_pep3118.cpp b/src/array_as_pep3118.cpp index e586954d..861e1cc2 100644 --- a/src/array_as_pep3118.cpp +++ b/src/array_as_pep3118.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -129,11 +129,11 @@ static void append_pep3118_format(intptr_t& out_itemsize, const ndt::type& dt, } // Pass through to error break; - case fixed_dim_type_id: { + case cfixed_dim_type_id: { ndt::type child_dt = dt; o << "("; do { - const fixed_dim_type *tdt = static_cast(child_dt.extended()); + const cfixed_dim_type *tdt = static_cast(child_dt.extended()); size_t dim_size = tdt->get_fixed_dim_size(); o << dim_size; if (child_dt.get_data_size() != tdt->get_element_type().get_data_size() * dim_size) { @@ -143,7 +143,7 @@ static void append_pep3118_format(intptr_t& out_itemsize, const ndt::type& dt, } o << ")"; child_dt = tdt->get_element_type(); - } while (child_dt.get_type_id() == fixed_dim_type_id && (o << ",")); + } while (child_dt.get_type_id() == cfixed_dim_type_id && (o << ",")); append_pep3118_format(out_itemsize, child_dt, metadata, o); out_itemsize = dt.get_data_size(); return; @@ -330,8 +330,8 @@ int pydynd::array_getbuffer_pep3118(PyObject *ndo, Py_buffer *buffer, int flags) dt = tdt->get_element_type(); break; } - case fixed_dim_type_id: { - const fixed_dim_type *tdt = static_cast(dt.extended()); + case cfixed_dim_type_id: { + const cfixed_dim_type *tdt = static_cast(dt.extended()); buffer->shape[i] = tdt->get_fixed_dim_size(); buffer->strides[i] = tdt->get_fixed_stride(); dt = tdt->get_element_type(); diff --git a/src/array_assign_from_py.cpp b/src/array_assign_from_py.cpp index 7f701372..bdae8513 100644 --- a/src/array_assign_from_py.cpp +++ b/src/array_assign_from_py.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -455,8 +455,8 @@ static void array_assign_from_pyseq(const dynd::ndt::type& dt, const char *metadata, char *data, PyObject *seq, size_t seqsize) { switch (dt.get_type_id()) { - case fixed_dim_type_id: { - const fixed_dim_type *fdd = static_cast(dt.extended()); + case cfixed_dim_type_id: { + const cfixed_dim_type *fdd = static_cast(dt.extended()); array_assign_strided_from_pyseq(fdd->get_element_type(), metadata, data, fdd->get_fixed_stride(), fdd->get_fixed_dim_size(), seq, seqsize); break; @@ -536,8 +536,8 @@ static void array_assign_from_pyiter(const dynd::ndt::type& dt, const char *metadata, char *data, PyObject *iter, PyObject *obj) { switch (dt.get_type_id()) { - case fixed_dim_type_id: { - const fixed_dim_type *fdd = static_cast(dt.extended()); + case cfixed_dim_type_id: { + const cfixed_dim_type *fdd = static_cast(dt.extended()); array_assign_strided_from_pyiter(fdd->get_element_type(), metadata, data, fdd->get_fixed_stride(), fdd->get_fixed_dim_size(), iter); break; diff --git a/src/array_from_py.cpp b/src/array_from_py.cpp index 91345e00..af65e103 100644 --- a/src/array_from_py.cpp +++ b/src/array_from_py.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -614,7 +614,7 @@ static bool ndt_type_requires_shape(const ndt::type& tp) { if (tp.get_ndim() > 0) { switch (tp.get_type_id()) { - case fixed_dim_type_id: + case cfixed_dim_type_id: case var_dim_type_id: return ndt_type_requires_shape( static_cast( diff --git a/src/array_from_py_dynamic.cpp b/src/array_from_py_dynamic.cpp index dc22529d..d01a0167 100644 --- a/src/array_from_py_dynamic.cpp +++ b/src/array_from_py_dynamic.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/array_from_py_typededuction.cpp b/src/array_from_py_typededuction.cpp index dccda4a1..a1c280d9 100644 --- a/src/array_from_py_typededuction.cpp +++ b/src/array_from_py_typededuction.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/array_functions.cpp b/src/array_functions.cpp index 4e239474..c4bd686c 100644 --- a/src/array_functions.cpp +++ b/src/array_functions.cpp @@ -759,7 +759,10 @@ dynd::nd::array pydynd::nd_fields(const nd::array& n, PyObject *field_list) selected_ndt_types[i] = field_types[selected_index[i]]; } // Create the result udt - ndt::type rudt = ndt::make_struct(selected_ndt_types, selected_fields); + ndt::type rudt = ndt::make_struct( + selected_ndt_types.size(), + selected_ndt_types.empty() ? NULL : &selected_ndt_types[0], + selected_fields.empty() ? NULL : &selected_fields[0]); ndt::type result_tp = n.get_type().with_replaced_dtype(rudt); const base_struct_type *rudt_bsd = static_cast(rudt.extended()); diff --git a/src/ctypes_interop.cpp b/src/ctypes_interop.cpp index 974301b0..98e238ee 100644 --- a/src/ctypes_interop.cpp +++ b/src/ctypes_interop.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -245,18 +245,22 @@ dynd::ndt::type pydynd::ndt_type_from_ctypes_cdatatype(PyObject *d) if (is_cstruct_compatible_offsets(field_count, &field_types[0], &field_offsets[0], total_size)) { - return ndt::make_cstruct(field_count, &field_types[0], &field_names[0]); + return ndt::make_cstruct( + field_count, field_types.empty() ? NULL : &field_types[0], + field_names.empty() ? NULL : &field_names[0]); } else { - return ndt::make_struct(field_types, field_names); + return ndt::make_struct( + field_count, field_types.empty() ? NULL : &field_types[0], + field_names.empty() ? NULL : &field_names[0]); } } else if (PyObject_IsSubclass(d, ctypes.PyCArrayType_Type)) { - // Translate into a either a fixed_dim or strided_dim + // Translate into a either a cfixed_dim or strided_dim pyobject_ownref element_tp_obj(PyObject_GetAttrString(d, "_type_")); ndt::type element_tp = ndt_type_from_ctypes_cdatatype(element_tp_obj); if (element_tp.get_data_size() != 0) { pyobject_ownref array_length_obj(PyObject_GetAttrString(d, "_length_")); intptr_t array_length = pyobject_as_index(array_length_obj.get()); - return ndt::make_fixed_dim(array_length, element_tp); + return ndt::make_cfixed_dim(array_length, element_tp); } else { return ndt::make_strided_dim(element_tp); } diff --git a/src/numpy_interop.cpp b/src/numpy_interop.cpp index 3a986e4c..cc16cf6d 100644 --- a/src/numpy_interop.cpp +++ b/src/numpy_interop.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -74,9 +74,13 @@ ndt::type make_struct_type_from_numpy_struct(PyArray_Descr *d, size_t data_align // Make a cstruct if possible, struct otherwise if (is_cstruct_compatible_offsets(field_types.size(), &field_types[0], &field_offsets[0], d->elsize)) { - return ndt::make_cstruct(field_types.size(), &field_types[0], &field_names[0]); + return ndt::make_cstruct(field_types.size(), + field_types.empty() ? NULL : &field_types[0], + field_names.empty() ? NULL : &field_names[0]); } else { - return ndt::make_struct(field_types, field_names); + return ndt::make_struct(field_types.size(), + field_types.empty() ? NULL : &field_types[0], + field_names.empty() ? NULL : &field_names[0]); } } @@ -100,7 +104,7 @@ ndt::type pydynd::ndt_type_from_numpy_dtype(PyArray_Descr *d, size_t data_alignm return ndt::make_strided_dim(dt, ndim); } else { // Otherwise make a fixed dim array - return dynd_make_fixed_dim_type(d->subarray->shape, dt, Py_None); + return dynd_make_cfixed_dim_type(d->subarray->shape, dt, Py_None); } } @@ -484,11 +488,11 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp) } return result; } - case fixed_dim_type_id: { + case cfixed_dim_type_id: { ndt::type child_tp = tp; vector shape; do { - const fixed_dim_type *ttp = static_cast(child_tp.extended()); + const cfixed_dim_type *ttp = static_cast(child_tp.extended()); shape.push_back(ttp->get_fixed_dim_size()); if (child_tp.get_data_size() != ttp->get_element_type().get_data_size() * shape.back()) { stringstream ss; @@ -496,7 +500,7 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp) throw dynd::type_error(ss.str()); } child_tp = ttp->get_element_type(); - } while (child_tp.get_type_id() == fixed_dim_type_id); + } while (child_tp.get_type_id() == cfixed_dim_type_id); pyobject_ownref dtype_obj((PyObject *)numpy_dtype_from_ndt_type(child_tp)); pyobject_ownref shape_obj(intptr_array_as_tuple((int)shape.size(), &shape[0])); pyobject_ownref tuple_obj(PyTuple_New(2)); diff --git a/src/type_functions.cpp b/src/type_functions.cpp index 38bad123..11017b9b 100644 --- a/src/type_functions.cpp +++ b/src/type_functions.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -339,7 +339,16 @@ dynd::ndt::type pydynd::dynd_make_struct_type(PyObject *field_types, PyObject *f vector field_names_vec; pyobject_as_vector_ndt_type(field_types, field_types_vec); pyobject_as_vector_string(field_names, field_names_vec); - return ndt::make_struct(field_types_vec, field_names_vec); + if (field_types_vec.size() != field_names_vec.size()) { + stringstream ss; + ss << "creating a struct type requires that the number of types "; + ss << field_types_vec.size() << " must equal the number of names "; + ss << field_names_vec.size(); + throw invalid_argument(ss.str()); + } + return ndt::make_struct(field_types_vec.size(), + field_types_vec.empty() ? NULL : &field_types_vec[0], + field_names_vec.empty() ? NULL : &field_names_vec[0]); } dynd::ndt::type pydynd::dynd_make_cstruct_type(PyObject *field_types, PyObject *field_names) @@ -349,12 +358,19 @@ dynd::ndt::type pydynd::dynd_make_cstruct_type(PyObject *field_types, PyObject * pyobject_as_vector_ndt_type(field_types, field_types_vec); pyobject_as_vector_string(field_names, field_names_vec); if (field_types_vec.size() != field_names_vec.size()) { - throw runtime_error("The input field types and field names lists must have the same size"); + stringstream ss; + ss << "creating a cstruct type requires that the number of types "; + ss << field_types_vec.size() << " must equal the number of names "; + ss << field_names_vec.size(); + throw invalid_argument(ss.str()); } - return ndt::make_cstruct(field_types_vec.size(), &field_types_vec[0], &field_names_vec[0]); + return ndt::make_cstruct( + field_types_vec.size(), + field_types_vec.empty() ? NULL : &field_types_vec[0], + field_names_vec.empty() ? NULL : &field_names_vec[0]); } -dynd::ndt::type pydynd::dynd_make_fixed_dim_type(PyObject *shape, const ndt::type& element_tp, PyObject *axis_perm) +dynd::ndt::type pydynd::dynd_make_cfixed_dim_type(PyObject *shape, const ndt::type& element_tp, PyObject *axis_perm) { vector shape_vec; if (PySequence_Check(shape)) { @@ -372,9 +388,9 @@ dynd::ndt::type pydynd::dynd_make_fixed_dim_type(PyObject *shape, const ndt::typ if (axis_perm_vec.size() != shape_vec.size()) { throw runtime_error("Provided axis_perm is a different size than the provided shape"); } - return ndt::make_fixed_dim(shape_vec.size(), &shape_vec[0], element_tp, &axis_perm_vec[0]); + return ndt::make_cfixed_dim(shape_vec.size(), &shape_vec[0], element_tp, &axis_perm_vec[0]); } else { - return ndt::make_fixed_dim(shape_vec.size(), &shape_vec[0], element_tp, NULL); + return ndt::make_cfixed_dim(shape_vec.size(), &shape_vec[0], element_tp, NULL); } } From cc7aad2ad1bb03484c6c1c45db364c979ec7bb3f Mon Sep 17 00:00:00 2001 From: Mark Wiebe Date: Sun, 20 Apr 2014 15:08:53 -0700 Subject: [PATCH 2/6] Update for ctuple type id --- dynd/_lowlevel/type_id.py | 23 ++++++++++++----------- dynd/tests/test_lowlevel.py | 5 +++++ dynd/tests/test_numpy_interop.py | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/dynd/_lowlevel/type_id.py b/dynd/_lowlevel/type_id.py index 3ef4f938..0fedeb84 100644 --- a/dynd/_lowlevel/type_id.py +++ b/dynd/_lowlevel/type_id.py @@ -57,16 +57,17 @@ STRUCT = 36 CSTRUCT = 37 TUPLE = 38 -NDOBJECT = 39 -CONVERT = 40 -BYTESWAP = 41 -VIEW = 42 -CUDA_HOST = 43 -CUDA_DEVICE = 44 -PROPERTY = 45 -EXPR = 46 -UNARY_EXPR = 47 -GROUPBY = 48 -TYPE = 49 +CTUPLE = 39 +NDOBJECT = 40 +CONVERT = 41 +BYTESWAP = 42 +VIEW = 43 +CUDA_HOST = 44 +CUDA_DEVICE = 45 +PROPERTY = 46 +EXPR = 47 +UNARY_EXPR = 48 +GROUPBY = 49 +TYPE = 50 BUILTIN_TYPE_ID_COUNT = 19 diff --git a/dynd/tests/test_lowlevel.py b/dynd/tests/test_lowlevel.py index 7410fc7f..2f7ce5c5 100644 --- a/dynd/tests/test_lowlevel.py +++ b/dynd/tests/test_lowlevel.py @@ -74,6 +74,11 @@ def test_type_id(self): _lowlevel.type_id.STRUCT) self.assertEqual(self.type_id_of(ndt.type('c{x : int32, y : int32}')), _lowlevel.type_id.CSTRUCT) + # Tuple + self.assertEqual(self.type_id_of(ndt.type('(int32, int32)')), + _lowlevel.type_id.TUPLE) + self.assertEqual(self.type_id_of(ndt.type('c(int32, int32)')), + _lowlevel.type_id.CTUPLE) # Convert/byteswap/view self.assertEqual(self.type_id_of(ndt.make_convert( ndt.int32, ndt.int8)), diff --git a/dynd/tests/test_numpy_interop.py b/dynd/tests/test_numpy_interop.py index e51c35eb..dbcd4726 100644 --- a/dynd/tests/test_numpy_interop.py +++ b/dynd/tests/test_numpy_interop.py @@ -456,7 +456,7 @@ def test_numpy_struct_scalar(self): # Create a NumPy struct scalar object, by indexing into # a structured array a = np.array([(10, 11, 12)], dtype='i4,i8,f8')[0] - aligned_tp = ndt.type('c{f0: int32, f1: int64, f2: float64}') + aligned_tp = ndt.type('{f0: int32, f1: int64, f2: float64}') val = {'f0': 10, 'f1': 11, 'f2': 12} # Construct using nd.array From 089493bbc5e955b903abb8d933e53e82682eeff6 Mon Sep 17 00:00:00 2001 From: Mark Wiebe Date: Sun, 20 Apr 2014 16:11:51 -0700 Subject: [PATCH 3/6] Use ndt::type::tcast<>() as added to libdynd --- src/array_as_numpy.cpp | 26 +++++++++++++------------- src/array_as_pep3118.cpp | 14 +++++++------- src/array_as_py.cpp | 10 +++++----- src/array_assign_from_py.cpp | 20 ++++++++++---------- src/array_from_py.cpp | 14 +++++++------- src/array_from_py_dynamic.cpp | 10 +++++----- src/array_from_py_typededuction.cpp | 2 +- src/array_functions.cpp | 26 ++++++++++++-------------- src/gfunc_callable_functions.cpp | 10 +++++----- src/numpy_interop.cpp | 18 +++++++++--------- src/type_functions.cpp | 10 +++++----- 11 files changed, 79 insertions(+), 81 deletions(-) diff --git a/src/array_as_numpy.cpp b/src/array_as_numpy.cpp index 280841b1..d077369a 100644 --- a/src/array_as_numpy.cpp +++ b/src/array_as_numpy.cpp @@ -63,7 +63,7 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, switch (dt.get_type_id()) { case fixedstring_type_id: { - const fixedstring_type *fsd = static_cast(dt.extended()); + const fixedstring_type *fsd = dt.tcast(); PyArray_Descr *result; switch (fsd->get_encoding()) { case string_encoding_ascii: @@ -127,12 +127,12 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions if (dt.get_type_id() == strided_dim_type_id) { - const strided_dim_type *sad = static_cast(dt.extended()); + const strided_dim_type *sad = dt.tcast(); make_numpy_dtype_for_copy(out_numpy_dtype, ndim - 1, sad->get_element_type(), metadata + sizeof(strided_dim_type_metadata)); } else { - const cfixed_dim_type *fad = static_cast(dt.extended()); + const cfixed_dim_type *fad = dt.tcast(); make_numpy_dtype_for_copy(out_numpy_dtype, ndim - 1, fad->get_element_type(), metadata + sizeof(strided_dim_type_metadata)); @@ -154,13 +154,13 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, size_t dim_size = 0; if (dt.get_type_id() == strided_dim_type_id) { const strided_dim_type *sad = - static_cast(element_tp.extended()); + element_tp.tcast(); dim_size = sad->get_dim_size(metadata, NULL); element_tp = sad->get_element_type(); metadata += sizeof(strided_dim_type_metadata); } else if (dt.get_type_id() == cfixed_dim_type_id) { const cfixed_dim_type *fad = - static_cast(element_tp.extended()); + element_tp.tcast(); dim_size = fad->get_fixed_dim_size(); element_tp = fad->get_element_type(); } else { @@ -196,7 +196,7 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, } case cstruct_type_id: case struct_type_id: { - const base_struct_type *bs = static_cast(dt.extended()); + const base_struct_type *bs = dt.tcast(); const ndt::type *field_types = bs->get_field_types(); const string *field_names = bs->get_field_names(); size_t field_count = bs->get_field_count(); @@ -285,7 +285,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir switch (dt.get_type_id()) { case fixedstring_type_id: { - const fixedstring_type *fsd = static_cast(dt.extended()); + const fixedstring_type *fsd = dt.tcast(); PyArray_Descr *result; switch (fsd->get_encoding()) { case string_encoding_ascii: @@ -324,7 +324,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir #endif } case property_type_id: { - const property_type *pd = static_cast(dt.extended()); + const property_type *pd = dt.tcast(); // Special-case of 'int64 as date' property type, which is binary // compatible with NumPy's "M8[D]" if (pd->is_reversed_property() && pd->get_value_type().get_type_id() == date_type_id && @@ -344,7 +344,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir break; } case byteswap_type_id: { - const base_expression_type *bed = static_cast(dt.extended()); + const base_expression_type *bed = dt.tcast(); // Analyze the unswapped version as_numpy_analysis(out_numpy_dtype, out_requires_copy, ndim, bed->get_value_type(), metadata); @@ -355,7 +355,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir return; } case strided_dim_type_id: { - const strided_dim_type *sad = static_cast(dt.extended()); + const strided_dim_type *sad = dt.tcast(); if (ndim > 0) { // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions @@ -373,7 +373,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir break; } case cfixed_dim_type_id: { - const cfixed_dim_type *fad = static_cast(dt.extended()); + const cfixed_dim_type *fad = dt.tcast(); if (ndim > 0) { // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions @@ -391,7 +391,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir size_t dim_size = 0; if (dt.get_type_id() == cfixed_dim_type_id) { const cfixed_dim_type *fad = - static_cast(element_tp.extended()); + element_tp.tcast(); element_tp = fad->get_element_type(); if (fad->get_data_size() != element_tp.get_data_size() * dim_size) { @@ -444,7 +444,7 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir *out_requires_copy = true; return; } - const base_struct_type *bs = static_cast(dt.extended()); + const base_struct_type *bs = dt.tcast(); const ndt::type *field_types = bs->get_field_types(); const string *field_names = bs->get_field_names(); const size_t *offsets = bs->get_data_offsets(metadata); diff --git a/src/array_as_pep3118.cpp b/src/array_as_pep3118.cpp index 861e1cc2..b29aacde 100644 --- a/src/array_as_pep3118.cpp +++ b/src/array_as_pep3118.cpp @@ -110,7 +110,7 @@ static void append_pep3118_format(intptr_t& out_itemsize, const ndt::type& dt, out_itemsize = 16; return; case fixedstring_type_id: - switch (static_cast(dt.extended())->get_encoding()) { + switch (dt.tcast()->get_encoding()) { case string_encoding_ascii: { intptr_t element_size = dt.get_data_size(); o << element_size << "s"; @@ -133,7 +133,7 @@ static void append_pep3118_format(intptr_t& out_itemsize, const ndt::type& dt, ndt::type child_dt = dt; o << "("; do { - const cfixed_dim_type *tdt = static_cast(child_dt.extended()); + const cfixed_dim_type *tdt = child_dt.tcast(); size_t dim_size = tdt->get_fixed_dim_size(); o << dim_size; if (child_dt.get_data_size() != tdt->get_element_type().get_data_size() * dim_size) { @@ -150,7 +150,7 @@ static void append_pep3118_format(intptr_t& out_itemsize, const ndt::type& dt, } case cstruct_type_id: { o << "T{"; - const cstruct_type *tdt = static_cast(dt.extended()); + const cstruct_type *tdt = dt.tcast(); const ndt::type *field_types = tdt->get_field_types(); const string *field_names = tdt->get_field_names(); size_t num_fields = tdt->get_field_count(); @@ -185,13 +185,13 @@ static void append_pep3118_format(intptr_t& out_itemsize, const ndt::type& dt, uint16_t u; } vals; vals.u = '>' + ('<' << 8); - const byteswap_type *bd = static_cast(dt.extended()); + const byteswap_type *bd = dt.tcast(); o << vals.s[0]; append_pep3118_format(out_itemsize, bd->get_value_type(), metadata, o); return; } case view_type_id: { - const view_type *vd = static_cast(dt.extended()); + const view_type *vd = dt.tcast(); // If it's a view of bytes, usually to view unaligned data, can ignore it // since the buffer format we're creating doesn't use alignment if (vd->get_operand_type().get_type_id() == fixedbytes_type_id) { @@ -322,7 +322,7 @@ int pydynd::array_getbuffer_pep3118(PyObject *ndo, Py_buffer *buffer, int flags) for (int i = 0; i < buffer->ndim; ++i) { switch (dt.get_type_id()) { case strided_dim_type_id: { - const strided_dim_type *tdt = static_cast(dt.extended()); + const strided_dim_type *tdt = dt.tcast(); const strided_dim_type_metadata *md = reinterpret_cast(metadata); buffer->shape[i] = md->size; buffer->strides[i] = md->stride; @@ -331,7 +331,7 @@ int pydynd::array_getbuffer_pep3118(PyObject *ndo, Py_buffer *buffer, int flags) break; } case cfixed_dim_type_id: { - const cfixed_dim_type *tdt = static_cast(dt.extended()); + const cfixed_dim_type *tdt = dt.tcast(); buffer->shape[i] = tdt->get_fixed_dim_size(); buffer->strides[i] = tdt->get_fixed_stride(); dt = tdt->get_element_type(); diff --git a/src/array_as_py.cpp b/src/array_as_py.cpp index cbfe267b..0a7f1e6a 100644 --- a/src/array_as_py.cpp +++ b/src/array_as_py.cpp @@ -98,7 +98,7 @@ static PyObject* element_as_pyobject(const ndt::type& d, const char *data, const case string_type_id: case json_type_id: { const char *begin = NULL, *end = NULL; - const base_string_type *esd = static_cast(d.extended()); + const base_string_type *esd = d.tcast(); esd->get_string_range(&begin, &end, metadata, data); switch (esd->get_encoding()) { case string_encoding_ascii: @@ -115,18 +115,18 @@ static PyObject* element_as_pyobject(const ndt::type& d, const char *data, const } } case date_type_id: { - const date_type *dd = static_cast(d.extended()); + const date_type *dd = d.tcast(); date_ymd ymd = dd->get_ymd(metadata, data); return PyDate_FromDate(ymd.year, ymd.month, ymd.day); } case time_type_id: { - const time_type *tt = static_cast(d.extended()); + const time_type *tt = d.tcast(); time_hmst hmst = tt->get_time(metadata, data); return PyTime_FromTime(hmst.hour, hmst.minute, hmst.second, hmst.tick / DYND_TICKS_PER_MICROSECOND); } case datetime_type_id: { - const datetime_type *dd = static_cast(d.extended()); + const datetime_type *dd = d.tcast(); int32_t year, month, day, hour, minute, second, tick; dd->get_cal(metadata, data, year, month, day, hour, minute, second, tick); int32_t usecond = tick / 10; @@ -157,7 +157,7 @@ static void nested_struct_as_py(const ndt::type& d, char *data, const char *meta { array_as_py_data *r = reinterpret_cast(result); - const base_struct_type *bsd = static_cast(d.extended()); + const base_struct_type *bsd = d.tcast(); size_t field_count = bsd->get_field_count(); const string *field_names = bsd->get_field_names(); const ndt::type *field_types = bsd->get_field_types(); diff --git a/src/array_assign_from_py.cpp b/src/array_assign_from_py.cpp index bdae8513..729c67cd 100644 --- a/src/array_assign_from_py.cpp +++ b/src/array_assign_from_py.cpp @@ -402,7 +402,7 @@ static void array_assign_from_pydict(const dynd::ndt::type& dt, const char *metadata, char *data, PyObject *value) { if (dt.get_kind() == struct_kind) { - const base_struct_type *fsd = static_cast(dt.extended()); + const base_struct_type *fsd = dt.tcast(); size_t field_count = fsd->get_field_count(); const string *field_names = fsd->get_field_names(); const ndt::type *field_types = fsd->get_field_types(); @@ -456,20 +456,20 @@ static void array_assign_from_pyseq(const dynd::ndt::type& dt, { switch (dt.get_type_id()) { case cfixed_dim_type_id: { - const cfixed_dim_type *fdd = static_cast(dt.extended()); + const cfixed_dim_type *fdd = dt.tcast(); array_assign_strided_from_pyseq(fdd->get_element_type(), metadata, data, fdd->get_fixed_stride(), fdd->get_fixed_dim_size(), seq, seqsize); break; } case strided_dim_type_id: { - const ndt::type& element_dt = static_cast(dt.extended())->get_element_type(); + const ndt::type& element_dt = dt.tcast()->get_element_type(); const strided_dim_type_metadata *md = reinterpret_cast(metadata); array_assign_strided_from_pyseq(element_dt, metadata + sizeof(strided_dim_type_metadata), data, md->stride, md->size, seq, seqsize); break; } case var_dim_type_id: { - const ndt::type& element_dt = static_cast(dt.extended())->get_element_type(); + const ndt::type& element_dt = dt.tcast()->get_element_type(); const var_dim_type_metadata *md = reinterpret_cast(metadata); var_dim_type_data *d = reinterpret_cast(data); if (d->begin == NULL) { @@ -503,7 +503,7 @@ static void array_assign_from_pyseq(const dynd::ndt::type& dt, } case struct_type_id: case cstruct_type_id: { - const base_struct_type *fsd = static_cast(dt.extended()); + const base_struct_type *fsd = dt.tcast(); size_t field_count = fsd->get_field_count(); const ndt::type *field_types = fsd->get_field_types(); const size_t *data_offsets = fsd->get_data_offsets(metadata); @@ -537,20 +537,20 @@ static void array_assign_from_pyiter(const dynd::ndt::type& dt, { switch (dt.get_type_id()) { case cfixed_dim_type_id: { - const cfixed_dim_type *fdd = static_cast(dt.extended()); + const cfixed_dim_type *fdd = dt.tcast(); array_assign_strided_from_pyiter(fdd->get_element_type(), metadata, data, fdd->get_fixed_stride(), fdd->get_fixed_dim_size(), iter); break; } case strided_dim_type_id: { - const ndt::type& element_dt = static_cast(dt.extended())->get_element_type(); + const ndt::type& element_dt = dt.tcast()->get_element_type(); const strided_dim_type_metadata *md = reinterpret_cast(metadata); array_assign_strided_from_pyiter(element_dt, metadata + sizeof(strided_dim_type_metadata), data, md->stride, md->size, iter); break; } case var_dim_type_id: { - const ndt::type& element_dt = static_cast(dt.extended())->get_element_type(); + const ndt::type& element_dt = dt.tcast()->get_element_type(); const var_dim_type_metadata *md = reinterpret_cast(metadata); var_dim_type_data *d = reinterpret_cast(data); // First check if the var_dim element is already assigned, @@ -659,7 +659,7 @@ static void array_assign_from_pyiter(const dynd::ndt::type& dt, } case struct_type_id: case cstruct_type_id: { - const base_struct_type *fsd = static_cast(dt.extended()); + const base_struct_type *fsd = dt.tcast(); size_t field_count = fsd->get_field_count(); const ndt::type *field_types = fsd->get_field_types(); const size_t *data_offsets = fsd->get_data_offsets(metadata); @@ -746,7 +746,7 @@ void pydynd::array_broadcast_assign_from_py(const dynd::ndt::type& dt, udt = udt.get_dtype(); } else if (udt.get_kind() == struct_kind) { ++dst_ndim; - udt = static_cast(udt.extended())->get_field_types()[0]; + udt = udt.tcast()->get_field_types()[0]; } else { break; } diff --git a/src/array_from_py.cpp b/src/array_from_py.cpp index af65e103..196de92e 100644 --- a/src/array_from_py.cpp +++ b/src/array_from_py.cpp @@ -180,7 +180,7 @@ inline void convert_one_pyscalar_date(const ndt::type& tp, const char *metadata, if (!PyDate_Check(obj)) { throw dynd::type_error("input object is not a date as expected"); } - const date_type *dd = static_cast(tp.extended()); + const date_type *dd = tp.tcast(); dd->set_ymd(metadata, out, assign_error_fractional, PyDateTime_GET_YEAR(obj), PyDateTime_GET_MONTH(obj), PyDateTime_GET_DAY(obj)); } @@ -190,7 +190,7 @@ inline void convert_one_pyscalar_time(const ndt::type& tp, const char *metadata, if (!PyTime_Check(obj)) { throw dynd::type_error("input object is not a time as expected"); } - const time_type *tt = static_cast(tp.extended()); + const time_type *tt = tp.tcast(); tt->set_time( metadata, out, assign_error_fractional, PyDateTime_TIME_GET_HOUR(obj), PyDateTime_TIME_GET_MINUTE(obj), PyDateTime_TIME_GET_SECOND(obj), @@ -206,7 +206,7 @@ inline void convert_one_pyscalar_datetime(const ndt::type& tp, const char *metad ((PyDateTime_DateTime *)obj)->tzinfo != NULL) { throw runtime_error("Converting datetimes with a timezone to dynd arrays is not yet supported"); } - const datetime_type *dd = static_cast(tp.extended()); + const datetime_type *dd = tp.tcast(); dd->set_cal(metadata, out, assign_error_fractional, PyDateTime_GET_YEAR(obj), PyDateTime_GET_MONTH(obj), PyDateTime_GET_DAY(obj), PyDateTime_DATE_GET_HOUR(obj), PyDateTime_DATE_GET_MINUTE(obj), @@ -337,7 +337,7 @@ static dynd::nd::array array_from_pylist(PyObject *obj) obj, &shape[0], 0); break; case string_type_id: { - const base_string_type *ext = static_cast(tp.extended()); + const base_string_type *ext = tp.tcast(); if (ext->get_encoding() == string_encoding_utf_8) { fill_array_from_pylist(result.get_type(), result.get_ndo_meta(), @@ -529,7 +529,7 @@ dynd::nd::array pydynd::array_from_py(PyObject *obj, uint32_t access_flags, bool "arrays is not yet supported"); } ndt::type d = ndt::make_datetime(tz_abstract); - const datetime_type *dd = static_cast(d.extended()); + const datetime_type *dd = d.tcast(); result = nd::empty(d); dd->set_cal(result.get_ndo_meta(), result.get_ndo()->m_data_pointer, assign_error_fractional, PyDateTime_GET_YEAR(obj), @@ -540,7 +540,7 @@ dynd::nd::array pydynd::array_from_py(PyObject *obj, uint32_t access_flags, bool PyDateTime_DATE_GET_MICROSECOND(obj) * 10); } else if (PyDate_Check(obj)) { ndt::type d = ndt::make_date(); - const date_type *dd = static_cast(d.extended()); + const date_type *dd = d.tcast(); result = nd::empty(d); dd->set_ymd(result.get_ndo_meta(), result.get_ndo()->m_data_pointer, assign_error_fractional, PyDateTime_GET_YEAR(obj), @@ -552,7 +552,7 @@ dynd::nd::array pydynd::array_from_py(PyObject *obj, uint32_t access_flags, bool "arrays is not yet supported"); } ndt::type d = ndt::make_time(tz_abstract); - const time_type *tt = static_cast(d.extended()); + const time_type *tt = d.tcast(); result = nd::empty(d); tt->set_time(result.get_ndo_meta(), result.get_ndo()->m_data_pointer, assign_error_fractional, PyDateTime_TIME_GET_HOUR(obj), diff --git a/src/array_from_py_dynamic.cpp b/src/array_from_py_dynamic.cpp index d01a0167..9b220073 100644 --- a/src/array_from_py_dynamic.cpp +++ b/src/array_from_py_dynamic.cpp @@ -126,11 +126,11 @@ static nd::array allocate_nd_arr( } // Advance metadata_ptr and data_ptr to the child dimension metadata_ptr += sizeof(var_dim_type_metadata); - tp = static_cast(tp.extended())->get_element_type(); + tp = tp.tcast()->get_element_type(); } else { // Advance metadata_ptr and data_ptr to the child dimension metadata_ptr += sizeof(strided_dim_type_metadata); - tp = static_cast(tp.extended())->get_element_type(); + tp = tp.tcast()->get_element_type(); } c.data_ptr = data_ptr; } @@ -552,7 +552,7 @@ static bool string_assign(const ndt::type& tp, const char *metadata, char *data, throw exception(); } - const string_type *st = static_cast(tp.extended()); + const string_type *st = tp.tcast(); st->set_utf8_string(metadata, data, assign_error_default, s, s + len); return true; } @@ -564,7 +564,7 @@ static bool string_assign(const ndt::type& tp, const char *metadata, char *data, throw runtime_error("Error getting string data"); } - const string_type *st = static_cast(tp.extended()); + const string_type *st = tp.tcast(); st->set_utf8_string(metadata, data, assign_error_default, s, s + len); return true; } @@ -594,7 +594,7 @@ static bool bytes_assign(const ndt::type& tp, const char *metadata, char *data, throw runtime_error("Error getting bytes data"); } - const bytes_type *st = static_cast(tp.extended()); + const bytes_type *st = tp.tcast(); st->set_bytes_data(metadata, data, s, s + len); return true; } diff --git a/src/array_from_py_typededuction.cpp b/src/array_from_py_typededuction.cpp index a1c280d9..12e1e850 100644 --- a/src/array_from_py_typededuction.cpp +++ b/src/array_from_py_typededuction.cpp @@ -243,7 +243,7 @@ size_t pydynd::get_nonragged_dim_count(const ndt::type& tp, size_t max_count) if (max_count <= 1) { return max_count; } else { - const base_struct_type *bsd = static_cast(tp.extended()); + const base_struct_type *bsd = tp.tcast(); size_t field_count = bsd->get_field_count(); const ndt::type *field_types = bsd->get_field_types(); for (size_t i = 0; i != field_count; ++i) { diff --git a/src/array_functions.cpp b/src/array_functions.cpp index c4bd686c..55c230e8 100644 --- a/src/array_functions.cpp +++ b/src/array_functions.cpp @@ -39,8 +39,8 @@ PyObject *pydynd::array_str(const dynd::nd::array& n) #else nd::array n_str; if (n.get_type().get_kind() == string_kind && - static_cast( - n.get_type().extended())->get_encoding() == string_encoding_ascii) { + n.get_type().tcast()->get_encoding() == + string_encoding_ascii) { // If it's already an ASCII string, pass-through n_str = n; } else { @@ -48,8 +48,7 @@ PyObject *pydynd::array_str(const dynd::nd::array& n) n_str = nd::empty(ndt::make_string(string_encoding_ascii)); n_str.vals() = n; } - const base_string_type *bsd = - static_cast(n_str.get_type().extended()); + const base_string_type *bsd = n_str.get_type().tcast(); const char *begin = NULL, *end = NULL; bsd->get_string_range(&begin, &end, n_str.get_ndo_meta(), n_str.get_readonly_originptr()); return PyString_FromStringAndSize(begin, end - begin); @@ -70,8 +69,8 @@ PyObject *pydynd::array_unicode(const dynd::nd::array& n) { nd::array n_str; if (n.get_type().get_kind() == string_kind && - static_cast( - n.get_type().extended())->get_encoding() == DYND_PY_ENCODING) { + n.get_type().tcast()->get_encoding() == + DYND_PY_ENCODING) { // If it's already a unicode string, pass-through n_str = n; } else { @@ -130,7 +129,7 @@ PyObject *pydynd::array_nonzero(const dynd::nd::array& n) case string_kind: { // Follow Python, return True if the string is nonempty, False otherwise nd::array n_eval = n.eval(); - const base_string_type *bsd = static_cast(n_eval.get_type().extended()); + const base_string_type *bsd = n_eval.get_type().tcast(); const char *begin = NULL, *end = NULL; bsd->get_string_range(&begin, &end, n_eval.get_ndo_meta(), n_eval.get_readonly_originptr()); if (begin != end) { @@ -144,7 +143,7 @@ PyObject *pydynd::array_nonzero(const dynd::nd::array& n) case bytes_kind: { // Return True if there is a non-zero byte, False otherwise nd::array n_eval = n.eval(); - const base_bytes_type *bbd = static_cast(n_eval.get_type().extended()); + const base_bytes_type *bbd = n_eval.get_type().tcast(); const char *begin = NULL, *end = NULL; bbd->get_bytes_range(&begin, &end, n_eval.get_ndo_meta(), n_eval.get_readonly_originptr()); while (begin != end) { @@ -547,7 +546,7 @@ bool pydynd::array_contains(const dynd::nd::array& n, PyObject *x) const char *metadata, *data; if (n.get_type().get_kind() == uniform_dim_kind) { dt = n.get_type(); - budd = static_cast(dt.extended()); + budd = dt.tcast(); metadata = n.get_ndo_meta(); data = n.get_readonly_originptr(); } else { @@ -556,7 +555,7 @@ bool pydynd::array_contains(const dynd::nd::array& n, PyObject *x) throw runtime_error("internal error in array_contains: expected uniform_dim kind after eval() call"); } dt = tmp.get_type(); - budd = static_cast(dt.extended()); + budd = dt.tcast(); metadata = tmp.get_ndo_meta(); data = tmp.get_readonly_originptr(); } @@ -738,7 +737,7 @@ dynd::nd::array pydynd::nd_fields(const nd::array& n, PyObject *field_list) ss << fdt; throw runtime_error(ss.str()); } - const base_struct_type *bsd = static_cast(fdt.extended()); + const base_struct_type *bsd = fdt.tcast(); const ndt::type *field_types = bsd->get_field_types(); if (selected_fields.empty()) { @@ -764,7 +763,7 @@ dynd::nd::array pydynd::nd_fields(const nd::array& n, PyObject *field_list) selected_ndt_types.empty() ? NULL : &selected_ndt_types[0], selected_fields.empty() ? NULL : &selected_fields[0]); ndt::type result_tp = n.get_type().with_replaced_dtype(rudt); - const base_struct_type *rudt_bsd = static_cast(rudt.extended()); + const base_struct_type *rudt_bsd = rudt.tcast(); // Allocate the new memory block. size_t metadata_size = result_tp.get_metadata_size(); @@ -791,8 +790,7 @@ dynd::nd::array pydynd::nd_fields(const nd::array& n, PyObject *field_list) if (tmp_dt.get_kind() != uniform_dim_kind) { throw runtime_error("nd.fields doesn't support dimensions with pointers yet"); } - const base_uniform_dim_type *budd = static_cast( - tmp_dt.extended()); + const base_uniform_dim_type *budd = tmp_dt.tcast(); size_t offset = budd->metadata_copy_construct_onedim(dst_metadata, src_metadata, n.get_memblock().get()); dst_metadata += offset; diff --git a/src/gfunc_callable_functions.cpp b/src/gfunc_callable_functions.cpp index 94c4ef9c..805c1d6e 100644 --- a/src/gfunc_callable_functions.cpp +++ b/src/gfunc_callable_functions.cpp @@ -236,7 +236,7 @@ PyObject *pydynd::call_gfunc_callable(const std::string& funcname, const dynd::g { const ndt::type& pdt = c.get_parameters_type(); nd::array params = nd::empty(pdt); - const cstruct_type *fsdt = static_cast(pdt.extended()); + const cstruct_type *fsdt = pdt.tcast(); if (fsdt->get_field_count() != 1) { stringstream ss; ss << "incorrect number of arguments for dynd callable \"" << funcname << "\" with parameters " << pdt; @@ -257,7 +257,7 @@ nd::array pydynd::call_gfunc_callable(const std::string& funcname, const dynd::g { const ndt::type& pdt = c.get_parameters_type(); nd::array params = nd::empty(pdt); - const cstruct_type *fsdt = static_cast(pdt.extended()); + const cstruct_type *fsdt = pdt.tcast(); if (fsdt->get_field_count() != 1) { stringstream ss; ss << "not enough arguments for dynd callable \"" << funcname << "\" with parameters " << pdt; @@ -278,7 +278,7 @@ static void fill_thiscall_parameters_array(const string& funcname, const gfunc:: nd::array& out_params, vector& out_storage) { const ndt::type& pdt = c.get_parameters_type(); - const cstruct_type *fsdt = static_cast(pdt.extended()); + const cstruct_type *fsdt = pdt.tcast(); size_t param_count = fsdt->get_field_count() - 1, args_count = PyTuple_GET_SIZE(args); if (args_count > param_count) { stringstream ss; @@ -408,7 +408,7 @@ PyObject *pydynd::array_callable_call(const array_callable_wrapper& ncw, PyObjec const ndt::type& pdt = ncw.c.get_parameters_type(); vector storage; nd::array params = nd::empty(pdt); - const cstruct_type *fsdt = static_cast(pdt.extended()); + const cstruct_type *fsdt = pdt.tcast(); // Set the 'self' parameter value set_single_parameter(ncw.funcname, fsdt->get_field_names()[0], fsdt->get_field_types()[0], params.get_ndo_meta() + fsdt->get_metadata_offsets()[0], @@ -439,7 +439,7 @@ static PyObject *ndt_type_callable_call(const std::string& funcname, const gfunc const ndt::type& pdt = c.get_parameters_type(); vector storage; nd::array params = nd::empty(pdt); - const cstruct_type *fsdt = static_cast(pdt.extended()); + const cstruct_type *fsdt = pdt.tcast(); // Set the 'self' parameter value set_single_parameter(funcname, fsdt->get_field_names()[0], fsdt->get_field_types()[0], params.get_ndo_meta() + fsdt->get_metadata_offsets()[0], diff --git a/src/numpy_interop.cpp b/src/numpy_interop.cpp index cc16cf6d..29e94119 100644 --- a/src/numpy_interop.cpp +++ b/src/numpy_interop.cpp @@ -284,7 +284,7 @@ void pydynd::fill_metadata_from_numpy_dtype(const ndt::type& dt, PyArray_Descr * // In DyND, the struct offsets are part of the metadata instead of the dtype. // That's why we have to populate them here. PyObject *d_names = d->names; - const struct_type *sdt = static_cast(dt.extended()); + const struct_type *sdt = dt.tcast(); const ndt::type *fields = sdt->get_field_types(); const size_t *metadata_offsets = sdt->get_metadata_offsets(); size_t field_count = sdt->get_field_count(); @@ -325,7 +325,7 @@ void pydynd::fill_metadata_from_numpy_dtype(const ndt::type& dt, PyArray_Descr * md[i].size = pyobject_as_index(PyTuple_GET_ITEM(adescr->shape, i)); md[i].stride = stride; stride *= md[i].size; - el = static_cast(el.extended())->get_element_type(); + el = el.tcast()->get_element_type(); } metadata += ndim * sizeof(strided_dim_type_metadata); } else { @@ -333,7 +333,7 @@ void pydynd::fill_metadata_from_numpy_dtype(const ndt::type& dt, PyArray_Descr * metadata += sizeof(strided_dim_type_metadata); md->size = pyobject_as_index(adescr->shape); md->stride = adescr->base->elsize; - el = static_cast(dt.extended())->get_element_type(); + el = dt.tcast()->get_element_type(); } // Fill the metadata for the array element, if necessary if (!el.is_builtin()) { @@ -377,7 +377,7 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp) case complex_float64_type_id: return PyArray_DescrFromType(NPY_CDOUBLE); case fixedstring_type_id: { - const fixedstring_type *ftp = static_cast(tp.extended()); + const fixedstring_type *ftp = tp.tcast(); PyArray_Descr *result; switch (ftp->get_encoding()) { case string_encoding_ascii: @@ -395,7 +395,7 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp) } /* case tuple_type_id: { - const tuple_type *ttp = static_cast(tp.extended()); + const tuple_type *ttp = tp.tcast(); const vector& fields = ttp->get_fields(); size_t num_fields = fields.size(); const vector& offsets = ttp->get_offsets(); @@ -434,7 +434,7 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp) } */ case cstruct_type_id: { - const cstruct_type *ttp = static_cast(tp.extended()); + const cstruct_type *ttp = tp.tcast(); const ndt::type *field_types = ttp->get_field_types(); const string *field_names = ttp->get_field_names(); const vector& offsets = ttp->get_data_offsets_vector(); @@ -492,7 +492,7 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp) ndt::type child_tp = tp; vector shape; do { - const cfixed_dim_type *ttp = static_cast(child_tp.extended()); + const cfixed_dim_type *ttp = child_tp.tcast(); shape.push_back(ttp->get_fixed_dim_size()); if (child_tp.get_data_size() != ttp->get_element_type().get_data_size() * shape.back()) { stringstream ss; @@ -548,7 +548,7 @@ PyArray_Descr *pydynd::numpy_dtype_from_ndt_type(const dynd::ndt::type& tp, cons ss << "Can only convert dynd type " << tp << " into a numpy dtype with array metadata"; throw dynd::type_error(ss.str()); } - const struct_type *stp = static_cast(tp.extended()); + const struct_type *stp = tp.tcast(); const ndt::type *field_types = stp->get_field_types(); const string *field_names = stp->get_field_names(); const size_t *metadata_offsets = stp->get_metadata_offsets(); @@ -903,7 +903,7 @@ char pydynd::numpy_kindchar_of(const dynd::ndt::type& d) return 'c'; case string_kind: if (d.get_type_id() == fixedstring_type_id) { - const base_string_type *esd = static_cast(d.extended()); + const base_string_type *esd = d.tcast(); switch (esd->get_encoding()) { case string_encoding_ascii: return 'S'; diff --git a/src/type_functions.cpp b/src/type_functions.cpp index 11017b9b..4fde8aec 100644 --- a/src/type_functions.cpp +++ b/src/type_functions.cpp @@ -74,14 +74,14 @@ std::string pydynd::ndt_type_repr(const dynd::ndt::type& d) ss << "ndt.date"; break; case time_type_id: - if (static_cast(d.extended())->get_timezone() == tz_abstract) { + if (d.tcast()->get_timezone() == tz_abstract) { ss << "ndt.time"; } else { ss << "ndt.type('" << d << "')"; } break; case datetime_type_id: - if (static_cast(d.extended())->get_timezone() == tz_abstract) { + if (d.tcast()->get_timezone() == tz_abstract) { ss << "ndt.datetime"; } else { ss << "ndt.type('" << d << "')"; @@ -91,15 +91,15 @@ std::string pydynd::ndt_type_repr(const dynd::ndt::type& d) ss << "ndt.json"; break; case bytes_type_id: - if (static_cast(d.extended())->get_target_alignment() == 1) { + if (d.tcast()->get_target_alignment() == 1) { ss << "ndt.bytes"; } else { ss << "ndt.type('" << d << "')"; } break; case string_type_id: - if (static_cast( - d.extended())->get_encoding() == string_encoding_utf_8) { + if (d.tcast()->get_encoding() == + string_encoding_utf_8) { ss << "ndt.string"; } else { ss << "ndt.type('" << d << "')"; From e414491a8ad726f832d9e11f3a1e9c12c20b97c3 Mon Sep 17 00:00:00 2001 From: Mark Wiebe Date: Sun, 20 Apr 2014 17:29:04 -0700 Subject: [PATCH 4/6] Update to reflect new fixed[N] type --- dynd/_lowlevel/type_id.py | 37 +++++++++++++++++++------------------ dynd/tests/test_lowlevel.py | 2 ++ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/dynd/_lowlevel/type_id.py b/dynd/_lowlevel/type_id.py index 0fedeb84..277e263c 100644 --- a/dynd/_lowlevel/type_id.py +++ b/dynd/_lowlevel/type_id.py @@ -51,23 +51,24 @@ BUSDATE = 30 JSON = 31 STRIDED_DIM = 32 -CFIXED_DIM = 33 -OFFSET_DIM = 34 -VAR_DIM = 35 -STRUCT = 36 -CSTRUCT = 37 -TUPLE = 38 -CTUPLE = 39 -NDOBJECT = 40 -CONVERT = 41 -BYTESWAP = 42 -VIEW = 43 -CUDA_HOST = 44 -CUDA_DEVICE = 45 -PROPERTY = 46 -EXPR = 47 -UNARY_EXPR = 48 -GROUPBY = 49 -TYPE = 50 +FIXED_DIM = 33 +CFIXED_DIM = 34 +OFFSET_DIM = 35 +VAR_DIM = 36 +STRUCT = 37 +CSTRUCT = 38 +TUPLE = 39 +CTUPLE = 40 +NDOBJECT = 41 +CONVERT = 42 +BYTESWAP = 43 +VIEW = 44 +CUDA_HOST = 45 +CUDA_DEVICE = 46 +PROPERTY = 47 +EXPR = 48 +UNARY_EXPR = 49 +GROUPBY = 50 +TYPE = 51 BUILTIN_TYPE_ID_COUNT = 19 diff --git a/dynd/tests/test_lowlevel.py b/dynd/tests/test_lowlevel.py index 2f7ce5c5..01d79dbc 100644 --- a/dynd/tests/test_lowlevel.py +++ b/dynd/tests/test_lowlevel.py @@ -97,6 +97,8 @@ def test_type_id(self): # Uniform arrays self.assertEqual(self.type_id_of(ndt.type('cfixed[3] * int32')), _lowlevel.type_id.CFIXED_DIM) + self.assertEqual(self.type_id_of(ndt.type('fixed[3] * int32')), + _lowlevel.type_id.FIXED_DIM) self.assertEqual(self.type_id_of(ndt.type('strided * int32')), _lowlevel.type_id.STRIDED_DIM) self.assertEqual(self.type_id_of(ndt.type('var * int32')), From 1ca7b432038c4de8459606a9c5bb710281e14fc7 Mon Sep 17 00:00:00 2001 From: Mark Wiebe Date: Mon, 21 Apr 2014 12:58:45 -0700 Subject: [PATCH 5/6] Update the code/tests to pass with the libdynd changes --- dynd/ndt/__init__.py | 2 +- dynd/tests/test_array_construct.py | 15 +++++++---- dynd/tests/test_array_getitem.py | 12 ++++----- dynd/tests/test_dtype.py | 2 +- dynd/tests/test_dtype_datashape.py | 2 +- dynd/tests/test_lowlevel.py | 8 +++--- dynd/tests/test_nd_fields.py | 8 +++--- include/ndt_type.pxd | 1 + include/type_functions.hpp | 1 + src/_pydynd.pyx | 40 +++++++++++++++++++++++----- src/array_assign_from_py.cpp | 42 ++++++++++++++++++++++++------ src/type_functions.cpp | 14 ++++++---- 12 files changed, 105 insertions(+), 42 deletions(-) diff --git a/dynd/ndt/__init__.py b/dynd/ndt/__init__.py index 9173c8e7..2427136f 100644 --- a/dynd/ndt/__init__.py +++ b/dynd/ndt/__init__.py @@ -5,7 +5,7 @@ make_view, \ make_unaligned, make_fixedstring, make_string, \ make_pointer, make_struct, make_cstruct, \ - make_strided_dim, make_cfixed_dim, make_var_dim, \ + make_strided_dim, make_fixed_dim, make_cfixed_dim, make_var_dim, \ make_categorical, replace_dtype, extract_dtype, \ factor_categorical, make_bytes, make_property, \ make_reversed_property, cuda_support diff --git a/dynd/tests/test_array_construct.py b/dynd/tests/test_array_construct.py index 63a055b4..1656ac52 100644 --- a/dynd/tests/test_array_construct.py +++ b/dynd/tests/test_array_construct.py @@ -49,12 +49,17 @@ def test_empty(self): # Constructor from type with fixed dimension a = nd.empty('3 * int32') self.assertEqual(a.access_flags, 'readwrite') + self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) + self.assertEqual(a.shape, (3,)) + # Constructor from type with cfixed dimension + a = nd.empty('cfixed[3] * int32') + self.assertEqual(a.access_flags, 'readwrite') self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) # Constructor from type with fixed dimension, accesskwarg a = nd.empty('3 * int32', access='rw') self.assertEqual(a.access_flags, 'readwrite') - self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) # Can't create with access as immutable self.assertRaises(ValueError, nd.empty, '3 * int32', access='immutable') @@ -91,7 +96,7 @@ def check_constructor(self, cons, value): # Constructor from type with fixed dimension a = cons('3 * int32') self.assertEqual(a.access_flags, 'immutable') - self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) self.assertEqual(nd.as_py(a), [value]*3) # Constructor from shape as single integer @@ -139,7 +144,7 @@ def check_constructor_readwrite(self, cons, value): # Constructor from type with fixed dimension a = cons('3 * int32', access='rw') self.assertEqual(a.access_flags, 'readwrite') - self.assertEqual(nd.type_of(a), ndt.make_cfixed_dim(3, ndt.int32)) + self.assertEqual(nd.type_of(a), ndt.make_fixed_dim(3, ndt.int32)) self.assertEqual(a.shape, (3,)) self.assertEqual(nd.as_py(a), [value]*3) # Constructor from shape as single integer @@ -731,8 +736,8 @@ def test_simple_fromiter_medsize(self): def test_ragged_fromiter(self): # Strided array of var from list of iterators a = nd.array([(1+x for x in range(3)), (5*x - 10 for x in range(5)), - [2, 10]], type='M * var * int32') - self.assertEqual(nd.type_of(a), ndt.type('M * var * int32')) + [2, 10]], type='strided * var * int32') + self.assertEqual(nd.type_of(a), ndt.type('strided * var * int32')) self.assertEqual(nd.as_py(a), [[1,2,3], [-10, -5, 0, 5, 10], [2, 10]]) # Var array of var from iterator of iterators diff --git a/dynd/tests/test_array_getitem.py b/dynd/tests/test_array_getitem.py index 86a105f9..db69d3cf 100644 --- a/dynd/tests/test_array_getitem.py +++ b/dynd/tests/test_array_getitem.py @@ -7,10 +7,10 @@ class TestArrayGetItem(unittest.TestCase): def test_strided_dim(self): a = nd.empty(100, ndt.int32) a[...] = nd.range(100) - self.assertEqual(nd.type_of(a), ndt.type('A * int32')) - self.assertEqual(nd.type_of(a[...]), ndt.type('A * int32')) + self.assertEqual(nd.type_of(a), ndt.type('strided * int32')) + self.assertEqual(nd.type_of(a[...]), ndt.type('strided * int32')) self.assertEqual(nd.type_of(a[0]), ndt.int32) - self.assertEqual(nd.type_of(a[0:1]), ndt.type('A * int32')) + self.assertEqual(nd.type_of(a[0:1]), ndt.type('strided * int32')) self.assertEqual(nd.as_py(a[0]), 0) self.assertEqual(nd.as_py(a[99]), 99) self.assertEqual(nd.as_py(a[-1]), 99) @@ -26,7 +26,7 @@ def test_fixed_dim(self): self.assertEqual(nd.type_of(a), ndt.type('100 * int32')) self.assertEqual(nd.type_of(a[...]), ndt.type('100 * int32')) self.assertEqual(nd.type_of(a[0]), ndt.int32) - self.assertEqual(nd.type_of(a[0:1]), ndt.type('A * int32')) + self.assertEqual(nd.type_of(a[0:1]), ndt.type('strided * int32')) self.assertEqual(nd.as_py(a[0]), 0) self.assertEqual(nd.as_py(a[99]), 99) self.assertEqual(nd.as_py(a[-1]), 99) @@ -41,9 +41,9 @@ def test_var_dim(self): a[...] = nd.range(100) self.assertEqual(nd.type_of(a), ndt.type('var * int32')) self.assertEqual(nd.type_of(a[...]), ndt.type('var * int32')) - self.assertEqual(nd.type_of(a[:]), ndt.type('M * int32')) + self.assertEqual(nd.type_of(a[:]), ndt.type('strided * int32')) self.assertEqual(nd.type_of(a[0]), ndt.int32) - self.assertEqual(nd.type_of(a[0:1]), ndt.type('A * int32')) + self.assertEqual(nd.type_of(a[0:1]), ndt.type('strided * int32')) self.assertEqual(nd.as_py(a[0]), 0) self.assertEqual(nd.as_py(a[99]), 99) self.assertEqual(nd.as_py(a[-1]), 99) diff --git a/dynd/tests/test_dtype.py b/dynd/tests/test_dtype.py index 74b45323..654568c0 100644 --- a/dynd/tests/test_dtype.py +++ b/dynd/tests/test_dtype.py @@ -213,7 +213,7 @@ def test_type_shape(self): # The shape attribute of ndt.type tp = ndt.type('3 * 4 * int32') self.assertEqual(tp.shape, (3, 4)) - tp = ndt.type('M * 3 * var * int32') + tp = ndt.type('strided * 3 * var * int32') self.assertEqual(tp.shape, (-1, 3, -1)) tp = ndt.type('var * 3 * 2 * int32') self.assertEqual(tp.shape, (-1, 3, 2)) diff --git a/dynd/tests/test_dtype_datashape.py b/dynd/tests/test_dtype_datashape.py index 0fecd030..7e509fb4 100644 --- a/dynd/tests/test_dtype_datashape.py +++ b/dynd/tests/test_dtype_datashape.py @@ -43,7 +43,7 @@ def test_cfixed_array(self): def test_struct(self): # Tests of cstruct datashape - dt = ndt.type('c{x: 3 * int32, y: string}') + dt = ndt.type('c{x: cfixed[3] * int32, y: string}') self.assertEqual(dt.type_id, 'cstruct') self.assertEqual(nd.as_py(dt.field_names), ['x', 'y']) # Tests of struct datashape diff --git a/dynd/tests/test_lowlevel.py b/dynd/tests/test_lowlevel.py index 01d79dbc..5a9d4f36 100644 --- a/dynd/tests/test_lowlevel.py +++ b/dynd/tests/test_lowlevel.py @@ -117,16 +117,16 @@ def test_array_from_ptr(self): a[1] = 6 a[2] = 9 # Readwrite version - b = _lowlevel.array_from_ptr(ndt.type('3 * int32'), ctypes.addressof(a), - a, 'readwrite') + b = _lowlevel.array_from_ptr(ndt.type('cfixed[3] * int32'), + ctypes.addressof(a), a, 'readwrite') self.assertEqual(_lowlevel.data_address_of(b), ctypes.addressof(a)) self.assertEqual(nd.dshape_of(b), '3 * int32') self.assertEqual(nd.as_py(b), [3, 6, 9]) b[1] = 10 self.assertEqual(a[1], 10) # Readonly version - b = _lowlevel.array_from_ptr(ndt.type('3 * int32'), ctypes.addressof(a), - a, 'readonly') + b = _lowlevel.array_from_ptr(ndt.type('cfixed[3] * int32'), + ctypes.addressof(a), a, 'readonly') self.assertEqual(nd.as_py(b), [3, 10, 9]) def assign_to(b): b[1] = 100 diff --git a/dynd/tests/test_nd_fields.py b/dynd/tests/test_nd_fields.py index e127c3f9..515f8b00 100644 --- a/dynd/tests/test_nd_fields.py +++ b/dynd/tests/test_nd_fields.py @@ -51,14 +51,14 @@ def test_fixed_var(self): type='3 * var * {x: int32, y: int32, z: string, w: string}') # Selecting a single field b = nd.fields(a, 'x') - self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.int32], ['x'])))) self.assertEqual(nd.as_py(b.x), nd.as_py(a.x)) # Selecting two fields b = nd.fields(a, 'z', 'y') - self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.string, ndt.int32], ['z', 'y'])))) @@ -66,7 +66,7 @@ def test_fixed_var(self): self.assertEqual(nd.as_py(b.y), nd.as_py(a.y)) # Selecting three fields b = nd.fields(a, 'w', 'y', 'z') - self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.string, ndt.int32, ndt.string], ['w', 'y', 'z'])))) @@ -75,7 +75,7 @@ def test_fixed_var(self): self.assertEqual(nd.as_py(b.z), nd.as_py(a.z)) # Reordering all four fields b = nd.fields(a, 'w', 'y', 'x', 'z') - self.assertEqual(nd.type_of(b), ndt.make_cfixed_dim(3, + self.assertEqual(nd.type_of(b), ndt.make_fixed_dim(3, ndt.make_var_dim(ndt.make_struct( [ndt.string, ndt.int32, ndt.int32, ndt.string], ['w', 'y', 'x', 'z'])))) diff --git a/include/ndt_type.pxd b/include/ndt_type.pxd index 9951b453..5d99bb1b 100644 --- a/include/ndt_type.pxd +++ b/include/ndt_type.pxd @@ -135,6 +135,7 @@ cdef extern from "type_functions.hpp" namespace "pydynd": ndt_type dynd_make_pointer_type(ndt_type&) except +translate_exception ndt_type dynd_make_struct_type(object, object) except +translate_exception ndt_type dynd_make_cstruct_type(object, object) except +translate_exception + ndt_type dynd_make_fixed_dim_type(object, ndt_type&) except +translate_exception ndt_type dynd_make_cfixed_dim_type(object, ndt_type&, object) except +translate_exception cdef extern from "numpy_interop.hpp" namespace "pydynd": diff --git a/include/type_functions.hpp b/include/type_functions.hpp index 82115606..30f0edee 100644 --- a/include/type_functions.hpp +++ b/include/type_functions.hpp @@ -114,6 +114,7 @@ dynd::ndt::type dynd_make_pointer_type(const dynd::ndt::type& target_tp); dynd::ndt::type dynd_make_struct_type(PyObject *field_types, PyObject *field_names); dynd::ndt::type dynd_make_cstruct_type(PyObject *field_types, PyObject *field_names); +dynd::ndt::type dynd_make_fixed_dim_type(PyObject *shape, const dynd::ndt::type& element_tp); dynd::ndt::type dynd_make_cfixed_dim_type(PyObject *shape, const dynd::ndt::type& element_tp, PyObject *axis_perm); /** diff --git a/src/_pydynd.pyx b/src/_pydynd.pyx index e8f2a315..873d6d47 100644 --- a/src/_pydynd.pyx +++ b/src/_pydynd.pyx @@ -680,11 +680,37 @@ def make_strided_dim(element_tp, ndim=None): SET(result.v, dynd_make_strided_dim_type(GET(w_type(element_tp).v), int(ndim))) return result -def make_fixed_dim(shape, element_tp, axis_perm=None): +def make_fixed_dim(shape, element_tp): """ - ndt.make_fixed_dim(shape, element_tp, axis_perm=None) + ndt.make_fixed_dim(shape, element_tp) - Constructs a fixed_dim type of the given shape and axis permutation + Constructs a fixed_dim type of the given shape. + + Parameters + ---------- + shape : tuple of int + The multi-dimensional shape of the resulting fixed array type. + element_tp : dynd type + The type of each element in the resulting array type. + + Examples + -------- + >>> from dynd import nd, ndt + + >>> ndt.make_fixed_dim(5, ndt.int32) + ndt.type('fixed_dim<5, int32>') + >>> ndt.make_fixed_dim((3,5), ndt.int32) + ndt.type('fixed_dim<3, fixed_dim<5, int32>>') + """ + cdef w_type result = w_type() + SET(result.v, dynd_make_fixed_dim_type(shape, GET(w_type(element_tp).v))) + return result + +def make_cfixed_dim(shape, element_tp, axis_perm=None): + """ + ndt.make_cfixed_dim(shape, element_tp, axis_perm=None) + + Constructs a cfixed_dim type of the given shape and axis permutation (default C order). Parameters @@ -703,15 +729,15 @@ def make_fixed_dim(shape, element_tp, axis_perm=None): -------- >>> from dynd import nd, ndt - >>> ndt.make_fixed_dim(5, ndt.int32) + >>> ndt.make_cfixed_dim(5, ndt.int32) ndt.type('fixed_dim<5, int32>') - >>> ndt.make_fixed_dim((3,5), ndt.int32) + >>> ndt.make_cfixed_dim((3,5), ndt.int32) ndt.type('fixed_dim<3, fixed_dim<5, int32>>') - >>> ndt.make_fixed_dim((3,5), ndt.int32, axis_perm=(0,1)) + >>> ndt.make_cfixed_dim((3,5), ndt.int32, axis_perm=(0,1)) ndt.type('fixed_dim<3, stride=4, fixed_dim<5, stride=12, int32>>') """ cdef w_type result = w_type() - SET(result.v, dynd_make_fixed_dim_type(shape, GET(w_type(element_tp).v), axis_perm)) + SET(result.v, dynd_make_cfixed_dim_type(shape, GET(w_type(element_tp).v), axis_perm)) return result def make_cstruct(field_types, field_names): diff --git a/src/array_assign_from_py.cpp b/src/array_assign_from_py.cpp index 729c67cd..6fb19883 100644 --- a/src/array_assign_from_py.cpp +++ b/src/array_assign_from_py.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -461,11 +462,24 @@ static void array_assign_from_pyseq(const dynd::ndt::type& dt, data, fdd->get_fixed_stride(), fdd->get_fixed_dim_size(), seq, seqsize); break; } + case fixed_dim_type_id: { + const fixed_dim_type *fdd = dt.tcast(); + const fixed_dim_type_metadata *md = + reinterpret_cast(metadata); + array_assign_strided_from_pyseq( + fdd->get_element_type(), + metadata + sizeof(fixed_dim_type_metadata), data, md->stride, + fdd->get_fixed_dim_size(), seq, seqsize); + break; + } case strided_dim_type_id: { - const ndt::type& element_dt = dt.tcast()->get_element_type(); - const strided_dim_type_metadata *md = reinterpret_cast(metadata); - array_assign_strided_from_pyseq(element_dt, metadata + sizeof(strided_dim_type_metadata), - data, md->stride, md->size, seq, seqsize); + const ndt::type &element_dt = + dt.tcast()->get_element_type(); + const strided_dim_type_metadata *md = + reinterpret_cast(metadata); + array_assign_strided_from_pyseq( + element_dt, metadata + sizeof(strided_dim_type_metadata), data, + md->stride, md->size, seq, seqsize); break; } case var_dim_type_id: { @@ -539,14 +553,26 @@ static void array_assign_from_pyiter(const dynd::ndt::type& dt, case cfixed_dim_type_id: { const cfixed_dim_type *fdd = dt.tcast(); array_assign_strided_from_pyiter(fdd->get_element_type(), metadata, - data, fdd->get_fixed_stride(), fdd->get_fixed_dim_size(), iter); + data, fdd->get_fixed_stride(), + fdd->get_fixed_dim_size(), iter); + break; + } + case fixed_dim_type_id: { + const fixed_dim_type *fdd = dt.tcast(); + const fixed_dim_type_metadata *md = reinterpret_cast(metadata); + array_assign_strided_from_pyiter( + fdd->get_element_type(), + metadata + sizeof(fixed_dim_type_metadata), data, md->stride, + fdd->get_fixed_dim_size(), iter); break; } case strided_dim_type_id: { - const ndt::type& element_dt = dt.tcast()->get_element_type(); + const ndt::type &element_dt = + dt.tcast()->get_element_type(); const strided_dim_type_metadata *md = reinterpret_cast(metadata); - array_assign_strided_from_pyiter(element_dt, metadata + sizeof(strided_dim_type_metadata), - data, md->stride, md->size, iter); + array_assign_strided_from_pyiter( + element_dt, metadata + sizeof(strided_dim_type_metadata), data, + md->stride, md->size, iter); break; } case var_dim_type_id: { diff --git a/src/type_functions.cpp b/src/type_functions.cpp index 4fde8aec..e42234dd 100644 --- a/src/type_functions.cpp +++ b/src/type_functions.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -370,14 +371,17 @@ dynd::ndt::type pydynd::dynd_make_cstruct_type(PyObject *field_types, PyObject * field_names_vec.empty() ? NULL : &field_names_vec[0]); } +dynd::ndt::type pydynd::dynd_make_fixed_dim_type(PyObject *shape, const dynd::ndt::type& element_tp) +{ + vector shape_vec; + pyobject_as_vector_intp(shape, shape_vec, true); + return ndt::make_fixed_dim(shape_vec.size(), &shape_vec[0], element_tp); +} + dynd::ndt::type pydynd::dynd_make_cfixed_dim_type(PyObject *shape, const ndt::type& element_tp, PyObject *axis_perm) { vector shape_vec; - if (PySequence_Check(shape)) { - pyobject_as_vector_intp(shape, shape_vec, false); - } else { - shape_vec.push_back(pyobject_as_index(shape)); - } + pyobject_as_vector_intp(shape, shape_vec, true); if (axis_perm != Py_None) { vector axis_perm_vec; From 509eb8db82ef536efb68367ea33d7770c7080f76 Mon Sep 17 00:00:00 2001 From: Mark Wiebe Date: Mon, 21 Apr 2014 14:17:04 -0700 Subject: [PATCH 6/6] Fixes for issues exposed by the blaze tests --- dynd/tests/test_numpy_interop.py | 28 ++++++++++++++++++ include/ndt_type.pxd | 1 + src/_pydynd.pyx | 10 +++++++ src/array_as_numpy.cpp | 51 ++++++++++++++++++++++++++++---- 4 files changed, 84 insertions(+), 6 deletions(-) diff --git a/dynd/tests/test_numpy_interop.py b/dynd/tests/test_numpy_interop.py index dbcd4726..713ca0d1 100644 --- a/dynd/tests/test_numpy_interop.py +++ b/dynd/tests/test_numpy_interop.py @@ -345,6 +345,22 @@ def assign_to(x,y): self.assertRaises(RuntimeError, nd.view, a, access='rw') class TestAsNumpy(unittest.TestCase): + def test_struct_as_numpy(self): + # Aligned cstruct + a = nd.array([[1, 2], [3, 4]], dtype='{x : int32, y: int64}') + b = nd.as_numpy(a) + self.assertEqual(b.dtype, + np.dtype([('x', np.int32), ('y', np.int64)], align=True)) + self.assertEqual(nd.as_py(a.x), b['x'].tolist()) + self.assertEqual(nd.as_py(a.y), b['y'].tolist()) + # Unaligned cstruct + a = nd.array([[1, 2], [3, 4]], + dtype='{x : unaligned[int32], y: unaligned[int64]}') + b = nd.as_numpy(a) + self.assertEqual(b.dtype, np.dtype([('x', np.int32), ('y', np.int64)])) + self.assertEqual(nd.as_py(a.x), b['x'].tolist()) + self.assertEqual(nd.as_py(a.y), b['y'].tolist()) + def test_cstruct_as_numpy(self): # Aligned cstruct a = nd.array([[1, 2], [3, 4]], dtype='c{x : int32, y: int64}') @@ -377,6 +393,18 @@ def test_cstruct_via_pep3118(self): self.assertEqual(nd.as_py(a.x), b['x'].tolist()) self.assertEqual(nd.as_py(a.y), b['y'].tolist()) + def test_fixed_dim(self): + a = nd.array([1, 3, 5], type='3 * int32') + b = nd.as_numpy(a) + self.assertEqual(b.dtype, np.dtype('int32')) + self.assertEqual(b.tolist(), [1, 3, 5]) + + def test_fixed_dim_via_pep3118(self): + a = nd.array([1, 3, 5], type='3 * int32') + b = np.asarray(a) + self.assertEqual(b.dtype, np.dtype('int32')) + self.assertEqual(b.tolist(), [1, 3, 5]) + class TestNumpyScalarInterop(unittest.TestCase): def test_numpy_scalar_conversion_dtypes(self): self.assertEqual(nd.dtype_of(nd.array(np.bool_(True))), ndt.bool) diff --git a/include/ndt_type.pxd b/include/ndt_type.pxd index 5d99bb1b..8aa85924 100644 --- a/include/ndt_type.pxd +++ b/include/ndt_type.pxd @@ -69,6 +69,7 @@ cdef extern from "dynd/type.hpp" namespace "dynd::ndt": type_id_t type_id() type_kind_t get_kind() size_t get_data_size() + size_t get_default_data_size(intptr_t, intptr_t*) size_t get_data_alignment() size_t get_metadata_size() base_type* extended() diff --git a/src/_pydynd.pyx b/src/_pydynd.pyx index 873d6d47..65ca717f 100644 --- a/src/_pydynd.pyx +++ b/src/_pydynd.pyx @@ -173,6 +173,16 @@ cdef class w_type: else: return None + property default_data_size: + """ + tp.default_data_size + + The size, in bytes, of the data for a default-constructed + instance of this dynd type. + """ + def __get__(self): + return (GET(self.v)).get_default_data_size(0, 0) + property data_alignment: """ tp.data_alignment diff --git a/src/array_as_numpy.cpp b/src/array_as_numpy.cpp index d077369a..cbc2d233 100644 --- a/src/array_as_numpy.cpp +++ b/src/array_as_numpy.cpp @@ -16,6 +16,7 @@ #include "utility_functions.hpp" #include +#include #include #include #include @@ -122,22 +123,34 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, #endif } case strided_dim_type_id: + case fixed_dim_type_id: case cfixed_dim_type_id: { if (ndim > 0) { // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions - if (dt.get_type_id() == strided_dim_type_id) { + switch (dt.get_type_id()) { + case strided_dim_type_id: { const strided_dim_type *sad = dt.tcast(); make_numpy_dtype_for_copy(out_numpy_dtype, ndim - 1, sad->get_element_type(), metadata + sizeof(strided_dim_type_metadata)); - } else { + return; + } + case fixed_dim_type_id: { + const fixed_dim_type *fad = dt.tcast(); + make_numpy_dtype_for_copy(out_numpy_dtype, + ndim - 1, fad->get_element_type(), + metadata + sizeof(fixed_dim_type_metadata)); + return; + } + case cfixed_dim_type_id: { const cfixed_dim_type *fad = dt.tcast(); make_numpy_dtype_for_copy(out_numpy_dtype, ndim - 1, fad->get_element_type(), - metadata + sizeof(strided_dim_type_metadata)); + metadata); + return; + } } - return; } else { // If this isn't one of the array dimensions, it maps into // a numpy dtype with a shape @@ -158,6 +171,12 @@ static void make_numpy_dtype_for_copy(pyobject_ownref *out_numpy_dtype, dim_size = sad->get_dim_size(metadata, NULL); element_tp = sad->get_element_type(); metadata += sizeof(strided_dim_type_metadata); + } else if (dt.get_type_id() == fixed_dim_type_id) { + const fixed_dim_type *fad = + element_tp.tcast(); + dim_size = fad->get_fixed_dim_size(); + element_tp = fad->get_element_type(); + metadata += sizeof(fixed_dim_type_metadata); } else if (dt.get_type_id() == cfixed_dim_type_id) { const cfixed_dim_type *fad = element_tp.tcast(); @@ -372,6 +391,24 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir } break; } + case fixed_dim_type_id: { + const fixed_dim_type *fad = dt.tcast(); + if (ndim > 0) { + // If this is one of the array dimensions, it simply + // becomes one of the numpy ndarray dimensions + as_numpy_analysis(out_numpy_dtype, out_requires_copy, + ndim - 1, fad->get_element_type(), + metadata + sizeof(fixed_dim_type_metadata)); + return; + } else { + // If this isn't one of the array dimensions, it maps into + // a numpy dtype with a shape + out_numpy_dtype->clear(); + *out_requires_copy = true; + return; + } + break; + } case cfixed_dim_type_id: { const cfixed_dim_type *fad = dt.tcast(); if (ndim > 0) { @@ -481,13 +518,15 @@ static void as_numpy_analysis(pyobject_ownref *out_numpy_dtype, bool *out_requir PyList_SET_ITEM((PyObject *)offsets_obj, i, PyLong_FromSize_t(offsets[i])); } - pyobject_ownref itemsize_obj(PyLong_FromSize_t(dt.get_data_size())); pyobject_ownref dict_obj(PyDict_New()); PyDict_SetItemString(dict_obj, "names", names_obj); PyDict_SetItemString(dict_obj, "formats", formats_obj); PyDict_SetItemString(dict_obj, "offsets", offsets_obj); - PyDict_SetItemString(dict_obj, "itemsize", itemsize_obj); + if (dt.get_data_size() > 0) { + pyobject_ownref itemsize_obj(PyLong_FromSize_t(dt.get_data_size())); + PyDict_SetItemString(dict_obj, "itemsize", itemsize_obj); + } PyArray_Descr *result = NULL; if (!PyArray_DescrConverter(dict_obj, &result)) {