Skip to content

Commit 6028a5b

Browse files
jbrockmendeljreback
authored andcommitted
PERF: typing and cdefs for tslibs.resolution (#21452)
1 parent 2a33926 commit 6028a5b

File tree

1 file changed

+42
-29
lines changed

1 file changed

+42
-29
lines changed

pandas/_libs/tslibs/resolution.pyx

+42-29
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ from cython cimport Py_ssize_t
55

66
import numpy as np
77
cimport numpy as cnp
8-
from numpy cimport ndarray, int64_t
8+
from numpy cimport ndarray, int64_t, int32_t
99
cnp.import_array()
1010

1111
from util cimport is_string_object, get_nat
@@ -45,12 +45,12 @@ cdef int RESO_MIN = 4
4545
cdef int RESO_HR = 5
4646
cdef int RESO_DAY = 6
4747

48-
_ONE_MICRO = 1000L
49-
_ONE_MILLI = _ONE_MICRO * 1000
50-
_ONE_SECOND = _ONE_MILLI * 1000
51-
_ONE_MINUTE = 60 * _ONE_SECOND
52-
_ONE_HOUR = 60 * _ONE_MINUTE
53-
_ONE_DAY = 24 * _ONE_HOUR
48+
_ONE_MICRO = <int64_t>1000L
49+
_ONE_MILLI = <int64_t>(_ONE_MICRO * 1000)
50+
_ONE_SECOND = <int64_t>(_ONE_MILLI * 1000)
51+
_ONE_MINUTE = <int64_t>(60 * _ONE_SECOND)
52+
_ONE_HOUR = <int64_t>(60 * _ONE_MINUTE)
53+
_ONE_DAY = <int64_t>(24 * _ONE_HOUR)
5454

5555
# ----------------------------------------------------------------------
5656

@@ -350,7 +350,7 @@ class Resolution(object):
350350
# TODO: this is non performant logic here (and duplicative) and this
351351
# simply should call unique_1d directly
352352
# plus no reason to depend on khash directly
353-
cdef unique_deltas(ndarray[int64_t] arr):
353+
cdef ndarray[int64_t, ndim=1] unique_deltas(ndarray[int64_t] arr):
354354
cdef:
355355
Py_ssize_t i, n = len(arr)
356356
int64_t val
@@ -374,21 +374,27 @@ cdef unique_deltas(ndarray[int64_t] arr):
374374
return result
375375

376376

377-
def _is_multiple(us, mult):
377+
cdef inline bint _is_multiple(int64_t us, int64_t mult):
378378
return us % mult == 0
379379

380380

381-
def _maybe_add_count(base, count):
381+
cdef inline str _maybe_add_count(str base, int64_t count):
382382
if count != 1:
383-
return '{count}{base}'.format(count=int(count), base=base)
383+
return '{count}{base}'.format(count=count, base=base)
384384
else:
385385
return base
386386

387387

388-
class _FrequencyInferer(object):
388+
cdef class _FrequencyInferer(object):
389389
"""
390390
Not sure if I can avoid the state machine here
391391
"""
392+
cdef public:
393+
object index
394+
object values
395+
bint warn
396+
bint is_monotonic
397+
dict _cache
392398

393399
def __init__(self, index, warn=True):
394400
self.index = index
@@ -476,16 +482,23 @@ class _FrequencyInferer(object):
476482
def rep_stamp(self):
477483
return Timestamp(self.values[0])
478484

479-
def month_position_check(self):
485+
cdef month_position_check(self):
480486
# TODO: cythonize this, very slow
481-
calendar_end = True
482-
business_end = True
483-
calendar_start = True
484-
business_start = True
485-
486-
years = self.fields['Y']
487-
months = self.fields['M']
488-
days = self.fields['D']
487+
cdef:
488+
int32_t daysinmonth, y, m, d
489+
bint calendar_end = True
490+
bint business_end = True
491+
bint calendar_start = True
492+
bint business_start = True
493+
bint cal
494+
int32_t[:] years
495+
int32_t[:] months
496+
int32_t[:] days
497+
498+
fields = self.fields
499+
years = fields['Y']
500+
months = fields['M']
501+
days = fields['D']
489502
weekdays = self.index.dayofweek
490503

491504
for y, m, d, wd in zip(years, months, days, weekdays):
@@ -525,7 +538,7 @@ class _FrequencyInferer(object):
525538
def ydiffs(self):
526539
return unique_deltas(self.fields['Y'].astype('i8'))
527540

528-
def _infer_daily_rule(self):
541+
cdef _infer_daily_rule(self):
529542
annual_rule = self._get_annual_rule()
530543
if annual_rule:
531544
nyears = self.ydiffs[0]
@@ -562,7 +575,7 @@ class _FrequencyInferer(object):
562575
if wom_rule:
563576
return wom_rule
564577

565-
def _get_annual_rule(self):
578+
cdef _get_annual_rule(self):
566579
if len(self.ydiffs) > 1:
567580
return None
568581

@@ -573,7 +586,7 @@ class _FrequencyInferer(object):
573586
return {'cs': 'AS', 'bs': 'BAS',
574587
'ce': 'A', 'be': 'BA'}.get(pos_check)
575588

576-
def _get_quarterly_rule(self):
589+
cdef _get_quarterly_rule(self):
577590
if len(self.mdiffs) > 1:
578591
return None
579592

@@ -584,14 +597,14 @@ class _FrequencyInferer(object):
584597
return {'cs': 'QS', 'bs': 'BQS',
585598
'ce': 'Q', 'be': 'BQ'}.get(pos_check)
586599

587-
def _get_monthly_rule(self):
600+
cdef _get_monthly_rule(self):
588601
if len(self.mdiffs) > 1:
589602
return None
590603
pos_check = self.month_position_check()
591604
return {'cs': 'MS', 'bs': 'BMS',
592605
'ce': 'M', 'be': 'BM'}.get(pos_check)
593606

594-
def _is_business_daily(self):
607+
cdef bint _is_business_daily(self):
595608
# quick check: cannot be business daily
596609
if self.day_deltas != [1, 3]:
597610
return False
@@ -604,7 +617,7 @@ class _FrequencyInferer(object):
604617
return np.all(((weekdays == 0) & (shifts == 3)) |
605618
((weekdays > 0) & (weekdays <= 4) & (shifts == 1)))
606619

607-
def _get_wom_rule(self):
620+
cdef _get_wom_rule(self):
608621
# wdiffs = unique(np.diff(self.index.week))
609622
# We also need -47, -49, -48 to catch index spanning year boundary
610623
# if not lib.ismember(wdiffs, set([4, 5, -47, -49, -48])).all():
@@ -627,9 +640,9 @@ class _FrequencyInferer(object):
627640
return 'WOM-{week}{weekday}'.format(week=week, weekday=wd)
628641

629642

630-
class _TimedeltaFrequencyInferer(_FrequencyInferer):
643+
cdef class _TimedeltaFrequencyInferer(_FrequencyInferer):
631644

632-
def _infer_daily_rule(self):
645+
cdef _infer_daily_rule(self):
633646
if self.is_unique:
634647
days = self.deltas[0] / _ONE_DAY
635648
if days % 7 == 0:

0 commit comments

Comments
 (0)