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.


/*REXX program  calculates and displays  some values for the  Ackermann function.       */
            /*╔════════════════════════════════════════════════════════════════════════╗
              ║  Note:  the Ackermann function  (as implemented here)  utilizes deep   ║
              ║         recursive and is limited by the largest number that can have   ║
              ║         "1"  (unity) added to a number  (successfully and accurately). ║
              ╚════════════════════════════════════════════════════════════════════════╝*/
high=24
         do     j=0  to 3;                    say
             do k=0  to high % (max(1, j))
             call tell_Ack  j, k
             end   /*k*/
         end       /*j*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
tell_Ack:  parse arg mm,nn;   calls=0            /*display an echo message to terminal. */
           #=right(nn,length(high))
           say 'Ackermann('mm", "#')='right(ackermann(mm, nn), high),
                                      left('', 12)     'calls='right(calls, high)
           return
/*──────────────────────────────────────────────────────────────────────────────────────*/
ackermann: procedure expose calls                /*compute value of Ackermann function. */
           parse arg m,n;   calls=calls+1
           if m==0  then return n+1
           if n==0  then return ackermann(m-1, 1)
                         return ackermann(m-1, ackermann(m, n-1) )