diff --git a/.conda/environment.yml b/.conda/environment.yml index 3d6fcb89..9fd075ec 100644 --- a/.conda/environment.yml +++ b/.conda/environment.yml @@ -7,6 +7,7 @@ name: rbc channels: - conda-forge + - numba - defaults dependencies: - python>=3.7 diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 2cfd9892..0b9684af 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -1,11 +1,11 @@ -name: 'CI' +name: 'ChangeLog' on: push: tags: - 'v*' jobs: - release: + changelog: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: diff --git a/.github/workflows/rbc_test.yml b/.github/workflows/rbc_test.yml index ee218600..415e7f5f 100644 --- a/.github/workflows/rbc_test.yml +++ b/.github/workflows/rbc_test.yml @@ -9,6 +9,12 @@ on: pull_request: branches: - master + # workflow_dispatch: + # inputs: + # debug_enabled: + # description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + # required: false + # default: false jobs: lint: @@ -32,16 +38,13 @@ jobs: name: ${{ matrix.os }} - Python v${{ matrix.python-version }} - Numba v${{ matrix.numba-version }} runs-on: ${{ matrix.os }} strategy: - fail-fast: false + fail-fast: true matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: [3.9, 3.8, 3.7] - numba-version: [0.53, 0.52] - exclude: - - python-version: 3.9 - numba-version: 0.52 + numba-version: [0.54, 0.53] - needs: lint + needs: [lint, omniscidb] steps: - name: Checkout code @@ -94,18 +97,27 @@ jobs: mamba run -n rbc pytest -sv -r A rbc/ -x omniscidb: - name: OmnisciDB ${{ matrix.omniscidb-version }} - ${{ matrix.os }} - Python v${{ matrix.python-version }} [${{ matrix.omniscidb-from }}] + name: OmnisciDB ${{ matrix.omniscidb-version }} - ${{ matrix.os }} - Numba v${{matrix.numba-version}} - Python v${{ matrix.python-version }} [${{ matrix.omniscidb-from }}] runs-on: ${{ matrix.os }} + timeout-minutes: 20 strategy: fail-fast: false matrix: os: [ubuntu-latest] python-version: [3.9, 3.8, 3.7] + numba-version: [0.54, 0.53] omniscidb-version: [5.5, 5.4, 5.2] omniscidb-from: [conda] include: - os: ubuntu-latest python-version: 3.8 + numba-version: 0.53 + omniscidb-version: dev + docker-image: omnisci/core-os-cpu-dev:latest + omniscidb-from: docker + - os: ubuntu-latest + python-version: 3.8 + numba-version: 0.54 omniscidb-version: dev docker-image: omnisci/core-os-cpu-dev:latest omniscidb-from: docker @@ -178,6 +190,7 @@ jobs: shell: bash -l {0} run: | cat .conda/environment.yml > rbc_test.yaml + echo " - numba=${{ matrix.numba-version }}" >> rbc_test.yaml echo " - python=${{ matrix.python-version }}" >> rbc_test.yaml mamba env create --file=rbc_test.yaml -n rbc @@ -196,6 +209,10 @@ jobs: run: | mamba run -n rbc python setup.py develop + # - name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + # if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + - name: Run rbc tests [docker] shell: bash -l {0} if: matrix.os == 'ubuntu-latest' && matrix.omniscidb-from == 'docker' @@ -203,8 +220,9 @@ jobs: OMNISCIDB_DEV_LABEL: ${{ 'docker-dev' }} EXPECTED_PYTHON_VERSION: ${{ matrix.python-version }} EXPECTED_OMNISCIDB_VERSION: ${{ matrix.omniscidb-version }} + EXPECTED_NUMBA_VERSION: ${{ matrix.numba-version }} run: | - mamba run -n rbc pytest -sv -r A rbc/ -x + mamba run -n rbc pytest -sv -r A rbc/tests/ -x -k omnisci - name: Run rbc tests shell: bash -l {0} @@ -212,8 +230,9 @@ jobs: env: EXPECTED_PYTHON_VERSION: ${{ matrix.python-version }} EXPECTED_OMNISCIDB_VERSION: ${{ matrix.omniscidb-version }} + EXPECTED_NUMBA_VERSION: ${{ matrix.numba-version }} run: | - mamba run -n rbc pytest -sv -r A rbc/ -x + mamba run -n rbc pytest -sv -r A rbc/tests/ -x -k omnisci - name: Show Omniscidb docker logs on failure [docker] shell: bash -l {0} diff --git a/rbc/externals/stdio.py b/rbc/externals/stdio.py index 1d87f5f5..68f4a94f 100644 --- a/rbc/externals/stdio.py +++ b/rbc/externals/stdio.py @@ -2,6 +2,7 @@ """ import functools +from rbc import irutils from llvmlite import ir from rbc.targetinfo import TargetInfo from numba.core import cgutils, extending @@ -13,7 +14,7 @@ def cg_fflush(builder): int8_t = ir.IntType(8) fflush_fnty = ir.FunctionType(int32_t, [int8_t.as_pointer()]) - fflush_fn = builder.module.get_or_insert_function(fflush_fnty, name="fflush") + fflush_fn = irutils.get_or_insert_function(builder.module, fflush_fnty, name="fflush") builder.call(fflush_fn, [int8_t.as_pointer()(None)]) diff --git a/rbc/irtools.py b/rbc/irtools.py index 6a5db79a..ffe5489a 100644 --- a/rbc/irtools.py +++ b/rbc/irtools.py @@ -10,6 +10,7 @@ import llvmlite.binding as llvm from .targetinfo import TargetInfo from .errors import UnsupportedError +from .utils import get_version from . import libfuncs, structure_type from rbc import externals from rbc.omnisci_backend import mathimpl @@ -230,10 +231,10 @@ def make_wrapper(fname, atypes, rtype, cres, target: TargetInfo, verbose=False): if return_as_first_argument: wrapty = ir.FunctionType(ir.VoidType(), [ll_return_type] + ll_argtypes) - wrapfn = module.add_function(wrapty, fname) + wrapfn = ir.Function(module, wrapty, fname) builder = ir.IRBuilder(wrapfn.append_basic_block('entry')) fnty = context.call_conv.get_function_type(rtype, atypes) - fn = builder.module.add_function(fnty, cres.fndesc.llvm_func_name) + fn = ir.Function(builder.module, fnty, cres.fndesc.llvm_func_name) status, out = context.call_conv.call_function( builder, fn, rtype, atypes, wrapfn.args[1:]) with cgutils.if_unlikely(builder, status.is_error): @@ -247,10 +248,10 @@ def make_wrapper(fname, atypes, rtype, cres, target: TargetInfo, verbose=False): builder.ret_void() else: wrapty = ir.FunctionType(ll_return_type, ll_argtypes) - wrapfn = module.add_function(wrapty, fname) + wrapfn = ir.Function(module, wrapty, fname) builder = ir.IRBuilder(wrapfn.append_basic_block('entry')) fnty = context.call_conv.get_function_type(rtype, atypes) - fn = builder.module.add_function(fnty, cres.fndesc.llvm_func_name) + fn = ir.Function(builder.module, fnty, cres.fndesc.llvm_func_name) status, out = context.call_conv.call_function( builder, fn, rtype, atypes, wrapfn.args) if verbose and target.is_cpu: @@ -275,9 +276,14 @@ def compile_instance(func, sig, succesful. """ flags = compiler.Flags() - flags.set('no_compile') - flags.set('no_cpython_wrapper') - flags.set('no_cfunc_wrapper') + if get_version('numba') >= (0, 54): + flags.no_compile = True + flags.no_cpython_wrapper = True + flags.no_cfunc_wrapper = True + else: + flags.set('no_compile') + flags.set('no_cpython_wrapper') + flags.set('no_cfunc_wrapper') fname = func.__name__ + sig.mangling() args, return_type = sigutils.normalize_signature( @@ -467,6 +473,10 @@ def compile_IR(ir): ir, re.M).group('triple') # Create execution engine + llvm.initialize() + llvm.initialize_all_targets() + llvm.initialize_all_asmprinters() + target = llvm.Target.from_triple(triple) target_machine = target.create_target_machine() backing_mod = llvm.parse_assembly("") diff --git a/rbc/irutils.py b/rbc/irutils.py new file mode 100644 index 00000000..df182d54 --- /dev/null +++ b/rbc/irutils.py @@ -0,0 +1,31 @@ +from rbc.utils import get_version +from numba.core import cgutils +from llvmlite import ir + + +int8_t = ir.IntType(8) +int32_t = ir.IntType(32) +int64_t = ir.IntType(64) +void_t = ir.VoidType() +fp32 = ir.FloatType() +fp64 = ir.DoubleType() + + +def get_or_insert_function(module, fnty, name=None): + if get_version('numba') >= (0, 54): + fn = cgutils.get_or_insert_function( + module, fnty, name=name) + else: + fn = module.get_or_insert_function( + fnty, name=name) + return fn + + +def get_member_value(builder, data, idx): + if get_version('numba') >= (0, 54): + assert data.opname == 'insertvalue', data.opname + return builder.extract_value(data, [idx]) + else: + assert data.opname == 'load', data.opname + struct = data.operands[0] + return builder.load(builder.gep(struct, [int32_t(0), int32_t(idx)])) diff --git a/rbc/libfuncs.py b/rbc/libfuncs.py index e2c6431b..35893850 100644 --- a/rbc/libfuncs.py +++ b/rbc/libfuncs.py @@ -36,7 +36,14 @@ def check(self, fname): """ Return True if library contains a function with given name. """ - return fname in self._function_names + if fname in self._function_names: + return True + + for func in self._function_names: + if func.endswith('.*') and fname.startswith(func[:-2]): + return True + + return False class OmnisciDB(Library): @@ -196,6 +203,15 @@ def check(self, fname): experimental.constrained.floor experimental.constrained.round experimental.constrained.roundeven experimental.constrained.lround experimental.constrained.llround experimental.constrained.trunc + experimental.gc.statepoint experimental.gc.result experimental.gc.relocate + experimental.gc.get.pointer.base experimental.gc.get.pointer.offset + experimental.vector.reduce.add.* experimental.vector.reduce.fadd.* + experimental.vector.reduce.mul.* experimental.vector.reduce.fmul.* + experimental.vector.reduce.and.* experimental.vector.reduce.or.* + experimental.vector.reduce.xor.* experimental.vector.reduce.smax.* + experimental.vector.reduce.smin.* experimental.vector.reduce.umax.* + experimental.vector.reduce.umin.* experimental.vector.reduce.fmax.* + experimental.vector.reduce.fmin.* flt.rounds var.annotation ptr.annotation annotation codeview.annotation trap debugtrap stackprotector stackguard objectsize expect expect.with.probability assume ssa_copy @@ -211,7 +227,8 @@ def check(self, fname): objc.retainAutoreleaseReturnValue objc.retainAutoreleasedReturnValue objc.retainBlock objc.storeStrong objc.storeWeak preserve.array.access.index - preserve.union.access.index preserve.struct.access.index '''.strip().split()) + preserve.union.access.index preserve.struct.access.index + masked.store.* '''.strip().split()) class NVVMIntrinsics(Library): diff --git a/rbc/omnisci_backend/omnisci_buffer.py b/rbc/omnisci_backend/omnisci_buffer.py index 26757fe8..149bec74 100644 --- a/rbc/omnisci_backend/omnisci_buffer.py +++ b/rbc/omnisci_backend/omnisci_buffer.py @@ -28,7 +28,7 @@ from .omnisci_metatype import OmnisciMetaType from llvmlite import ir import numpy as np -from rbc import typesystem +from rbc import typesystem, irutils from rbc.targetinfo import TargetInfo from llvmlite import ir as llvm_ir from numba.core import datamodel, cgutils, extending, types @@ -164,8 +164,7 @@ def omnisci_buffer_constructor(context, builder, sig, args): alloc_fnty = ir.FunctionType(int8_t.as_pointer(), [int64_t, int64_t]) - alloc_fn = builder.module.get_or_insert_function( - alloc_fnty, name="allocate_varlen_buffer") + alloc_fn = irutils.get_or_insert_function(builder.module, alloc_fnty, "allocate_varlen_buffer") ptr8 = builder.call(alloc_fn, [element_count, element_size]) # remember possible temporary allocations so that when leaving a # UDF/UDTF, these will be deallocated, see omnisci_pipeline.py. @@ -196,7 +195,7 @@ def codegen(context, builder, signature, args): # TODO: using stdlib `free` that works only for CPU. For CUDA # devices, we need to use omniscidb provided deallocator. free_fnty = llvm_ir.FunctionType(void_t, [int8_t.as_pointer()]) - free_fn = builder.module.get_or_insert_function(free_fnty, name="free") + free_fn = irutils.get_or_insert_function(builder.module, free_fnty, "free") # We skip the ret pointer iff we're returning a Buffer # otherwise, we free everything @@ -302,10 +301,7 @@ def omnisci_buffer_len_(typingctx, data): def codegen(context, builder, signature, args): data, = args - assert data.opname == 'load' - struct = data.operands[0] - return builder.load(builder.gep( - struct, [int32_t(0), int32_t(1)])) + return irutils.get_member_value(builder, data, 1) return sig, codegen @@ -341,11 +337,7 @@ def omnisci_buffer_getitem_(typingctx, data, index): def codegen(context, builder, signature, args): data, index = args - assert data.opname == 'load' - buf = data.operands[0] - - ptr = builder.load(builder.gep( - buf, [int32_t(0), int32_t(0)])) + ptr = irutils.get_member_value(builder, data, 0) res = builder.load(builder.gep(ptr, [index])) return res @@ -416,14 +408,8 @@ def omnisci_buffer_setitem_(typingctx, data, index, value): nb_value = value def codegen(context, builder, signature, args): - zero = int32_t(0) - data, index, value = args - - assert data.opname == 'load' - buf = data.operands[0] - - ptr = builder.load(builder.gep(buf, [zero, zero])) + ptr = irutils.get_member_value(builder, data, 0) value = truncate_or_extend(builder, nb_value, eltype, value, ptr.type.pointee) builder.store(value, builder.gep(ptr, [index])) diff --git a/rbc/omnisci_backend/omnisci_column.py b/rbc/omnisci_backend/omnisci_column.py index 91dd5343..96126b8e 100644 --- a/rbc/omnisci_backend/omnisci_column.py +++ b/rbc/omnisci_backend/omnisci_column.py @@ -8,7 +8,7 @@ 'OmnisciCursorType'] from llvmlite import ir -from rbc import typesystem +from rbc import typesystem, irutils from .omnisci_buffer import Buffer, OmnisciBufferType, BufferType from .column_list import OmnisciColumnListType from rbc.targetinfo import TargetInfo @@ -55,14 +55,8 @@ def omnisci_column_set_null_(typingctx, col_var, row_idx): null_value = target_info.null_values[str(T)] def codegen(context, builder, signature, args): - zero = int32_t(0) - data, index = args - - assert data.opname == 'load' - buf = data.operands[0] - - ptr = builder.load(builder.gep(buf, [zero, zero])) + ptr = irutils.get_member_value(builder, data, 0) ty = ptr.type.pointee nv = ir.Constant(ir.IntType(T.bitwidth), null_value) @@ -90,12 +84,8 @@ def omnisci_column_is_null_(typingctx, col_var, row_idx): nv = ir.Constant(ir.IntType(T.bitwidth), null_value) def codegen(context, builder, signature, args): - zero = int32_t(0) data, index = args - assert data.opname == 'load' - buf = data.operands[0] - - ptr = builder.load(builder.gep(buf, [zero, zero])) + ptr = irutils.get_member_value(builder, data, 0) res = builder.load(builder.gep(ptr, [index])) if isinstance(T, types.Float): diff --git a/rbc/structure_type.py b/rbc/structure_type.py index 06e9fd16..879c5a50 100644 --- a/rbc/structure_type.py +++ b/rbc/structure_type.py @@ -2,6 +2,7 @@ __all__ = ['StructureNumbaType', 'StructureNumbaPointerType', 'make_numba_struct'] import operator +from rbc.irutils import get_member_value from llvmlite import ir from numba.core import datamodel, extending, types, imputils, typing, cgutils, typeconv @@ -130,11 +131,8 @@ def model__init__(self, dmm, fe_type): @lowering_registry.lower_getattr_generic(StructureNumbaType) def StructureNumbaType_getattr_impl(context, builder, sig, struct, attr): model = datamodel.default_manager.lookup(sig) - assert struct.opname == 'load' index = model.get_field_position(attr) - - ptr = builder.gep(struct.operands[0], [int32_t(0), int32_t(0)]) - return builder.load(builder.gep(ptr, [int32_t(index)])) + return get_member_value(builder, struct, index) @lowering_registry.lower_setattr_generic(StructureNumbaType) @@ -142,7 +140,6 @@ def StructureNumbaType_setattr_impl(context, builder, sig, args, attr): typ = sig.args[0] struct, value = args model = datamodel.default_manager.lookup(typ) - assert struct.opname == 'load' index = model.get_field_position(attr) ptr = builder.gep(struct.operands[0], [int32_t(0), int32_t(index)]) return builder.store(value, ptr) @@ -152,7 +149,6 @@ def StructureNumbaType_setattr_impl(context, builder, sig, args, attr): def StructureNumbaPointerType_getattr_impl(context, builder, sig, struct, attr): typ = sig.dtype model = datamodel.default_manager.lookup(typ) - assert struct.opname == 'load' index = model.get_field_position(attr) rawptr = cgutils.alloca_once_value(builder, value=struct) struct = builder.load(builder.gep(rawptr, [int32_t(0)])) @@ -165,7 +161,6 @@ def StructureNumbaPointerType_setattr_impl(context, builder, sig, args, attr): typ = sig.args[0].dtype struct, value = args model = datamodel.default_manager.lookup(typ) - assert struct.opname == 'load' index = model.get_field_position(attr) rawptr = cgutils.alloca_once_value(builder, value=struct) ptr = builder.load(rawptr) diff --git a/rbc/tests/test_omnisci_array_methods.py b/rbc/tests/test_omnisci_array_methods.py index 283a78a8..a55ac954 100644 --- a/rbc/tests/test_omnisci_array_methods.py +++ b/rbc/tests/test_omnisci_array_methods.py @@ -1,5 +1,6 @@ import pytest import numpy as np +from rbc.tests import omnisci_fixture from rbc.omnisci_backend import Array @@ -10,117 +11,115 @@ @pytest.fixture(scope='module') def omnisci(): - config = rbc_omnisci.get_client_config(debug=not True) - m = rbc_omnisci.RemoteOmnisci(**config) - # issue https://github.com/xnd-project/rbc/issues/134 - table_name = 'rbc_test_omnisci_array_methods' - m.sql_execute('DROP TABLE IF EXISTS {table_name}'.format(**locals())) - yield m + for o in omnisci_fixture(globals()): + define(o) + yield o ndarray_methods = [ - ('fill', 'double[](int64, double)', (5, 4), [4.0, 4.0, 4.0, 4.0, 4.0]), - ('max', 'double(int64, double)', (5, 4.0), 4.0), - ('max_empty', 'int8(int32)', (0, ), -128), - ('max_initial', 'double(int64, double, double)', (5, 4.0, 30.0), 30.0), - ('mean', 'double(int64, double)', (5, 2.0), 2.0), - ('mean_empty_float', 'float64(int64)', (0, ), np.nan), - ('mean_empty_int', 'int32(int64)', (0, ), 0), - ('min', 'double(int64, double)', (5, 4.0), 4.0), - ('min_empty', 'int16(int64)', (0, ), 32767), - ('min_initial', 'double(int64, double, double)', (5, 4.0, -3.0), -3.0), - ('sum', 'double(int64, double)', (5, 2.0), 10.0), - ('sum_initial', 'double(int64, double, double)', (5, 2.0, 2.0), 12.0), - ('prod', 'double(int64, double)', (5, 3.0), 243.0), - ('prod_initial', 'double(int64, double, double)', (5, 3.0, 2), 486.0), + ('fill', (5, 4), [4.0, 4.0, 4.0, 4.0, 4.0]), + ('max', (5, 4.0), 4.0), + ('max_empty', (0, ), -128), + ('max_initial', (5, 4.0, 30.0), 30.0), + ('mean', (5, 2.0), 2.0), + ('mean_empty_float', (0, ), np.nan), + ('mean_empty_int', (0, ), 0), + ('min', (5, 4.0), 4.0), + ('min_empty', (0, ), 32767), + ('min_initial', (5, 4.0, -3.0), -3.0), + ('sum', (5, 2.0), 10.0), + ('sum_initial', (5, 2.0, 2.0), 12.0), + ('prod', (5, 3.0), 243.0), + ('prod_initial', (5, 3.0, 2), 486.0), ] -def ndarray_fill(size, v): - a = Array(size, 'double') - a.fill(v) - return a - - -def ndarray_max(size, v): - a = Array(size, 'double') - a.fill(v) - return a.max() - - -def ndarray_max_empty(size): - a = Array(size, 'int8') - return a.max() - - -def ndarray_max_initial(size, v, initial): - a = Array(size, 'double') - a.fill(v) - return a.max(initial=initial) - - -def ndarray_mean(size, v): - a = Array(size, 'double') - a.fill(v) - return a.mean() - - -def ndarray_mean_empty_float(size): - a = Array(size, 'float64') - return a.mean() - - -def ndarray_mean_empty_int(size): - a = Array(size, 'int32') - return a.mean() - - -def ndarray_min(size, v): - a = Array(size, 'double') - a.fill(v) - return a.min() - - -def ndarray_min_empty(size): - a = Array(size, 'int16') - return a.min() - - -def ndarray_min_initial(size, v, initial): - a = Array(size, 'double') - a.fill(v) - return a.min(initial=initial) - - -def ndarray_sum(size, v): - a = Array(size, 'double') - a.fill(v) - return a.sum() - - -def ndarray_sum_initial(size, v, initial): - a = Array(size, 'double') - a.fill(v) - return a.sum(initial=initial) - - -def ndarray_prod(size, v): - a = Array(size, 'double') - a.fill(v) - return a.prod() - - -def ndarray_prod_initial(size, v, initial): - a = Array(size, 'double') - a.fill(v) - return a.prod(initial=initial) - - -@pytest.mark.parametrize("method, signature, args, expected", ndarray_methods, +def define(omnisci): + + @omnisci('double[](int64, double)') + def ndarray_fill(size, v): + a = Array(size, 'double') + a.fill(v) + return a + + @omnisci('double(int64, double)') + def ndarray_max(size, v): + a = Array(size, 'double') + a.fill(v) + return a.max() + + @omnisci('int8(int32)') + def ndarray_max_empty(size): + a = Array(size, 'int8') + return a.max() + + @omnisci('double(int64, double, double)') + def ndarray_max_initial(size, v, initial): + a = Array(size, 'double') + a.fill(v) + return a.max(initial=initial) + + @omnisci('double(int64, double)') + def ndarray_mean(size, v): + a = Array(size, 'double') + a.fill(v) + return a.mean() + + @omnisci('float64(int64)') + def ndarray_mean_empty_float(size): + a = Array(size, 'float64') + return a.mean() + + @omnisci('float64(int64)') + def ndarray_mean_empty_int(size): + a = Array(size, 'int32') + return a.mean() + + @omnisci('double(int64, double)') + def ndarray_min(size, v): + a = Array(size, 'double') + a.fill(v) + return a.min() + + @omnisci('int16(int64)') + def ndarray_min_empty(size): + a = Array(size, 'int16') + return a.min() + + @omnisci('double(int64, double, double)') + def ndarray_min_initial(size, v, initial): + a = Array(size, 'double') + a.fill(v) + return a.min(initial=initial) + + @omnisci('double(int64, double)') + def ndarray_sum(size, v): + a = Array(size, 'double') + a.fill(v) + return a.sum() + + @omnisci('double(int64, double, double)') + def ndarray_sum_initial(size, v, initial): + a = Array(size, 'double') + a.fill(v) + return a.sum(initial=initial) + + @omnisci('double(int64, double)') + def ndarray_prod(size, v): + a = Array(size, 'double') + a.fill(v) + return a.prod() + + @omnisci('double(int64, double, double)') + def ndarray_prod_initial(size, v, initial): + a = Array(size, 'double') + a.fill(v) + return a.prod(initial=initial) + + +@pytest.mark.parametrize("method, args, expected", ndarray_methods, ids=[item[0] for item in ndarray_methods]) -def test_ndarray_methods(omnisci, method, signature, args, expected): - omnisci.reset() - +def test_ndarray_methods(omnisci, method, args, expected): if omnisci.has_cuda and omnisci.version < (5, 5): pytest.skip( f'{method}: crashes CUDA enabled omniscidb server [issue 93]') @@ -134,10 +133,9 @@ def test_ndarray_methods(omnisci, method, signature, args, expected): f'{method}: fails on CPU-only omniscidb server' ' v 5.3.1+ [issue 114]') - omnisci(signature)(eval('ndarray_{}'.format(method))) + query_args = ', '.join(map(str, args)) + query = f'SELECT ndarray_{method}({query_args})' - query = 'select ndarray_{method}'.format(**locals()) + \ - '(' + ', '.join(map(str, args)) + ')' _, result = omnisci.sql_execute(query) out = list(result)[0] diff --git a/rbc/tests/test_omnisci_array_operators.py b/rbc/tests/test_omnisci_array_operators.py index e961d58f..e6ce1c0e 100644 --- a/rbc/tests/test_omnisci_array_operators.py +++ b/rbc/tests/test_omnisci_array_operators.py @@ -1,6 +1,7 @@ import pytest import numpy as np from rbc.omnisci_backend import Array +from rbc.tests import omnisci_fixture from numba import types as nb_types import operator @@ -12,483 +13,483 @@ @pytest.fixture(scope='module') def omnisci(): - config = rbc_omnisci.get_client_config(debug=not True) - m = rbc_omnisci.RemoteOmnisci(**config) - # issue https://github.com/xnd-project/rbc/issues/134 - table_name = 'rbc_test_omnisci_array_operators' - m.sql_execute('DROP TABLE IF EXISTS {table_name}'.format(**locals())) - yield m + for o in omnisci_fixture(globals()): + define(o) + yield o operator_methods = [ - ('abs', 'int32[](int64)', (6,), np.arange(6)), - ('add', 'int32[](int64)', (6,), np.full(6, 5)), - ('and_bw', 'int32[](int64)', (6,), [0, 0, 2, 2, 0, 0]), - ('countOf', 'int64(int64, int64, int64)', (6, 3, 4), 0), - ('countOf', 'int64(int64, int64, int64)', (6, 3, 3), 6), - ('eq', 'int8[](int64, int32)', (6, 3), [0, 0, 0, 1, 0, 0]), - ('eq_array', 'bool(int64, int32)', (6, 3), True), - ('floordiv', 'int32[](int64)', (6,), [3, 2, 2, 2, 2, 1]), - ('floordiv2', 'double[](int64)', (6,), [3.0, 2.0, 2.0, 2.0, 2.0, 1.0]), - ('ge', 'int8[](int64, int32)', (6, 3), [0, 0, 0, 1, 1, 1]), - ('ge_array', 'bool(int64, int32)', (6, 3), True), - ('gt', 'int8[](int64, int32)', (6, 3), [0, 0, 0, 0, 1, 1]), - ('gt_array', 'bool(int64, int32)', (6, 3), False), - ('iadd', 'int32[](int64)', (6,), [1, 2, 3, 4, 5, 6]), - ('iand', 'int32[](int64)', (6,), [0, 0, 2, 2, 0, 0]), - ('ifloordiv', 'int32[](int64)', (6,), [3, 2, 2, 2, 2, 1]), - ('ifloordiv2', 'double[](int64)', (6,), [3, 2, 2, 2, 2, 1]), - ('ilshift', 'int32[](int64)', (6,), [0, 16, 16, 12, 8, 5]), - ('imul', 'int32[](int64)', (6,), [0, 4, 6, 6, 4, 0]), - ('ior', 'int32[](int64)', (6,), [5, 5, 3, 3, 5, 5]), - ('isub', 'int32[](int64)', (6,), [-5, -3, -1, 1, 3, 5]), - ('ipow', 'int32[](int64)', (6,), [1, 32, 81, 64, 25, 6]), - ('irshift', 'int32[](int64)', (6,), [0, 0, 0, 0, 2, 5]), - ('itruediv', 'int32[](int64)', (6,), [3, 2, 2, 2, 2, 1]), - ('itruediv2', 'double[](int64)', (6,), [3.3333333333333335, 2.75, 2.4, 2.1666666666666665, 2.0, 1.875]), # noqa: E501 - ('imod', 'int32[](int64)', (6,), [0, 4, 1, 5, 2, 6]), - ('ixor', 'int32[](int64)', (6,), [5, 5, 1, 1, 5, 5]), - ('in', 'int8(int64, int32)', (6, 3), True), - ('is', 'int8(int64, int32)', (6, 3), True), - ('is_not', 'int8(int64, int32)', (6, 3), False), - ('is_not2', 'int8(int64, int32)', (6, 3), True), - ('le', 'int8[](int64, int32)', (6, 3), [1, 1, 1, 1, 0, 0]), - ('le_array', 'bool(int64, int32)', (6, 3), True), - ('lshift', 'int32[](int64)', (6,), [0, 16, 16, 12, 8, 5]), - ('lt', 'int8[](int64, int32)', (6, 3), [1, 1, 1, 0, 0, 0]), - ('lt_array', 'bool(int64, int32)', (6, 3), False), - ('mul', 'int32[](int64)', (6,), [0, 4, 6, 6, 4, 0]), - ('mod', 'int32[](int64)', (6,), [0, 4, 1, 5, 2, 6]), - ('ne', 'int8[](int64, int32)', (6, 3), [1, 1, 1, 0, 1, 1]), - ('neg', 'int32[](int64)', (6,), [0, -1, -2, -3, -4, -5]), - ('ne_array', 'bool(int64, int32)', (6, 3), False), - ('not_in', 'int8(int64, int32)', (6, 3), False), - ('or_bw', 'int32[](int64)', (6,), [5, 5, 3, 3, 5, 5]), - ('pos', 'int32[](int64)', (6,), [0, -1, -2, -3, -4, -5]), - ('pow', 'int32[](int64)', (6,), [1, 32, 81, 64, 25, 6]), - ('rshift', 'int32[](int64)', (6,), [0, 0, 0, 0, 2, 5]), - ('sub', 'int32[](int64)', (6,), [-5, -3, -1, 1, 3, 5]), - ('truediv', 'int32[](int64)', (6,), [3, 2, 2, 2, 2, 1]), - ('truediv2', 'double[](int64)', (6,), [3.3333333333333335, 2.75, 2.4, 2.1666666666666665, 2.0, 1.875]), # noqa: E501 - ('xor', 'int32[](int64)', (6,), [5, 5, 1, 1, 5, 5]), + ('abs', (6,), np.arange(6)), + ('add', (6,), np.full(6, 5)), + ('and_bw', (6,), [0, 0, 2, 2, 0, 0]), + ('countOf', (6, 3, 4), 0), + ('countOf', (6, 3, 3), 6), + ('eq', (6, 3), [0, 0, 0, 1, 0, 0]), + ('eq_array', (6, 3), True), + ('floordiv', (6,), [3, 2, 2, 2, 2, 1]), + ('floordiv2', (6,), [3.0, 2.0, 2.0, 2.0, 2.0, 1.0]), + ('ge', (6, 3), [0, 0, 0, 1, 1, 1]), + ('ge_array', (6, 3), True), + ('gt', (6, 3), [0, 0, 0, 0, 1, 1]), + ('gt_array', (6, 3), False), + ('iadd', (6,), [1, 2, 3, 4, 5, 6]), + ('iand', (6,), [0, 0, 2, 2, 0, 0]), + ('ifloordiv', (6,), [3, 2, 2, 2, 2, 1]), + ('ifloordiv2', (6,), [3, 2, 2, 2, 2, 1]), + ('ilshift', (6,), [0, 16, 16, 12, 8, 5]), + ('imul', (6,), [0, 4, 6, 6, 4, 0]), + ('ior', (6,), [5, 5, 3, 3, 5, 5]), + ('isub', (6,), [-5, -3, -1, 1, 3, 5]), + ('ipow', (6,), [1, 32, 81, 64, 25, 6]), + ('irshift', (6,), [0, 0, 0, 0, 2, 5]), + ('itruediv', (6,), [3, 2, 2, 2, 2, 1]), + ('itruediv2', (6,), [3.3333333333333335, 2.75, 2.4, 2.1666666666666665, 2.0, 1.875]), # noqa: E501 + ('imod', (6,), [0, 4, 1, 5, 2, 6]), + ('ixor', (6,), [5, 5, 1, 1, 5, 5]), + ('in', (6, 3), True), + ('is', (6, 3), True), + ('is_not', (6, 3), False), + ('is_not2', (6, 3), True), + ('le', (6, 3), [1, 1, 1, 1, 0, 0]), + ('le_array', (6, 3), True), + ('lshift', (6,), [0, 16, 16, 12, 8, 5]), + ('lt', (6, 3), [1, 1, 1, 0, 0, 0]), + ('lt_array', (6, 3), False), + ('mul', (6,), [0, 4, 6, 6, 4, 0]), + ('mod', (6,), [0, 4, 1, 5, 2, 6]), + ('ne', (6, 3), [1, 1, 1, 0, 1, 1]), + ('ne_array', (6, 3), False), + ('neg', (6,), [0, -1, -2, -3, -4, -5]), + ('not_in', (6, 3), False), + ('or_bw', (6,), [5, 5, 3, 3, 5, 5]), + ('pos', (6,), [0, -1, -2, -3, -4, -5]), + ('pow', (6,), [1, 32, 81, 64, 25, 6]), + ('rshift', (6,), [0, 0, 0, 0, 2, 5]), + ('sub', (6,), [-5, -3, -1, 1, 3, 5]), + ('truediv', (6,), [3, 2, 2, 2, 2, 1]), + ('truediv2', (6,), [3.3333333333333335, 2.75, 2.4, 2.1666666666666665, 2.0, 1.875]), # noqa: E501 + ('xor', (6,), [5, 5, 1, 1, 5, 5]), ] -def operator_countOf(size, fill_value, b): - a = Array(size, 'int64') - for i in range(size): - a[i] = fill_value - return operator.countOf(a, b) - - -def operator_neg(size): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return operator.neg(a) - - -def operator_abs(size): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(-i) - return abs(a) - - -def operator_pos(size): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(-i) - return operator.pos(a) - - -def operator_rshift(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.rshift(a, b) - - -def operator_irshift(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.irshift(a, b) - return a - - -def operator_lshift(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.lshift(a, b) - - -def operator_ilshift(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.ilshift(a, b) - return a - - -def operator_floordiv(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i+10) - b[i] = nb_types.int32(i+3) - return operator.floordiv(a, b) - - -def operator_ifloordiv(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i+10) - b[i] = nb_types.int32(i+3) - operator.ifloordiv(a, b) - return a - - -def operator_floordiv2(size): - a = Array(size, 'double') - b = Array(size, 'double') - for i in range(size): - a[i] = nb_types.double(i+10) - b[i] = nb_types.double(i+3) - return operator.floordiv(a, b) - - -def operator_ifloordiv2(size): - a = Array(size, 'double') - b = Array(size, 'double') - for i in range(size): - a[i] = nb_types.double(i+10) - b[i] = nb_types.double(i+3) - operator.ifloordiv(a, b) - return a - - -def operator_truediv(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i+10) - b[i] = nb_types.int32(i+3) - return operator.truediv(a, b) - - -def operator_itruediv(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i+10) - b[i] = nb_types.int32(i+3) - operator.itruediv(a, b) - return a - - -def operator_truediv2(size): - a = Array(size, 'double') - b = Array(size, 'double') - for i in range(size): - a[i] = nb_types.double(i+10) - b[i] = nb_types.double(i+3) - return operator.truediv(a, b) - - -def operator_itruediv2(size): - a = Array(size, 'double') - b = Array(size, 'double') - for i in range(size): - a[i] = nb_types.double(i+10) - b[i] = nb_types.double(i+3) - operator.itruediv(a, b) - return a - - -def operator_pow(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i+1) - b[i] = nb_types.int32(size-i) - return operator.pow(a, b) - - -def operator_ipow(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i+1) - b[i] = nb_types.int32(size-i) - operator.ipow(a, b) - return a - - -def operator_mul(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.mul(a, b) - - -def operator_imul(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.imul(a, b) - return a - - -def operator_mod(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i * 123) - b[i] = nb_types.int32(7) - return operator.mod(a, b) - - -def operator_imod(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i * 123) - b[i] = nb_types.int32(7) - operator.imod(a, b) - return a - - -def operator_sub(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.sub(a, b) - - -def operator_isub(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.isub(a, b) - return a - - -def operator_add(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.add(a, b) - - -def operator_iadd(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(1) - operator.iadd(a, b) - return a - - -def operator_xor(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.xor(a, b) - - -def operator_ixor(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.ixor(a, b) - return a - - -def operator_or_bw(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.or_(a, b) - - -def operator_ior(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.ior(a, b) - return a - - -def operator_and_bw(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - return operator.and_(a, b) - - -def operator_iand(size): - a = Array(size, 'int32') - b = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - b[i] = nb_types.int32(size-i-1) - operator.iand(a, b) - return a - - -def operator_eq(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a == v - - -def operator_eq_array(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a == a - - -def operator_ne(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a != v - - -def operator_ne_array(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a != a - - -def operator_lt(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a < v - - -def operator_lt_array(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a < a - - -def operator_le(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a <= v - - -def operator_le_array(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a <= a - - -def operator_gt(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a > v - - -def operator_gt_array(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a > a - - -def operator_ge(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a >= v - - -def operator_ge_array(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return a >= a - - -def operator_in(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return v in a - - -def operator_not_in(size, v): - a = Array(size, 'int32') - for i in range(size): - a[i] = nb_types.int32(i) - return v not in a - - -def operator_is(size, v): - a = Array(size, 'int32') - a.fill(v) - return a is a - - -def operator_is_not(size, v): - a = Array(size, 'int32') - a.fill(v) - return a is not a - - -def operator_is_not2(size, v): - a = Array(size, 'int32') - a.fill(v) - b = Array(size, 'int32') - b.fill(v) - return a is not b - - -@pytest.mark.parametrize("suffix, signature, args, expected", operator_methods, +def define(omnisci): + + @omnisci('int32[](int64)') + def operator_abs(size): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(-i) + return abs(a) + + @omnisci('int32[](int64)') + def operator_add(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.add(a, b) + + @omnisci('int32[](int64)') + def operator_and_bw(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.and_(a, b) + + @omnisci('int64(int64, int64, int64)') + def operator_countOf(size, fill_value, b): + a = Array(size, 'int64') + for i in range(size): + a[i] = fill_value + return operator.countOf(a, b) + + @omnisci('int8[](int64, int32)') + def operator_eq(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a == v + + @omnisci('bool(int64, int32)') + def operator_eq_array(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a == a + + @omnisci('int32[](int64)') + def operator_floordiv(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i+10) + b[i] = nb_types.int32(i+3) + return operator.floordiv(a, b) + + @omnisci('double[](int64)') + def operator_floordiv2(size): + a = Array(size, 'double') + b = Array(size, 'double') + for i in range(size): + a[i] = nb_types.double(i+10) + b[i] = nb_types.double(i+3) + return operator.floordiv(a, b) + + @omnisci('int8[](int64, int32)') + def operator_ge(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a >= v + + @omnisci('bool(int64, int32)') + def operator_ge_array(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a >= a + + @omnisci('int8[](int64, int32)') + def operator_gt(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a > v + + @omnisci('bool(int64, int32)') + def operator_gt_array(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a > a + + @omnisci('int32[](int64)') + def operator_iadd(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(1) + operator.iadd(a, b) + return a + + @omnisci('int32[](int64)') + def operator_iand(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.iand(a, b) + return a + + @omnisci('int32[](int64)') + def operator_ifloordiv(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i+10) + b[i] = nb_types.int32(i+3) + operator.ifloordiv(a, b) + return a + + @omnisci('double[](int64)') + def operator_ifloordiv2(size): + a = Array(size, 'double') + b = Array(size, 'double') + for i in range(size): + a[i] = nb_types.double(i+10) + b[i] = nb_types.double(i+3) + operator.ifloordiv(a, b) + return a + + @omnisci('int32[](int64)') + def operator_ilshift(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.ilshift(a, b) + return a + + @omnisci('int32[](int64)') + def operator_imul(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.imul(a, b) + return a + + @omnisci('int32[](int64)') + def operator_ior(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.ior(a, b) + return a + + @omnisci('int32[](int64)') + def operator_isub(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.isub(a, b) + return a + + @omnisci('int32[](int64)') + def operator_ipow(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i+1) + b[i] = nb_types.int32(size-i) + operator.ipow(a, b) + return a + + @omnisci('int32[](int64)') + def operator_irshift(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.irshift(a, b) + return a + + @omnisci('int32[](int64)') + def operator_itruediv(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i+10) + b[i] = nb_types.int32(i+3) + operator.itruediv(a, b) + return a + + @omnisci('double[](int64)') + def operator_itruediv2(size): + a = Array(size, 'double') + b = Array(size, 'double') + for i in range(size): + a[i] = nb_types.double(i+10) + b[i] = nb_types.double(i+3) + operator.itruediv(a, b) + return a + + @omnisci('int32[](int64)') + def operator_imod(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i * 123) + b[i] = nb_types.int32(7) + operator.imod(a, b) + return a + + @omnisci('int32[](int64)') + def operator_ixor(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + operator.ixor(a, b) + return a + + @omnisci('int8(int64, int32)') + def operator_in(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return v in a + + @omnisci('int8(int64, int32)') + def operator_is(size, v): + a = Array(size, 'int32') + a.fill(v) + return a is a + + @omnisci('int8(int64, int32)') + def operator_is_not(size, v): + a = Array(size, 'int32') + a.fill(v) + return a is not a + + @omnisci('int8(int64, int32)') + def operator_is_not2(size, v): + a = Array(size, 'int32') + a.fill(v) + b = Array(size, 'int32') + b.fill(v) + return a is not b + + @omnisci('int8[](int64, int32)') + def operator_le(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a <= v + + @omnisci('bool(int64, int32)') + def operator_le_array(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a <= a + + @omnisci('int32[](int64)') + def operator_lshift(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.lshift(a, b) + + @omnisci('int8[](int64, int32)') + def operator_lt(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a < v + + @omnisci('bool(int64, int32)') + def operator_lt_array(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a < a + + @omnisci('int32[](int64)') + def operator_mul(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.mul(a, b) + + @omnisci('int32[](int64)') + def operator_mod(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i * 123) + b[i] = nb_types.int32(7) + return operator.mod(a, b) + + @omnisci('int8[](int64, int32)') + def operator_ne(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a != v + + @omnisci('bool(int64, int32)') + def operator_ne_array(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return a != a + + @omnisci('int32[](int64)') + def operator_neg(size): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return operator.neg(a) + + @omnisci('int8(int64, int32)') + def operator_not_in(size, v): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + return v not in a + + @omnisci('int32[](int64)') + def operator_or_bw(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.or_(a, b) + + @omnisci('int32[](int64)') + def operator_pos(size): + a = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(-i) + return operator.pos(a) + + @omnisci('int32[](int64)') + def operator_pow(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i+1) + b[i] = nb_types.int32(size-i) + return operator.pow(a, b) + + @omnisci('int32[](int64)') + def operator_rshift(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.rshift(a, b) + + @omnisci('int32[](int64)') + def operator_sub(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.sub(a, b) + + @omnisci('int32[](int64)') + def operator_truediv(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i+10) + b[i] = nb_types.int32(i+3) + return operator.truediv(a, b) + + @omnisci('double[](int64)') + def operator_truediv2(size): + a = Array(size, 'double') + b = Array(size, 'double') + for i in range(size): + a[i] = nb_types.double(i+10) + b[i] = nb_types.double(i+3) + return operator.truediv(a, b) + + @omnisci('int32[](int64)') + def operator_xor(size): + a = Array(size, 'int32') + b = Array(size, 'int32') + for i in range(size): + a[i] = nb_types.int32(i) + b[i] = nb_types.int32(size-i-1) + return operator.xor(a, b) + + +@pytest.mark.parametrize("suffix, args, expected", operator_methods, ids=[item[0] for item in operator_methods]) -def test_array_operators(omnisci, suffix, signature, args, expected): +def test_array_operators(omnisci, suffix, args, expected): if omnisci.has_cuda and suffix in ['countOf', 'in', 'not_in'] and omnisci.version < (5, 5): # https://github.com/xnd-project/rbc/issues/107 @@ -506,10 +507,6 @@ def test_array_operators(omnisci, suffix, signature, args, expected): f'operator_{suffix}: crashes CPU-only omniscidb server v 5.3.1' ' [issue 115]') - omnisci.reset() - - omnisci(signature)(eval('operator_{}'.format(suffix))) - query = 'select operator_{suffix}'.format(**locals()) + \ '(' + ', '.join(map(str, args)) + ')' _, result = omnisci.sql_execute(query) diff --git a/rbc/tests/test_omnisci_template.py b/rbc/tests/test_omnisci_template.py index 4a516932..a1763ab6 100644 --- a/rbc/tests/test_omnisci_template.py +++ b/rbc/tests/test_omnisci_template.py @@ -51,6 +51,10 @@ def create_columns(omnisci): @pytest.mark.parametrize("size", (32,)) def test_template_text(omnisci, size): + if omnisci.has_cuda: + omnisci.require_version( + (5, 8), "Requires omniscidb-internal PR 5809", label='PR5809') + fn = "ct_binding_template" table = f"{omnisci.base_name}_{size}" base = f"base_{size}" @@ -71,6 +75,10 @@ def test_template_text(omnisci, size): @pytest.mark.parametrize("col", ("i4", "f4")) def test_template_number(omnisci, col): + if omnisci.has_cuda: + omnisci.require_version( + (5, 8), "Requires omniscidb-internal PR 5809", label='PR5809') + fn = "ct_binding_template" table = omnisci.table_name @@ -106,7 +114,7 @@ def test_template_columnlist_number(omnisci, col, out): @pytest.mark.parametrize("col,out", zip(("i4", "f4"), (10, 20))) def test_template_column_number(omnisci, col, out): - omnisci.require_version((5, 8), "Requires omniscidb-internal PR #5770", label="PR5770") + omnisci.require_version((5, 8), "Requires omniscidb-internal PR #5770") fn = "ct_binding_column" table = omnisci.table_name