1
1
# cython: boundscheck=False, wraparound=False, cdivision=True
2
-
3
2
from libc.math cimport (
4
3
round ,
5
4
signbit,
6
5
sqrt,
6
+ pow ,
7
+ log10,
8
+ abs ,
9
+ isfinite,
7
10
)
8
11
from libcpp.deque cimport deque
9
12
from libcpp.stack cimport stack
10
13
from libcpp.unordered_map cimport unordered_map
14
+ from libcpp cimport bool
15
+
11
16
12
17
from pandas._libs.algos cimport TiebreakEnumType
13
18
@@ -21,6 +26,8 @@ from numpy cimport (
21
26
ndarray,
22
27
)
23
28
29
+
30
+
24
31
cnp.import_array()
25
32
26
33
import cython
@@ -724,6 +731,46 @@ cdef float64_t calc_kurt(int64_t minp, int64_t nobs,
724
731
725
732
return result
726
733
734
+ cdef void update_sum_of_window( float64_t val,
735
+ float64_t ** x_value,
736
+ float64_t ** comp_value,
737
+ int power_of_element,
738
+ bool add_mode, # 1 for add_kurt, 0 for remove_kurt
739
+ ) noexcept nogil:
740
+
741
+ cdef:
742
+ float64_t val_raised, new_sum
743
+ bool val_length_flag, x_length_flag
744
+
745
+ if add_mode:
746
+ val_raised = pow (val, power_of_element)
747
+ else :
748
+ val_raised = - pow (val, power_of_element)
749
+
750
+ x_length_flag = abs (log10(abs (x_value[0 ][0 ]))) > 15 and isfinite(abs (log10(abs (x_value[0 ][0 ])))) == 1
751
+ val_length_flag = abs (log10(abs (val_raised))) > 15 and isfinite(abs (log10(abs (val_raised)))) == 1
752
+
753
+ # We'll try to maintain comp_value as the counter for
754
+ # numbers <1e15 to keep it from getting rounded out.
755
+ if x_length_flag and val_length_flag:
756
+ # Both > 1e15 or < 1-e15
757
+ x_value[0 ][0 ] += val_raised
758
+
759
+ elif x_length_flag:
760
+ comp_value[0 ][0 ] += val_raised
761
+
762
+
763
+ elif val_length_flag:
764
+ comp_value[0 ][0 ] += x_value[0 ][0 ]
765
+ x_value[0 ][0 ] = val_raised
766
+
767
+ else :
768
+ # Neither are >1e15/<1e-15, safe to proceed
769
+ x_value[0 ][0 ] += val_raised
770
+
771
+ if comp_value[0 ][0 ] != 0 :
772
+ x_value[0 ][0 ] += comp_value[0 ][0 ]
773
+ comp_value[0 ][0 ] = 0
727
774
728
775
cdef void add_kurt(float64_t val, int64_t * nobs,
729
776
float64_t * x, float64_t * xx,
@@ -736,29 +783,15 @@ cdef void add_kurt(float64_t val, int64_t *nobs,
736
783
float64_t * prev_value
737
784
) noexcept nogil:
738
785
""" add a value from the kurotic calc """
739
- cdef:
740
- float64_t y, t
741
786
742
787
# Not NaN
743
788
if val == val:
744
789
nobs[0 ] = nobs[0 ] + 1
745
790
746
- y = val - compensation_x[0 ]
747
- t = x[0 ] + y
748
- compensation_x[0 ] = t - x[0 ] - y
749
- x[0 ] = t
750
- y = val * val - compensation_xx[0 ]
751
- t = xx[0 ] + y
752
- compensation_xx[0 ] = t - xx[0 ] - y
753
- xx[0 ] = t
754
- y = val * val * val - compensation_xxx[0 ]
755
- t = xxx[0 ] + y
756
- compensation_xxx[0 ] = t - xxx[0 ] - y
757
- xxx[0 ] = t
758
- y = val * val * val * val - compensation_xxxx[0 ]
759
- t = xxxx[0 ] + y
760
- compensation_xxxx[0 ] = t - xxxx[0 ] - y
761
- xxxx[0 ] = t
791
+ update_sum_of_window(val, & x, & compensation_x, 1 , 1 )
792
+ update_sum_of_window(val, & xx, & compensation_xx, 2 , 1 )
793
+ update_sum_of_window(val, & xxx, & compensation_xxx, 3 , 1 )
794
+ update_sum_of_window(val, & xxxx, & compensation_xxxx, 4 , 1 )
762
795
763
796
# GH#42064, record num of same values to remove floating point artifacts
764
797
if val == prev_value[0 ]:
@@ -768,7 +801,6 @@ cdef void add_kurt(float64_t val, int64_t *nobs,
768
801
num_consecutive_same_value[0 ] = 1
769
802
prev_value[0 ] = val
770
803
771
-
772
804
cdef void remove_kurt(float64_t val, int64_t * nobs,
773
805
float64_t * x, float64_t * xx,
774
806
float64_t * xxx, float64_t * xxxx,
@@ -777,40 +809,25 @@ cdef void remove_kurt(float64_t val, int64_t *nobs,
777
809
float64_t * compensation_xxx,
778
810
float64_t * compensation_xxxx) noexcept nogil:
779
811
""" remove a value from the kurotic calc """
780
- cdef:
781
- float64_t y, t
782
812
783
813
# Not NaN
784
814
if val == val:
785
815
nobs[0 ] = nobs[0 ] - 1
786
816
787
- y = - val - compensation_x[0 ]
788
- t = x[0 ] + y
789
- compensation_x[0 ] = t - x[0 ] - y
790
- x[0 ] = t
791
- y = - val * val - compensation_xx[0 ]
792
- t = xx[0 ] + y
793
- compensation_xx[0 ] = t - xx[0 ] - y
794
- xx[0 ] = t
795
- y = - val * val * val - compensation_xxx[0 ]
796
- t = xxx[0 ] + y
797
- compensation_xxx[0 ] = t - xxx[0 ] - y
798
- xxx[0 ] = t
799
- y = - val * val * val * val - compensation_xxxx[0 ]
800
- t = xxxx[0 ] + y
801
- compensation_xxxx[0 ] = t - xxxx[0 ] - y
802
- xxxx[0 ] = t
803
-
817
+ update_sum_of_window(val, & x, & compensation_x, 1 , 0 )
818
+ update_sum_of_window(val, & xx, & compensation_xx, 2 , 0 )
819
+ update_sum_of_window(val, & xxx, & compensation_xxx, 3 , 0 )
820
+ update_sum_of_window(val, & xxxx, & compensation_xxxx, 4 , 0 )
804
821
805
822
def roll_kurt (ndarray[float64_t] values , ndarray[int64_t] start ,
806
823
ndarray[int64_t] end , int64_t minp ) -> np.ndarray:
807
824
cdef:
808
825
Py_ssize_t i , j
809
826
float64_t val , mean_val , min_val , sum_val = 0
810
- float64_t compensation_xxxx_add , compensation_xxxx_remove
811
- float64_t compensation_xxx_remove , compensation_xxx_add
812
- float64_t compensation_xx_remove , compensation_xx_add
813
- float64_t compensation_x_remove , compensation_x_add
827
+ float64_t compensation_xxxx
828
+ float64_t compensation_xxx
829
+ float64_t compensation_xx
830
+ float64_t compensation_x
814
831
float64_t x , xx , xxx , xxxx
815
832
float64_t prev_value
816
833
int64_t nobs , s , e , num_consecutive_same_value
@@ -851,16 +868,16 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
851
868
prev_value = values[s]
852
869
num_consecutive_same_value = 0
853
870
854
- compensation_xxxx_add = compensation_xxxx_remove = 0
855
- compensation_xxx_remove = compensation_xxx_add = 0
856
- compensation_xx_remove = compensation_xx_add = 0
857
- compensation_x_remove = compensation_x_add = 0
871
+ compensation_xxxx = 0
872
+ compensation_xxx = 0
873
+ compensation_xx = 0
874
+ compensation_x = 0
858
875
x = xx = xxx = xxxx = 0
859
876
nobs = 0
860
877
for j in range (s, e):
861
878
add_kurt(values_copy[j], & nobs, & x, & xx, & xxx, & xxxx,
862
- & compensation_x_add , & compensation_xx_add ,
863
- & compensation_xxx_add , & compensation_xxxx_add ,
879
+ & compensation_x , & compensation_xx ,
880
+ & compensation_xxx , & compensation_xxxx ,
864
881
& num_consecutive_same_value, & prev_value)
865
882
866
883
else :
@@ -870,14 +887,14 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
870
887
# calculate deletes
871
888
for j in range (start[i - 1 ], s):
872
889
remove_kurt(values_copy[j], & nobs, & x, & xx, & xxx, & xxxx,
873
- & compensation_x_remove , & compensation_xx_remove ,
874
- & compensation_xxx_remove , & compensation_xxxx_remove )
890
+ & compensation_x , & compensation_xx ,
891
+ & compensation_xxx , & compensation_xxxx )
875
892
876
893
# calculate adds
877
894
for j in range (end[i - 1 ], e):
878
895
add_kurt(values_copy[j], & nobs, & x, & xx, & xxx, & xxxx,
879
- & compensation_x_add , & compensation_xx_add ,
880
- & compensation_xxx_add , & compensation_xxxx_add ,
896
+ & compensation_x , & compensation_xx ,
897
+ & compensation_xxx , & compensation_xxxx ,
881
898
& num_consecutive_same_value, & prev_value)
882
899
883
900
output[i] = calc_kurt(minp, nobs, x, xx, xxx, xxxx,
0 commit comments