def dspace_type(space, impl, dtype=None): """Select the correct corresponding n-tuples space. Parameters ---------- space : `LinearSpace` Template space from which to infer an adequate data space. If it has a `LinearSpace.field` attribute, ``dtype`` must be consistent with it. impl : string Implementation backend for the data space dtype : `numpy.dtype`, optional Data type which the space is supposed to use. If ``None`` is given, the space type is purely determined from ``space`` and ``impl``. Otherwise, it must be compatible with the field of ``space``. Returns ------- stype : type Space type selected after the space's field, the backend and the data type """ spacetype_map = {RealNumbers: FN_IMPLS, ComplexNumbers: FN_IMPLS, type(None): NTUPLES_IMPLS} field_type = type(getattr(space, 'field', None)) if dtype is None: pass elif is_real_floating_dtype(dtype): if field_type is None or field_type == ComplexNumbers: raise TypeError('real floating data type {!r} requires space ' 'field to be of type RealNumbers, got {}' ''.format(dtype, field_type)) elif is_complex_floating_dtype(dtype): if field_type is None or field_type == RealNumbers: raise TypeError('complex floating data type {!r} requires space ' 'field to be of type ComplexNumbers, got {!r}' ''.format(dtype, field_type)) elif is_scalar_dtype(dtype): if field_type == ComplexNumbers: raise TypeError('non-floating data type {!r} requires space field ' 'to be of type RealNumbers, got {!r}' .format(dtype, field_type)) else: raise TypeError('non-scalar data type {!r} cannot be combined with ' 'a `LinearSpace`'.format(dtype)) stype = spacetype_map[field_type].get(impl, None) if stype is None: raise NotImplementedError('no corresponding data space available ' 'for space {!r} and implementation {!r}' ''.format(space, impl)) return stype
def test_resizing_op_adjoint(padding, fn_impl): pad_mode, pad_const = padding dtypes = [dt for dt in odl.FN_IMPLS[fn_impl].available_dtypes() if is_real_floating_dtype(dt)] for dtype in dtypes: space = odl.uniform_discr([0, -1], [1, 1], (4, 5), dtype=dtype, impl=fn_impl) res_space = odl.uniform_discr([0, -1.4], [1.5, 1.4], (6, 7), dtype=dtype, impl=fn_impl) res_op = odl.ResizingOperator(space, res_space, pad_mode=pad_mode, pad_const=pad_const) if pad_const != 0.0: with pytest.raises(NotImplementedError): res_op.adjoint return elem = noise_element(space) res_elem = noise_element(res_space) inner1 = res_op(elem).inner(res_elem) inner2 = elem.inner(res_op.adjoint(res_elem)) assert almost_equal(inner1, inner2, places=dtype_places(dtype))
def dspace_type(space, impl, dtype=None): """Select the correct corresponding n-tuples space. Parameters ---------- space : `object` The template space. If it has a ``field`` attribute, ``dtype`` must be consistent with it impl : {'numpy', 'cuda'} The backend for the data space dtype : `type`, optional Data type which the space is supposed to use. If `None`, the space type is purely determined from ``space`` and ``impl``. If given, it must be compatible with the field of ``space``. Non-floating types result in basic `Fn`-type spaces. Returns ------- stype : `type` Space type selected after the space's field, the backend and the data type """ impl_ = str(impl).lower() if impl_ not in ('numpy', 'cuda'): raise ValueError('implementation type {} not understood.' ''.format(impl)) if impl_ == 'cuda' and not CUDA_AVAILABLE: raise ValueError('CUDA implementation not available.') basic_map = {'numpy': Fn, 'cuda': CudaFn} spacetype_map = { 'numpy': {RealNumbers: Rn, ComplexNumbers: Cn, type(None): Ntuples}, 'cuda': {RealNumbers: CudaRn, ComplexNumbers: None, type(None): CudaNtuples} } field_type = type(getattr(space, 'field', None)) if dtype is None: stype = spacetype_map[impl_][field_type] elif is_real_floating_dtype(dtype): if field_type is None or field_type == ComplexNumbers: raise TypeError('real floating data type {!r} requires space ' 'field to be of type `RealNumbers`, got {}.' ''.format(dtype, field_type)) stype = spacetype_map[impl_][field_type] elif is_complex_floating_dtype(dtype): if field_type is None or field_type == RealNumbers: raise TypeError('complex floating data type {!r} requires space ' 'field to be of type `ComplexNumbers`, got {!r}.' ''.format(dtype, field_type)) stype = spacetype_map[impl_][field_type] elif is_scalar_dtype(dtype): if field_type == ComplexNumbers: raise TypeError('non-floating data type {!r} requires space field ' 'to be of type `RealNumbers`, got {!r}.' .format(dtype, field_type)) elif field_type == RealNumbers: stype = basic_map[impl_] else: stype = spacetype_map[impl_][field_type] elif field_type is None: # Only in this case are arbitrary types allowed stype = spacetype_map[impl_][field_type] else: raise TypeError('non-scalar data type {!r} cannot be combined with ' 'a `LinearSpace`.'.format(dtype)) if stype is None: raise NotImplementedError('no corresponding data space available ' 'for space {!r} and implementation {!r}.' ''.format(space, impl)) return stype
def test_is_real_floating_dtype(): for dtype in real_float_dtypes: assert is_real_floating_dtype(dtype)
def dspace_type(space, impl, dtype=None): """Select the correct corresponding n-tuples space. Parameters ---------- space : Template space from which to infer an adequate data space. If it has a `LinearSpace.field` attribute, ``dtype`` must be consistent with it. impl : {'numpy', 'cuda'} Implementation backend for the data space dtype : `type`, optional Data type which the space is supposed to use. If `None`, the space type is purely determined from ``space`` and ``impl``. If given, it must be compatible with the field of ``space``. Returns ------- stype : `type` Space type selected after the space's field, the backend and the data type """ impl, impl_in = str(impl).lower(), impl if impl not in ('numpy', 'cuda'): raise ValueError("`impl` '{}' not understood" ''.format(impl_in)) if impl == 'cuda' and not CUDA_AVAILABLE: raise ValueError("'cuda' implementation not available") basic_map = {'numpy': Fn, 'cuda': CudaFn} spacetype_map = { 'numpy': {RealNumbers: Fn, ComplexNumbers: Fn, type(None): Ntuples}, 'cuda': {RealNumbers: CudaFn, ComplexNumbers: None, type(None): CudaNtuples} } field_type = type(getattr(space, 'field', None)) if dtype is None: stype = spacetype_map[impl][field_type] elif is_real_floating_dtype(dtype): if field_type is None or field_type == ComplexNumbers: raise TypeError('real floating data type {!r} requires space ' 'field to be of type RealNumbers, got {}' ''.format(dtype, field_type)) stype = spacetype_map[impl][field_type] elif is_complex_floating_dtype(dtype): if field_type is None or field_type == RealNumbers: raise TypeError('complex floating data type {!r} requires space ' 'field to be of type ComplexNumbers, got {!r}' ''.format(dtype, field_type)) stype = spacetype_map[impl][field_type] elif is_scalar_dtype(dtype): if field_type == ComplexNumbers: raise TypeError('non-floating data type {!r} requires space field ' 'to be of type RealNumbers, got {!r}' .format(dtype, field_type)) elif field_type == RealNumbers: stype = basic_map[impl] else: stype = spacetype_map[impl][field_type] elif field_type is None: # Only in this case are arbitrary types allowed stype = spacetype_map[impl][field_type] else: raise TypeError('non-scalar data type {!r} cannot be combined with ' 'a `LinearSpace`'.format(dtype)) if stype is None: raise NotImplementedError('no corresponding data space available ' 'for space {!r} and implementation {!r}' ''.format(space, impl)) return stype
def vector(array, dtype=None, impl="numpy"): """Create an n-tuples type vector from an array. Parameters ---------- array : array-like Array from which to create the vector. Scalars become one-dimensional vectors. dtype : `object`, optional Set the data type of the vector manually with this option. By default, the space type is inferred from the input data. impl : {'numpy', 'cuda'} Implementation backend for the vector Returns ------- vec : `NtuplesBaseVector` Vector created from the input array. Its concrete type depends on the provided arguments. Notes ----- This is a convenience function and not intended for use in speed-critical algorithms. It creates a NumPy array first, hence especially CUDA vectors as input result in a large speed penalty. Examples -------- >>> vector([1, 2, 3]) # No automatic cast to float Fn(3, 'int').element([1, 2, 3]) >>> vector([1, 2, 3], dtype=float) Rn(3).element([1.0, 2.0, 3.0]) >>> vector([1 + 1j, 2, 3 - 2j]) Cn(3).element([(1+1j), (2+0j), (3-2j)]) Non-scalar types are also supported: >>> vector([u'Hello,', u' world!']) Ntuples(2, '<U7').element([u'Hello,', u' world!']) Scalars become a one-element vector: >>> vector(0.0) Rn(1).element([0.0]) """ # Sanitize input arr = np.array(array, copy=False, ndmin=1) impl = str(impl).lower() # Validate input if arr.ndim > 1: raise ValueError("array has {} dimensions, expected 1." "".format(arr.ndim)) # Set dtype if dtype is not None: space_dtype = dtype elif arr.dtype == float and impl == "cuda": # Special case, default float is float32 on cuda space_dtype = "float32" else: space_dtype = arr.dtype # Select implementation if impl == "numpy": if is_real_floating_dtype(space_dtype): space_type = Rn elif is_complex_floating_dtype(space_dtype): space_type = Cn elif is_scalar_dtype(space_dtype): space_type = Fn else: space_type = Ntuples elif impl == "cuda": if not CUDA_AVAILABLE: raise ValueError("CUDA implementation not available.") if is_real_floating_dtype(space_dtype): space_type = CudaRn elif is_complex_floating_dtype(space_dtype): raise NotImplementedError("complex spaces in CUDA not supported.") elif is_scalar_dtype(space_dtype): space_type = CudaFn else: space_type = CudaNtuples else: raise ValueError("implementation '{}' not understood.".format(impl)) return space_type(len(arr), dtype=space_dtype).element(arr)
def vector(array, dtype=None, impl='numpy'): """Create an n-tuples type vector from an array. Parameters ---------- array : `array-like` Array from which to create the vector. Scalars become one-dimensional vectors. dtype : `object`, optional Set the data type of the vector manually with this option. By default, the space type is inferred from the input data. impl : {'numpy', 'cuda'} Implementation backend for the vector Returns ------- vec : `NtuplesBaseVector` Vector created from the input array. Its concrete type depends on the provided arguments. Notes ----- This is a convenience function and not intended for use in speed-critical algorithms. It creates a NumPy array first, hence especially CUDA vectors as input result in a large speed penalty. Examples -------- >>> vector([1, 2, 3]) # No automatic cast to float Fn(3, 'int').element([1, 2, 3]) >>> vector([1, 2, 3], dtype=float) Rn(3).element([1.0, 2.0, 3.0]) >>> vector([1 + 1j, 2, 3 - 2j]) Cn(3).element([(1+1j), (2+0j), (3-2j)]) Non-scalar types are also supported: >>> vector([True, False]) Ntuples(2, 'bool').element([True, False]) Scalars become a one-element vector: >>> vector(0.0) Rn(1).element([0.0]) """ # Sanitize input arr = np.array(array, copy=False, ndmin=1) impl, impl_in = str(impl).lower(), impl # Validate input if arr.ndim > 1: raise ValueError('array has {} dimensions, expected 1' ''.format(arr.ndim)) # Set dtype if dtype is not None: space_dtype = dtype elif arr.dtype == np.dtype('float64') and impl == 'cuda': # Special case, default float is float32 on cuda space_dtype = 'float32' else: space_dtype = arr.dtype # Select implementation if impl == 'numpy': if is_real_floating_dtype(space_dtype): space_type = Rn elif is_complex_floating_dtype(space_dtype): space_type = Cn elif is_scalar_dtype(space_dtype): space_type = Fn else: space_type = Ntuples elif impl == 'cuda': if not CUDA_AVAILABLE: raise ValueError("'cuda' implementation not available") if is_real_floating_dtype(space_dtype): space_type = CudaRn elif is_complex_floating_dtype(space_dtype): raise NotImplementedError('complex spaces in CUDA not supported') elif is_scalar_dtype(space_dtype): space_type = CudaFn else: space_type = CudaNtuples else: raise ValueError("`impl` '{}' not understood".format(impl_in)) return space_type(len(arr), dtype=space_dtype).element(arr)