Skip to content

Commit 100947c

Browse files
committed
is_monotonic
1 parent 5bbeb56 commit 100947c

File tree

2 files changed

+185
-113
lines changed

2 files changed

+185
-113
lines changed

pandas/src/generate_code.py

+37-25
Original file line numberDiff line numberDiff line change
@@ -609,23 +609,33 @@ def is_monotonic_%(name)s(ndarray[%(c_type)s] arr, bint timelike):
609609
if timelike and arr[0] == iNaT:
610610
return False, False, None
611611
612-
prev = arr[0]
613-
for i in range(1, n):
614-
cur = arr[i]
615-
if timelike and cur == iNaT:
616-
return False, False, None
617-
if cur < prev:
618-
is_monotonic_inc = 0
619-
elif cur > prev:
620-
is_monotonic_dec = 0
621-
elif cur == prev:
622-
is_unique = 0
623-
else:
624-
# cur or prev is NaN
625-
return False, False, None
626-
if not is_monotonic_inc and not is_monotonic_dec:
627-
return False, False, None
628-
prev = cur
612+
%(nogil)s
613+
%(tab)sprev = arr[0]
614+
%(tab)sfor i in range(1, n):
615+
%(tab)s cur = arr[i]
616+
%(tab)s if timelike and cur == iNaT:
617+
%(tab)s is_unique = 0
618+
%(tab)s is_monotonic_inc = 0
619+
%(tab)s is_monotonic_dec = 0
620+
%(tab)s break
621+
%(tab)s if cur < prev:
622+
%(tab)s is_monotonic_inc = 0
623+
%(tab)s elif cur > prev:
624+
%(tab)s is_monotonic_dec = 0
625+
%(tab)s elif cur == prev:
626+
%(tab)s is_unique = 0
627+
%(tab)s else:
628+
%(tab)s # cur or prev is NaN
629+
%(tab)s is_unique = 0
630+
%(tab)s is_monotonic_inc = 0
631+
%(tab)s is_monotonic_dec = 0
632+
%(tab)s break
633+
%(tab)s if not is_monotonic_inc and not is_monotonic_dec:
634+
%(tab)s is_unique = 0
635+
%(tab)s is_monotonic_inc = 0
636+
%(tab)s is_monotonic_dec = 0
637+
%(tab)s break
638+
%(tab)s prev = cur
629639
return is_monotonic_inc, is_monotonic_dec, is_unique
630640
"""
631641

@@ -2462,22 +2472,24 @@ def generate_take_template(template, exclude=None):
24622472
def generate_from_template(template, exclude=None):
24632473
# name, ctype, capable of holding NA
24642474
function_list = [
2465-
('float64', 'float64_t', 'np.float64', True),
2466-
('float32', 'float32_t', 'np.float32', True),
2467-
('object', 'object', 'object', True),
2468-
('int32', 'int32_t', 'np.int32', False),
2469-
('int64', 'int64_t', 'np.int64', False),
2470-
('bool', 'uint8_t', 'np.bool', False)
2475+
('float64', 'float64_t', 'np.float64', True, True),
2476+
('float32', 'float32_t', 'np.float32', True, True),
2477+
('object', 'object', 'object', True, False),
2478+
('int32', 'int32_t', 'np.int32', False, True),
2479+
('int64', 'int64_t', 'np.int64', False, True),
2480+
('bool', 'uint8_t', 'np.bool', False, True)
24712481
]
24722482

24732483
output = StringIO()
2474-
for name, c_type, dtype, can_hold_na in function_list:
2484+
for name, c_type, dtype, can_hold_na, nogil in function_list:
24752485
if exclude is not None and name in exclude:
24762486
continue
24772487

24782488
func = template % {'name': name, 'c_type': c_type,
24792489
'dtype': dtype,
2480-
'raise_on_na': 'False' if can_hold_na else 'True'}
2490+
'raise_on_na': 'False' if can_hold_na else 'True',
2491+
'nogil' : 'with nogil:' if nogil else '',
2492+
'tab' : ' ' if nogil else '' }
24812493
output.write(func)
24822494
output.write("\n")
24832495
return output.getvalue()

pandas/src/generated.pyx

+148-88
Original file line numberDiff line numberDiff line change
@@ -1840,23 +1840,33 @@ def is_monotonic_float64(ndarray[float64_t] arr, bint timelike):
18401840
if timelike and arr[0] == iNaT:
18411841
return False, False, None
18421842

1843-
prev = arr[0]
1844-
for i in range(1, n):
1845-
cur = arr[i]
1846-
if timelike and cur == iNaT:
1847-
return False, False, None
1848-
if cur < prev:
1849-
is_monotonic_inc = 0
1850-
elif cur > prev:
1851-
is_monotonic_dec = 0
1852-
elif cur == prev:
1853-
is_unique = 0
1854-
else:
1855-
# cur or prev is NaN
1856-
return False, False, None
1857-
if not is_monotonic_inc and not is_monotonic_dec:
1858-
return False, False, None
1859-
prev = cur
1843+
with nogil:
1844+
prev = arr[0]
1845+
for i in range(1, n):
1846+
cur = arr[i]
1847+
if timelike and cur == iNaT:
1848+
is_unique = 0
1849+
is_monotonic_inc = 0
1850+
is_monotonic_dec = 0
1851+
break
1852+
if cur < prev:
1853+
is_monotonic_inc = 0
1854+
elif cur > prev:
1855+
is_monotonic_dec = 0
1856+
elif cur == prev:
1857+
is_unique = 0
1858+
else:
1859+
# cur or prev is NaN
1860+
is_unique = 0
1861+
is_monotonic_inc = 0
1862+
is_monotonic_dec = 0
1863+
break
1864+
if not is_monotonic_inc and not is_monotonic_dec:
1865+
is_unique = 0
1866+
is_monotonic_inc = 0
1867+
is_monotonic_dec = 0
1868+
break
1869+
prev = cur
18601870
return is_monotonic_inc, is_monotonic_dec, is_unique
18611871

18621872
@cython.boundscheck(False)
@@ -1888,23 +1898,33 @@ def is_monotonic_float32(ndarray[float32_t] arr, bint timelike):
18881898
if timelike and arr[0] == iNaT:
18891899
return False, False, None
18901900

1891-
prev = arr[0]
1892-
for i in range(1, n):
1893-
cur = arr[i]
1894-
if timelike and cur == iNaT:
1895-
return False, False, None
1896-
if cur < prev:
1897-
is_monotonic_inc = 0
1898-
elif cur > prev:
1899-
is_monotonic_dec = 0
1900-
elif cur == prev:
1901-
is_unique = 0
1902-
else:
1903-
# cur or prev is NaN
1904-
return False, False, None
1905-
if not is_monotonic_inc and not is_monotonic_dec:
1906-
return False, False, None
1907-
prev = cur
1901+
with nogil:
1902+
prev = arr[0]
1903+
for i in range(1, n):
1904+
cur = arr[i]
1905+
if timelike and cur == iNaT:
1906+
is_unique = 0
1907+
is_monotonic_inc = 0
1908+
is_monotonic_dec = 0
1909+
break
1910+
if cur < prev:
1911+
is_monotonic_inc = 0
1912+
elif cur > prev:
1913+
is_monotonic_dec = 0
1914+
elif cur == prev:
1915+
is_unique = 0
1916+
else:
1917+
# cur or prev is NaN
1918+
is_unique = 0
1919+
is_monotonic_inc = 0
1920+
is_monotonic_dec = 0
1921+
break
1922+
if not is_monotonic_inc and not is_monotonic_dec:
1923+
is_unique = 0
1924+
is_monotonic_inc = 0
1925+
is_monotonic_dec = 0
1926+
break
1927+
prev = cur
19081928
return is_monotonic_inc, is_monotonic_dec, is_unique
19091929

19101930
@cython.boundscheck(False)
@@ -1936,11 +1956,15 @@ def is_monotonic_object(ndarray[object] arr, bint timelike):
19361956
if timelike and arr[0] == iNaT:
19371957
return False, False, None
19381958

1959+
19391960
prev = arr[0]
19401961
for i in range(1, n):
19411962
cur = arr[i]
19421963
if timelike and cur == iNaT:
1943-
return False, False, None
1964+
is_unique = 0
1965+
is_monotonic_inc = 0
1966+
is_monotonic_dec = 0
1967+
break
19441968
if cur < prev:
19451969
is_monotonic_inc = 0
19461970
elif cur > prev:
@@ -1949,9 +1973,15 @@ def is_monotonic_object(ndarray[object] arr, bint timelike):
19491973
is_unique = 0
19501974
else:
19511975
# cur or prev is NaN
1952-
return False, False, None
1976+
is_unique = 0
1977+
is_monotonic_inc = 0
1978+
is_monotonic_dec = 0
1979+
break
19531980
if not is_monotonic_inc and not is_monotonic_dec:
1954-
return False, False, None
1981+
is_unique = 0
1982+
is_monotonic_inc = 0
1983+
is_monotonic_dec = 0
1984+
break
19551985
prev = cur
19561986
return is_monotonic_inc, is_monotonic_dec, is_unique
19571987

@@ -1984,23 +2014,33 @@ def is_monotonic_int32(ndarray[int32_t] arr, bint timelike):
19842014
if timelike and arr[0] == iNaT:
19852015
return False, False, None
19862016

1987-
prev = arr[0]
1988-
for i in range(1, n):
1989-
cur = arr[i]
1990-
if timelike and cur == iNaT:
1991-
return False, False, None
1992-
if cur < prev:
1993-
is_monotonic_inc = 0
1994-
elif cur > prev:
1995-
is_monotonic_dec = 0
1996-
elif cur == prev:
1997-
is_unique = 0
1998-
else:
1999-
# cur or prev is NaN
2000-
return False, False, None
2001-
if not is_monotonic_inc and not is_monotonic_dec:
2002-
return False, False, None
2003-
prev = cur
2017+
with nogil:
2018+
prev = arr[0]
2019+
for i in range(1, n):
2020+
cur = arr[i]
2021+
if timelike and cur == iNaT:
2022+
is_unique = 0
2023+
is_monotonic_inc = 0
2024+
is_monotonic_dec = 0
2025+
break
2026+
if cur < prev:
2027+
is_monotonic_inc = 0
2028+
elif cur > prev:
2029+
is_monotonic_dec = 0
2030+
elif cur == prev:
2031+
is_unique = 0
2032+
else:
2033+
# cur or prev is NaN
2034+
is_unique = 0
2035+
is_monotonic_inc = 0
2036+
is_monotonic_dec = 0
2037+
break
2038+
if not is_monotonic_inc and not is_monotonic_dec:
2039+
is_unique = 0
2040+
is_monotonic_inc = 0
2041+
is_monotonic_dec = 0
2042+
break
2043+
prev = cur
20042044
return is_monotonic_inc, is_monotonic_dec, is_unique
20052045

20062046
@cython.boundscheck(False)
@@ -2032,23 +2072,33 @@ def is_monotonic_int64(ndarray[int64_t] arr, bint timelike):
20322072
if timelike and arr[0] == iNaT:
20332073
return False, False, None
20342074

2035-
prev = arr[0]
2036-
for i in range(1, n):
2037-
cur = arr[i]
2038-
if timelike and cur == iNaT:
2039-
return False, False, None
2040-
if cur < prev:
2041-
is_monotonic_inc = 0
2042-
elif cur > prev:
2043-
is_monotonic_dec = 0
2044-
elif cur == prev:
2045-
is_unique = 0
2046-
else:
2047-
# cur or prev is NaN
2048-
return False, False, None
2049-
if not is_monotonic_inc and not is_monotonic_dec:
2050-
return False, False, None
2051-
prev = cur
2075+
with nogil:
2076+
prev = arr[0]
2077+
for i in range(1, n):
2078+
cur = arr[i]
2079+
if timelike and cur == iNaT:
2080+
is_unique = 0
2081+
is_monotonic_inc = 0
2082+
is_monotonic_dec = 0
2083+
break
2084+
if cur < prev:
2085+
is_monotonic_inc = 0
2086+
elif cur > prev:
2087+
is_monotonic_dec = 0
2088+
elif cur == prev:
2089+
is_unique = 0
2090+
else:
2091+
# cur or prev is NaN
2092+
is_unique = 0
2093+
is_monotonic_inc = 0
2094+
is_monotonic_dec = 0
2095+
break
2096+
if not is_monotonic_inc and not is_monotonic_dec:
2097+
is_unique = 0
2098+
is_monotonic_inc = 0
2099+
is_monotonic_dec = 0
2100+
break
2101+
prev = cur
20522102
return is_monotonic_inc, is_monotonic_dec, is_unique
20532103

20542104
@cython.boundscheck(False)
@@ -2080,23 +2130,33 @@ def is_monotonic_bool(ndarray[uint8_t] arr, bint timelike):
20802130
if timelike and arr[0] == iNaT:
20812131
return False, False, None
20822132

2083-
prev = arr[0]
2084-
for i in range(1, n):
2085-
cur = arr[i]
2086-
if timelike and cur == iNaT:
2087-
return False, False, None
2088-
if cur < prev:
2089-
is_monotonic_inc = 0
2090-
elif cur > prev:
2091-
is_monotonic_dec = 0
2092-
elif cur == prev:
2093-
is_unique = 0
2094-
else:
2095-
# cur or prev is NaN
2096-
return False, False, None
2097-
if not is_monotonic_inc and not is_monotonic_dec:
2098-
return False, False, None
2099-
prev = cur
2133+
with nogil:
2134+
prev = arr[0]
2135+
for i in range(1, n):
2136+
cur = arr[i]
2137+
if timelike and cur == iNaT:
2138+
is_unique = 0
2139+
is_monotonic_inc = 0
2140+
is_monotonic_dec = 0
2141+
break
2142+
if cur < prev:
2143+
is_monotonic_inc = 0
2144+
elif cur > prev:
2145+
is_monotonic_dec = 0
2146+
elif cur == prev:
2147+
is_unique = 0
2148+
else:
2149+
# cur or prev is NaN
2150+
is_unique = 0
2151+
is_monotonic_inc = 0
2152+
is_monotonic_dec = 0
2153+
break
2154+
if not is_monotonic_inc and not is_monotonic_dec:
2155+
is_unique = 0
2156+
is_monotonic_inc = 0
2157+
is_monotonic_dec = 0
2158+
break
2159+
prev = cur
21002160
return is_monotonic_inc, is_monotonic_dec, is_unique
21012161

21022162

0 commit comments

Comments
 (0)