Alaska Software Inc. - Recursive function ends with xppFatal?
Username: Password:
AuthorTopic: Recursive function ends with xppFatal?
Sander EliasRecursive function ends with xppFatal?
on Wed, 18 Mar 2015 07:12:06 +0100
Hi All,

I like to solve some problems with recursive functions, and ran into a snag.
the following code will exit with a xppfatal?

PROCEDURE Main
   local arr  := {}
   local max  := 2000
   local x    := 0
   local nSum := 0
   /* we use the ansi charset by default */
   SET CHARSET TO ANSI

   for x = 1 to max
      aAdd(arr,x)
   next
   nSum := recursiveSum(arr,1,max)
   qout("sum"+ str(nSum))
   inkey(10)
RETURN

function recursiveSum(arr,index,stop,prev)
   default index to 1, prev to 0
   if index > stop
      return prev
   endif
   return recursiveSum(arr,index+1,stop,prev+arr[index])

I'm assuming I run out of the stack, but already with less then 2000 iterations? How can I enlarge my stack, and what are the trade-offs?
Regards
Sander Elias
--------------------------------------------
also a member off the XXP (http://www.xxp.nl)
Hubert BrandelRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 08:16:50 +0100
Am 18.03.2015 um 07:12 schrieb "Sander Elias":
> How can I enlarge my stack,
with a parameter from ALINK

/ST[ACK]:<max>[,<min>]
Sander EliasRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 09:46:11 +0100
Hi Hubert,

Thanks for the info!
However, that leaves the question, how large should I make it. And what is the trade of? I'm assuming there must be one if it's this small to begin with..
Also, their is some lack in documentation. What is the default size? Why is that size picked? 

Regards
Sander Elias
--------------------------------------------
also a member off the XXP (http://www.xxp.nl)
Thomas BraunRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 15:08:36 +0100
Sander Elias wrote:

> However, that leaves the question, how large should I make it. And what
> is the trade of? I'm assuming there must be one if it's this small to
> begin with.. Also, their is some lack in documentation. What is the
> default size? Why is that size picked? 

According to the docs, the default maximum value is 1 MB:

> /ST[ACK]:<max>[,<min>]  This option sets the stack size of an Xbase++
> application. <max> is a numeric value indicating the maximum stack size
> in bytes (default is 1 MB), while <min> optionally defines the stack
> size at program start. This means that the minimum stack size is <min>
> bytes and it can grow dynamically at runtime to a maximum size of <max>
> bytes.

So if I where you I would increase it to 2 MB and see what happens 

Unfortunately this still leaves all your other questions unanswered.

I rember that there has been discussions about this switch several times in
the past, maybe just do a search in the news group.

Thomas
Werner MartlRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 11:05:02 +0100
Am 18.03.2015 um 07:12 schrieb "Sander Elias":
> Hi All,
>
> I like to solve some problems with recursive functions, and ran into a snag.
> the following code will exit with a xppfatal?
>
> PROCEDURE Main
>     local arr  := {}
>     local max  := 2000
>     local x    := 0
>     local nSum := 0
>     /* we use the ansi charset by default */
>     SET CHARSET TO ANSI
>
>     for x = 1 to max
>        aAdd(arr,x)
>     next
>     nSum := recursiveSum(arr,1,max)
>     qout("sum"+ str(nSum))
>     inkey(10)
> RETURN
>
> function recursiveSum(arr,index,stop,prev)
>     default index to 1, prev to 0
>     if index > stop
>        return prev
>     endif
>     return recursiveSum(arr,index+1,stop,prev+arr[index])
>
> I'm assuming I run out of the stack, but already with less then 2000 iterations? How can I enlarge my stack, and what are the trade-offs?
> Regards
> Sander Elias
> --------------------------------------------
> also a member off the XXP (http://www.xxp.nl)
>

Hi Elias,

replace

 >     for x = 1 to max
 >        aAdd(arr,x)
 >     next

with

arr := array(max)
afill(arr, 0)

==> much faster, less memory-leaks.

Best regards,

Werner
Thomas BraunRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 11:40:39 +0100
Werner Martl wrote:

> Hi Elias,
> 
> replace
> 
>  >     for x = 1 to max
>  >        aAdd(arr,x)
>  >     next

Werner,

the result of your code is not the same as the code above!

Your code sets each element of the array to 0.

Elias' code fills the array with a sequence of consecutive numbers
1,...,max

To make it identical, you need to do this:

arr := array(max)
For x = 1 TO max
  arr[x] := x
Next

I did not test if this is actually faster or using less memory as the
original code.

regards
Thomas
Sander EliasRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 13:45:55 +0100
Hi Werner, Thomas,

As Thomes remarked, the code fills the array with different numbers. 
Actually my code sample is not about the for-next loop. It is about the problem with recursive functions. And this was the simplest sample I could come up with.
I can't complain about array speed in xbase anymore (big progress into that in 2.0) 
I did some simple timings. On my computer I can create an array 10.000.000(no, not a typo!) the same way as the above sample, and then traverse it summing it up in approximate 4 seconds. That is an HUGE improvement of 1.9

Regards
Sander Elias
--------------------------------------------
also a member off the XXP (http://www.xxp.nl)
Thomas BraunRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 15:05:05 +0100
Sander Elias wrote:

> Hi Werner, Thomas,
> 
> As Thomes remarked, the code fills the array with different numbers. 
> Actually my code sample is not about the for-next loop. It is about the problem with recursive functions. 

Probably Werner supects some memory leak to be the cause for your problem
(which I doubt it is)

Did the /ST switch help to mitigate the problem?

Thomas
Sander EliasRe: Recursive function ends with xppFatal?
on Wed, 18 Mar 2015 16:24:51 +0100
>Did the /ST switch help to mitigate the problem?
Yes it did. I upped it to 10Mb. Now I can recursively traverse at a usable level (20.000 seems to run ok now, that is in a test program, with nothing else going on!)
at 21000 there is still a fatal, which still is very bad. However, I'm still in the dark on the flip side of this? Just some extra memory? Thats not a bad deal, but what is the catch?

But now at least I can use stuff like this in most cases without too much worrying.

function reduce(bBlock,arr,index,prev)
   static last
   default index to 1, prev to 0
   if index == 1
      last := len(arr)
   endif
   if index > last
      return prev
   endif
   return reduce(bBlock,arr,index+1,eval(bBlock,arr[index],prev))

   nSum:= reduce({|c,pre| c+pre}, arr,1,max)
   nMax:= reduce({|c,pre| max(c,pre)}, arr,1,max)

With the speed of 2.x this works more then fast enough. 



Regards
Sander Elias
--------------------------------------------
also a member off the XXP (http://www.xxp.nl)
Thomas BraunRe: Recursive function ends with xppFatal?
on Thu, 19 Mar 2015 09:03:20 +0100
Sander Elias wrote:

> with nothing else going on!) at 21000 there is still a fatal, which
> still is very bad.

Yes - a proper error message would be the preferred way instead of leaving
the developer alone in the dark with some rather cryptic and undocumented
fatal error 

Thomas