def test_vectorize_explicit_signature(self): def _check_explicit_signature(sig): f = vectorize([sig], nopython=True)(mul_usecase) # This isn't really right but we can't do better than this, # since Numpy's ufuncs don't store the metadata of return types. # Related to https://github.com/numpy/numpy/issues/5429 self.assertPreciseEqual(f(TD(2), 3), TD(6)) # Test passing the signature in object form (issue #917) sig = types.NPTimedelta('s')(types.NPTimedelta('s'), types.int64) _check_explicit_signature(sig) # Same with the signature in string form sig = "NPTimedelta('s')(NPTimedelta('s'), int64)" _check_explicit_signature(sig)
def typer(val1, val2): if is_dt64_series_typ(val1) and val2 == pandas_timestamp_type: return SeriesType(types.NPTimedelta('ns')) from hpat.hiframes.pd_index_ext import DatetimeIndexType if isinstance(val1, DatetimeIndexType) and val2 == pandas_timestamp_type: from hpat.hiframes.pd_index_ext import TimedeltaIndexType return TimedeltaIndexType(False)
def generic(self, args, kws): if len(args) == 1: # Guard against unary - return left, right = args if isinstance(left, types.NPDatetime) and isinstance(right, types.NPDatetime): # All units compatible! Yoohoo! unit = npdatetime.get_best_unit(left.unit, right.unit) return signature(types.NPTimedelta(unit), left, right)
def test_call_notation(self): # Function call signature i = types.int32 d = types.double self.assertEqual(i(), typing.signature(i)) self.assertEqual(i(d), typing.signature(i, d)) self.assertEqual(i(d, d), typing.signature(i, d, d)) # Value cast self.assertPreciseEqual(i(42.5), 42) self.assertPreciseEqual(d(-5), -5.0) ty = types.NPDatetime('Y') self.assertPreciseEqual(ty('1900'), np.datetime64('1900', 'Y')) self.assertPreciseEqual(ty('NaT'), np.datetime64('NaT', 'Y')) ty = types.NPTimedelta('s') self.assertPreciseEqual(ty(5), np.timedelta64(5, 's')) self.assertPreciseEqual(ty('NaT'), np.timedelta64('NaT', 's')) ty = types.NPTimedelta('') self.assertPreciseEqual(ty(5), np.timedelta64(5)) self.assertPreciseEqual(ty('NaT'), np.timedelta64('NaT'))
def test_call_notation(self): # Function call signature i = types.int32 d = types.double self.assertEqual(i(), typing.signature(i)) self.assertEqual(i(d), typing.signature(i, d)) self.assertEqual(i(d, d), typing.signature(i, d, d)) # Value cast self.assertPreciseEqual(i(42.5), 42) self.assertPreciseEqual(d(-5), -5.0) ty = types.NPDatetime('Y') self.assertPreciseEqual(ty('1900'), np.datetime64('1900', 'Y')) if numpy_version < (1,16): # FIXME: workaround for known NumPy 1.16 issue self.assertPreciseEqual(ty('NaT'), np.datetime64('NaT', 'Y')) ty = types.NPTimedelta('s') self.assertPreciseEqual(ty(5), np.timedelta64(5, 's')) if numpy_version < (1,16): # FIXME: workaround for known NumPy 1.16 issue self.assertPreciseEqual(ty('NaT'), np.timedelta64('NaT', 's')) ty = types.NPTimedelta('') self.assertPreciseEqual(ty(5), np.timedelta64(5)) if numpy_version < (1,16): # FIXME: workaround for known NumPy 1.16 issue self.assertPreciseEqual(ty('NaT'), np.timedelta64('NaT'))
def test_jit_explicit_signature(self): def _check_explicit_signature(sig): f = jit(sig, nopython=True)(add_usecase) # Just a sanity check args = DT(1, 'ms'), TD(2, 'us') expected = add_usecase(*args) self.assertPreciseEqual(f(*args), expected) # Test passing the signature in object form sig = types.NPDatetime('us')(types.NPDatetime('ms'), types.NPTimedelta('us')) _check_explicit_signature(sig) # Same with the signature in string form sig = "NPDatetime('us')(NPDatetime('ms'), NPTimedelta('us'))" _check_explicit_signature(sig)
def test_print_values(self): """ Test printing a single argument value. """ pyfunc = print_value def check_values(typ, values): cr = compile_isolated(pyfunc, (typ,)) cfunc = cr.entry_point for val in values: with captured_stdout(): cfunc(val) self.assertEqual(sys.stdout.getvalue(), str(val) + '\n') # Various scalars check_values(types.int32, (1, -234)) check_values(types.int64, (1, -234, 123456789876543210, -123456789876543210)) check_values(types.uint64, (1, 234, 123456789876543210, 2**63 + 123)) check_values(types.boolean, (True, False)) check_values(types.float64, (1.5, 100.0**10.0, float('nan'))) check_values(types.complex64, (1+1j,)) check_values(types.NPTimedelta('ms'), (np.timedelta64(100, 'ms'),)) cr = compile_isolated(pyfunc, (types.float32,)) cfunc = cr.entry_point with captured_stdout(): cfunc(1.1) # Float32 will lose precision got = sys.stdout.getvalue() expect = '1.10000002384' self.assertTrue(got.startswith(expect)) self.assertTrue(got.endswith('\n')) # NRT-enabled type with self.assertNoNRTLeak(): x = [1, 3, 5, 7] with self.assertRefCount(x): check_values(types.List(types.int32), (x,)) # Array will have to use object mode arraytype = types.Array(types.int32, 1, 'C') cr = compile_isolated(pyfunc, (arraytype,), flags=enable_pyobj_flags) cfunc = cr.entry_point with captured_stdout(): cfunc(np.arange(10)) self.assertEqual(sys.stdout.getvalue(), '[0 1 2 3 4 5 6 7 8 9]\n')
class MaskedConstructor(ConcreteTemplate): key = api.Masked units = ["ns", "ms", "us", "s"] datetime_cases = {types.NPDatetime(u) for u in units} timedelta_cases = {types.NPTimedelta(u) for u in units} cases = [ nb_signature(MaskedType(t), t, types.boolean) for t in ( types.integer_domain | types.real_domain | datetime_cases | timedelta_cases | {types.boolean} ) ]
def test_atomic_types(self): for unit in ('M', 'ms'): ty = types.NPDatetime(unit) self.check_pickling(ty) ty = types.NPTimedelta(unit) self.check_pickling(ty)
def test_ufunc_find_matching_loop(self): f = numpy_support.ufunc_find_matching_loop np_add = FakeUFunc(_add_types) np_mul = FakeUFunc(_mul_types) np_isnan = FakeUFunc(_isnan_types) np_sqrt = FakeUFunc(_sqrt_types) def check(ufunc, input_types, sigs, output_types=()): """ Check that ufunc_find_matching_loop() finds one of the given *sigs* for *ufunc*, *input_types* and optional *output_types*. """ loop = f(ufunc, input_types + output_types) self.assertTrue(loop) if isinstance(sigs, str): sigs = (sigs, ) self.assertIn( loop.ufunc_sig, sigs, "inputs=%s and outputs=%s should have selected " "one of %s, got %s" % (input_types, output_types, sigs, loop.ufunc_sig)) self.assertEqual(len(loop.numpy_inputs), len(loop.inputs)) self.assertEqual(len(loop.numpy_outputs), len(loop.outputs)) if not output_types: # Add explicit outputs and check the result is the same loop_explicit = f(ufunc, list(input_types) + loop.outputs) self.assertEqual(loop_explicit, loop) else: self.assertEqual(loop.outputs, list(output_types)) # Round-tripping inputs and outputs loop_rt = f(ufunc, loop.inputs + loop.outputs) self.assertEqual(loop_rt, loop) return loop def check_exact(ufunc, input_types, sigs, output_types=()): """ Like check(), but also ensure no casting of inputs occurred. """ loop = check(ufunc, input_types, sigs, output_types) self.assertEqual(loop.inputs, list(input_types)) def check_no_match(ufunc, input_types): loop = f(ufunc, input_types) self.assertIs(loop, None) # Exact matching for number types check_exact(np_add, (types.bool_, types.bool_), '??->?') check_exact(np_add, (types.int8, types.int8), 'bb->b') check_exact(np_add, (types.uint8, types.uint8), 'BB->B') check_exact(np_add, (types.int64, types.int64), ('ll->l', 'qq->q')) check_exact(np_add, (types.uint64, types.uint64), ('LL->L', 'QQ->Q')) check_exact(np_add, (types.float32, types.float32), 'ff->f') check_exact(np_add, (types.float64, types.float64), 'dd->d') check_exact(np_add, (types.complex64, types.complex64), 'FF->F') check_exact(np_add, (types.complex128, types.complex128), 'DD->D') # Exact matching for datetime64 and timedelta64 types check_exact(np_add, (types.NPTimedelta('s'), types.NPTimedelta('s')), 'mm->m', output_types=(types.NPTimedelta('s'), )) check_exact(np_add, (types.NPTimedelta('ms'), types.NPDatetime('s')), 'mM->M', output_types=(types.NPDatetime('ms'), )) check_exact(np_add, (types.NPDatetime('s'), types.NPTimedelta('s')), 'Mm->M', output_types=(types.NPDatetime('s'), )) check_exact(np_mul, (types.NPTimedelta('s'), types.int64), 'mq->m', output_types=(types.NPTimedelta('s'), )) check_exact(np_mul, (types.float64, types.NPTimedelta('s')), 'dm->m', output_types=(types.NPTimedelta('s'), )) # Mix and match number types, with casting check(np_add, (types.bool_, types.int8), 'bb->b') check(np_add, (types.uint8, types.bool_), 'BB->B') check(np_add, (types.int16, types.uint16), 'ii->i') check(np_add, (types.complex64, types.float64), 'DD->D') check(np_add, (types.float64, types.complex64), 'DD->D') # Integers, when used together with floating-point numbers, # should cast to any real or complex (see #2006) int_types = [types.int32, types.uint32, types.int64, types.uint64] for intty in int_types: check(np_add, (types.float32, intty), 'ff->f') check(np_add, (types.float64, intty), 'dd->d') check(np_add, (types.complex64, intty), 'FF->F') check(np_add, (types.complex128, intty), 'DD->D') # However, when used alone, they should cast only to # floating-point types of sufficient precision # (typical use case: np.sqrt(2) should give an accurate enough value) for intty in int_types: check(np_sqrt, (intty, ), 'd->d') check(np_isnan, (intty, ), 'd->?') # With some timedelta64 arguments as well check(np_mul, (types.NPTimedelta('s'), types.int32), 'mq->m', output_types=(types.NPTimedelta('s'), )) check(np_mul, (types.NPTimedelta('s'), types.uint32), 'mq->m', output_types=(types.NPTimedelta('s'), )) check(np_mul, (types.NPTimedelta('s'), types.float32), 'md->m', output_types=(types.NPTimedelta('s'), )) check(np_mul, (types.float32, types.NPTimedelta('s')), 'dm->m', output_types=(types.NPTimedelta('s'), )) # No match check_no_match(np_add, (types.NPDatetime('s'), types.NPDatetime('s'))) # No implicit casting from int64 to timedelta64 (Numpy would allow # this). check_no_match(np_add, (types.NPTimedelta('s'), types.int64))
def is_timedelta64_series_typ(t): return isinstance(t, SeriesType) and t.dtype == types.NPTimedelta('ns')
def test_ufunc_find_matching_loop(self): f = numpy_support.ufunc_find_matching_loop np_add = FakeUFunc(_add_types) np_mul = FakeUFunc(_mul_types) def check(ufunc, input_types, sigs, output_types=()): """ Check that ufunc_find_matching_loop() finds one of the given *sigs* for *ufunc*, *input_types* and optional *output_types*. """ loop = f(ufunc, input_types + output_types) self.assertTrue(loop) if isinstance(sigs, str): sigs = (sigs, ) self.assertIn(loop.ufunc_sig, sigs) self.assertEqual(len(loop.numpy_inputs), len(loop.inputs)) self.assertEqual(len(loop.numpy_outputs), len(loop.outputs)) if not output_types: # Add explicit outputs and check the result is the same loop_explicit = f(ufunc, list(input_types) + loop.outputs) self.assertEqual(loop_explicit, loop) else: self.assertEqual(loop.outputs, list(output_types)) # Round-tripping inputs and outputs loop_rt = f(ufunc, loop.inputs + loop.outputs) self.assertEqual(loop_rt, loop) return loop def check_exact(ufunc, input_types, sigs, output_types=()): loop = check(ufunc, input_types, sigs, output_types) self.assertEqual(loop.inputs, list(input_types)) def check_no_match(ufunc, input_types): loop = f(ufunc, input_types) self.assertIs(loop, None) # Exact matching for number types check_exact(np_add, (types.bool_, types.bool_), '??->?') check_exact(np_add, (types.int8, types.int8), 'bb->b') check_exact(np_add, (types.uint8, types.uint8), 'BB->B') check_exact(np_add, (types.int64, types.int64), ('ll->l', 'qq->q')) check_exact(np_add, (types.uint64, types.uint64), ('LL->L', 'QQ->Q')) check_exact(np_add, (types.float32, types.float32), 'ff->f') check_exact(np_add, (types.float64, types.float64), 'dd->d') check_exact(np_add, (types.complex64, types.complex64), 'FF->F') check_exact(np_add, (types.complex128, types.complex128), 'DD->D') # Exact matching for datetime64 and timedelta64 types check_exact(np_add, (types.NPTimedelta('s'), types.NPTimedelta('s')), 'mm->m', output_types=(types.NPTimedelta('s'), )) check_exact(np_add, (types.NPTimedelta('ms'), types.NPDatetime('s')), 'mM->M', output_types=(types.NPDatetime('ms'), )) check_exact(np_add, (types.NPDatetime('s'), types.NPTimedelta('s')), 'Mm->M', output_types=(types.NPDatetime('s'), )) check_exact(np_mul, (types.NPTimedelta('s'), types.int64), 'mq->m', output_types=(types.NPTimedelta('s'), )) check_exact(np_mul, (types.float64, types.NPTimedelta('s')), 'dm->m', output_types=(types.NPTimedelta('s'), )) # Mix and match number types, with casting check(np_add, (types.bool_, types.int8), 'bb->b') check(np_add, (types.uint8, types.bool_), 'BB->B') check(np_add, (types.int16, types.uint16), 'ii->i') check(np_add, (types.complex64, types.float64), 'DD->D') check(np_add, (types.float64, types.complex64), 'DD->D') # With some timedelta64 arguments as well check(np_mul, (types.NPTimedelta('s'), types.int32), 'mq->m', output_types=(types.NPTimedelta('s'), )) check(np_mul, (types.NPTimedelta('s'), types.uint32), 'mq->m', output_types=(types.NPTimedelta('s'), )) check(np_mul, (types.NPTimedelta('s'), types.float32), 'md->m', output_types=(types.NPTimedelta('s'), )) check(np_mul, (types.float32, types.NPTimedelta('s')), 'dm->m', output_types=(types.NPTimedelta('s'), )) # No match check_no_match(np_add, (types.NPDatetime('s'), types.NPDatetime('s'))) # No implicit casting from int64 to timedelta64 (Numpy would allow # this). check_no_match(np_add, (types.NPTimedelta('s'), types.int64))
def typer(val): return types.NPTimedelta('ns')
return lambda val: hash(dt64_to_integer(val)) # ----------------------------------------------------------- def timedelta64_to_integer(val): return int(val) @type_callable(timedelta64_to_integer) def type_dt64_to_int(context): def typer(val): return types.int64 return typer @lower_builtin(timedelta64_to_integer, types.NPTimedelta('ns')) def impl_dt64_to_int(context, builder, sig, args): return args[0] # ----------------------------------------------------------- @lower_builtin(myref, types.int32) @lower_builtin(myref, types.int64) @lower_builtin(myref, types.IntegerLiteral) def impl_myref_int32(context, builder, sig, args): typ = types.voidptr val = args[0] assert isinstance(val, lir.instructions.LoadInstr) return builder.bitcast(val.operands[0], lir.IntType(8).as_pointer())
from numba.extending import (models, register_model, lower_cast, infer_getattr, type_callable, infer, overload, make_attribute_wrapper, box) from numba.typing.templates import (infer_global, AbstractTemplate, signature, AttributeTemplate, bound_function) from numba.targets.boxing import box_array import sdc from sdc.str_ext import string_type import sdc.hiframes from sdc.hiframes.pd_series_ext import (is_str_series_typ, string_array_type, SeriesType) from sdc.hiframes.pd_timestamp_ext import pandas_timestamp_type, datetime_date_type from sdc.hiframes.datetime_date_ext import array_datetime_date _dt_index_data_typ = types.Array(types.NPDatetime('ns'), 1, 'C') _timedelta_index_data_typ = types.Array(types.NPTimedelta('ns'), 1, 'C') class DatetimeIndexType(types.IterableType): """Temporary type class for DatetimeIndex objects. """ def __init__(self, is_named=False): # TODO: support other properties like freq/tz/dtype/yearfirst? self.is_named = is_named super(DatetimeIndexType, self).__init__( name="DatetimeIndex(is_named = {})".format(is_named)) def copy(self): # XXX is copy necessary? return DatetimeIndexType(self.is_named)
@property def is_f_contig(self): # same as Buffer return self.layout == 'F' or (self.ndim <= 1 and self.layout in 'CF') @property def is_contig(self): # same as Buffer return self.layout in 'CF' string_series_type = SeriesType(string_type, 1, 'C', True) # TODO: create a separate DatetimeIndex type from Series dt_index_series_type = SeriesType(types.NPDatetime('ns'), 1, 'C') timedelta_index_series_type = SeriesType(types.NPTimedelta('ns'), 1, 'C') date_series_type = SeriesType(datetime_date_type, 1, 'C') # register_model(SeriesType)(models.ArrayModel) # need to define model since fix_df_array overload goes to native code @register_model(SeriesType) class SeriesModel(models.StructModel): def __init__(self, dmm, fe_type): # TODO: types other than Array and StringArray? if fe_type.dtype == string_type: members = hpat.str_arr_ext.str_arr_model_members else: ndim = 1 members = [ ('meminfo', types.MemInfoPointer(fe_type.dtype)),