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..277e263c 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', @@ -52,21 +52,23 @@ JSON = 31 STRIDED_DIM = 32 FIXED_DIM = 33 -OFFSET_DIM = 34 -VAR_DIM = 35 -STRUCT = 36 -FIXEDSTRUCT = 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 +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/ndt/__init__.py b/dynd/ndt/__init__.py index 61322c66..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_fixed_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_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..1656ac52 100644 --- a/dynd/tests/test_array_construct.py +++ b/dynd/tests/test_array_construct.py @@ -51,6 +51,11 @@ def test_empty(self): 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') @@ -549,27 +554,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 @@ -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_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.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 d568c0b9..7e509fb4 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: 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 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..5a9d4f36 100644 --- a/dynd/tests/test_lowlevel.py +++ b/dynd/tests/test_lowlevel.py @@ -71,7 +71,14 @@ 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) + # 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)), @@ -88,7 +95,9 @@ 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')), + 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) @@ -108,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_numpy_interop.py b/dynd/tests/test_numpy_interop.py index 0bd7d8ea..713ca0d1 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 @@ -345,7 +345,7 @@ def assign_to(x,y): self.assertRaises(RuntimeError, nd.view, a, access='rw') class TestAsNumpy(unittest.TestCase): - def test_cstruct_as_numpy(self): + 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) @@ -361,9 +361,25 @@ def test_cstruct_as_numpy(self): 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}') + 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='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()) + self.assertEqual(nd.as_py(a.y), b['y'].tolist()) + 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,12 +387,24 @@ 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()) 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 715a4374..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() @@ -135,7 +136,8 @@ 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_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": 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..30f0edee 100644 --- a/include/type_functions.hpp +++ b/include/type_functions.hpp @@ -114,7 +114,8 @@ 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_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); /** * Implementation of __getitem__ for the wrapped dynd type object. diff --git a/src/_pydynd.pyx b/src/_pydynd.pyx index e8f2a315..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 @@ -680,11 +690,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) + + 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_fixed_dim(shape, element_tp, axis_perm=None) + ndt.make_cfixed_dim(shape, element_tp, axis_perm=None) - Constructs a fixed_dim type of the given shape and axis permutation + Constructs a cfixed_dim type of the given shape and axis permutation (default C order). Parameters @@ -703,15 +739,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_as_numpy.cpp b/src/array_as_numpy.cpp index e83154c9..cbc2d233 100644 --- a/src/array_as_numpy.cpp +++ b/src/array_as_numpy.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,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: @@ -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 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) { - const strided_dim_type *sad = static_cast(dt.extended()); + 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 { - const fixed_dim_type *fad = static_cast(dt.extended()); + 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(strided_dim_type_metadata)); + 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); + return; + } } - return; } else { // If this isn't one of the array dimensions, it maps into // a numpy dtype with a shape @@ -154,13 +167,19 @@ 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() == fixed_dim_type_id) { const fixed_dim_type *fad = - static_cast(element_tp.extended()); + 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(); dim_size = fad->get_fixed_dim_size(); element_tp = fad->get_element_type(); } else { @@ -196,7 +215,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 +304,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 +343,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 +363,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 +374,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 +392,25 @@ 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()); + 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) { // If this is one of the array dimensions, it simply // becomes one of the numpy ndarray dimensions @@ -389,9 +426,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 = + element_tp.tcast(); element_tp = fad->get_element_type(); if (fad->get_data_size() != element_tp.get_data_size() * dim_size) { @@ -444,7 +481,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); @@ -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)) { diff --git a/src/array_as_pep3118.cpp b/src/array_as_pep3118.cpp index e586954d..b29aacde 100644 --- a/src/array_as_pep3118.cpp +++ b/src/array_as_pep3118.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -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"; @@ -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 = 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) { @@ -143,14 +143,14 @@ 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; } 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; @@ -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 = 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 7f701372..6fb19883 100644 --- a/src/array_assign_from_py.cpp +++ b/src/array_assign_from_py.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -402,7 +403,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(); @@ -455,21 +456,34 @@ 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 = 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 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 = static_cast(dt.extended())->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: { - 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 +517,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); @@ -536,21 +550,33 @@ 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 = 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 = 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); + 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 +685,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 +772,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 91345e00..196de92e 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 @@ -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), @@ -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..9b220073 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 @@ -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 dccda4a1..12e1e850 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 @@ -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 4e239474..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()) { @@ -759,9 +758,12 @@ 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()); + const base_struct_type *rudt_bsd = rudt.tcast(); // Allocate the new memory block. size_t metadata_size = result_tp.get_metadata_size(); @@ -788,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/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/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 3a986e4c..29e94119 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); } } @@ -280,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(); @@ -321,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 { @@ -329,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()) { @@ -373,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: @@ -391,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(); @@ -430,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(); @@ -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 = 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; @@ -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)); @@ -544,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(); @@ -899,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 38bad123..e42234dd 100644 --- a/src/type_functions.cpp +++ b/src/type_functions.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -74,14 +75,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 +92,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 << "')"; @@ -339,7 +340,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,19 +359,29 @@ 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_fixed_dim_type(PyObject *shape, const dynd::ndt::type& element_tp) { 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); + 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; + pyobject_as_vector_intp(shape, shape_vec, true); if (axis_perm != Py_None) { vector axis_perm_vec; @@ -372,9 +392,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); } }