@@ -5,7 +5,7 @@ from cython cimport Py_ssize_t
55
66import numpy as np
77cimport numpy as cnp
8- from numpy cimport ndarray, int64_t
8+ from numpy cimport ndarray, int64_t, int32_t
99cnp.import_array()
1010
1111from util cimport is_string_object, get_nat
@@ -45,12 +45,12 @@ cdef int RESO_MIN = 4
4545cdef int RESO_HR = 5
4646cdef 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