229 lines
4.0 KiB
Python
229 lines
4.0 KiB
Python
"""
|
|
Usecases of recursive functions.
|
|
|
|
Some functions are compiled at import time, hence a separate module.
|
|
"""
|
|
|
|
from numba import jit
|
|
|
|
|
|
@jit("i8(i8)", nopython=True)
|
|
def fib1(n):
|
|
if n < 2:
|
|
return n
|
|
# Note the second call uses a named argument
|
|
return fib1(n - 1) + fib1(n=n - 2)
|
|
|
|
|
|
def make_fib2():
|
|
@jit("i8(i8)", nopython=True)
|
|
def fib2(n):
|
|
if n < 2:
|
|
return n
|
|
return fib2(n - 1) + fib2(n=n - 2)
|
|
|
|
return fib2
|
|
|
|
fib2 = make_fib2()
|
|
|
|
|
|
def make_type_change_self(jit=lambda x: x):
|
|
@jit
|
|
def type_change_self(x, y):
|
|
if x > 1 and y > 0:
|
|
return x + type_change_self(x - y, y)
|
|
else:
|
|
return y
|
|
return type_change_self
|
|
|
|
|
|
# Implicit signature
|
|
@jit(nopython=True)
|
|
def fib3(n):
|
|
if n < 2:
|
|
return n
|
|
return fib3(n - 1) + fib3(n - 2)
|
|
|
|
|
|
# Run-away self recursion
|
|
@jit(nopython=True)
|
|
def runaway_self(x):
|
|
return runaway_self(x)
|
|
|
|
|
|
@jit(nopython=True)
|
|
def raise_self(x):
|
|
if x == 1:
|
|
raise ValueError("raise_self")
|
|
elif x > 0:
|
|
return raise_self(x - 1)
|
|
else:
|
|
return 1
|
|
|
|
|
|
# Mutual recursion
|
|
@jit(nopython=True)
|
|
def outer_fac(n):
|
|
if n < 1:
|
|
return 1
|
|
return n * inner_fac(n - 1)
|
|
|
|
|
|
@jit(nopython=True)
|
|
def inner_fac(n):
|
|
if n < 1:
|
|
return 1
|
|
return n * outer_fac(n - 1)
|
|
|
|
|
|
# Mutual recursion with different arg names
|
|
def make_mutual2(jit=lambda x: x):
|
|
@jit
|
|
def foo(x):
|
|
if x > 0:
|
|
return 2 * bar(z=1, y=x)
|
|
return 1 + x
|
|
|
|
@jit
|
|
def bar(y, z):
|
|
return foo(x=y - z)
|
|
|
|
return foo, bar
|
|
|
|
|
|
# Mutual runaway recursion
|
|
|
|
@jit(nopython=True)
|
|
def runaway_mutual(x):
|
|
return runaway_mutual_inner(x)
|
|
|
|
|
|
@jit(nopython=True)
|
|
def runaway_mutual_inner(x):
|
|
return runaway_mutual(x)
|
|
|
|
|
|
# Mutual type changing recursion
|
|
|
|
def make_type_change_mutual(jit=lambda x: x):
|
|
@jit
|
|
def foo(x, y):
|
|
if x > 1 and y > 0:
|
|
# call bar first to exercise partial type inference.
|
|
# typeinferer suspended at the call to bar() and haven't determined
|
|
# the potential return type from the else-branch
|
|
return x + bar(x - y, y)
|
|
else:
|
|
return y
|
|
|
|
@jit
|
|
def bar(x, y):
|
|
if x > 1 and y > 0:
|
|
return x + foo(x - y, y)
|
|
else:
|
|
return y
|
|
|
|
return foo
|
|
|
|
|
|
# Indirect mutual recursion
|
|
def make_four_level(jit=lambda x: x):
|
|
@jit
|
|
def first(x):
|
|
# The recursing call must have a path that is non-recursing.
|
|
if x > 0:
|
|
return second(x) * 2
|
|
else:
|
|
return 1
|
|
|
|
@jit
|
|
def second(x):
|
|
return third(x) * 3
|
|
|
|
@jit
|
|
def third(x):
|
|
return fourth(x) * 4
|
|
|
|
@jit
|
|
def fourth(x):
|
|
return first(x / 2 - 1)
|
|
|
|
return first
|
|
|
|
|
|
def make_inner_error(jit=lambda x: x):
|
|
@jit
|
|
def outer(x):
|
|
if x > 0:
|
|
return inner(x)
|
|
|
|
else:
|
|
return 1
|
|
|
|
@jit
|
|
def inner(x):
|
|
if x > 0:
|
|
return outer(x - 1)
|
|
else:
|
|
# this branch is actually never executed
|
|
return error_fun(x)
|
|
|
|
@jit
|
|
def error_fun(x):
|
|
# to trigger an untyped attribute error
|
|
return x.ndim
|
|
|
|
return outer
|
|
|
|
|
|
def make_raise_mutual(jit=lambda x: x):
|
|
@jit
|
|
def outer(x):
|
|
if x > 0:
|
|
return inner(x)
|
|
else:
|
|
return 1
|
|
|
|
@jit
|
|
def inner(x):
|
|
if x == 1:
|
|
raise ValueError('raise_mutual')
|
|
elif x > 0:
|
|
return outer(x - 1)
|
|
else:
|
|
return 1
|
|
|
|
return outer
|
|
|
|
|
|
def make_optional_return_case(jit=lambda x: x):
|
|
@jit
|
|
def foo(x):
|
|
if x > 5:
|
|
return x - 1
|
|
else:
|
|
return
|
|
|
|
@jit
|
|
def bar(x):
|
|
out = foo(x)
|
|
if out is None:
|
|
return out
|
|
elif out < 8:
|
|
return out
|
|
else:
|
|
return x * bar(out)
|
|
|
|
return bar
|
|
|
|
|
|
def make_growing_tuple_case(jit=lambda x: x):
|
|
# From issue #4387
|
|
@jit
|
|
def make_list(n):
|
|
if n <= 0:
|
|
return None
|
|
|
|
return (n, make_list(n - 1))
|
|
return make_list
|