The Ackermann function is a classic example of a recursive function, notable especially because it is not a primitive recursive function. It grows very quickly in value, as does the size of its call tree.



The Ackermann function is usually defined as follows:







A
(
m
,
n
)
=


{



n
+
1



if 

m
=
0




A
(
m
−
1
,
1
)



if 

m
>
0

 and 

n
=
0




A
(
m
−
1
,
A
(
m
,
n
−
1
)
)



if 

m
>
0

 and 

n
>
0.








{\displaystyle A(m,n)={\begin{cases}n+1&{\mbox{if }}m=0\\A(m-1,1)&{\mbox{if }}m>0{\mbox{ and }}n=0\\A(m-1,A(m,n-1))&{\mbox{if }}m>0{\mbox{ and }}n>0.\end{cases}}}






Its arguments are never negative and it always terminates.



Task

Write a function which returns the value of 



A
(
m
,
n
)


{\displaystyle A(m,n)}

. Arbitrary precision is preferred (since the function grows so quickly), but not required.



See also

 Conway chained arrow notation for the Ackermann function.


function ack(integer m, integer n)
    if m=0 then
        return n+1
    elsif m=1 then
        return n+2
    elsif m=2 then
        return 2*n+3
    elsif m=3 then
        return power(2,n+3)-3
    elsif m>0 and n=0 then
        return ack(m-1,1)
    else
        return ack(m-1,ack(m,n-1))
    end if
end function
 
constant limit = 23,
         fmtlens = {1,2,2,2,3,3,3,4,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8}
 
atom t0 = time()
printf(1,"   0")
for j=1 to limit do
    string fmt = sprintf(" %%%dd",fmtlens[j+1])
    printf(1,fmt,j)
end for
printf(1,"\n")
for i=0 to 5 do
    printf(1,"%d:",i)
    for j=0 to iff(i>=4?5-i:limit) do
        string fmt = sprintf(" %%%dd",fmtlens[j+1])
        printf(1,fmt,{ack(i,j)})
    end for
    printf(1,"\n")
end for
