/* val6.c  2013-04-29 14:20
   Reference executable for validating application profiling tools.
   val6:  recursive function with workload at bottom of deep call stack.

   Execute a workload after recursing beyond a specified depth.  The exact
   maximum depth will depend on the initial depth of main and the number of
   levels of interrupt handler functions appearing below cycfn.

   With default values of the parameters, the expected distribution of time
   is approximately
     main    total 100 % self   0 %
     cycfn   total 100 % self 100 %

   For determining the depth at which trouble first appears, EACHLOOP may be
   set to generate an observable delay on each invocation.  By default, no
   such delay is generated.

   Test case suggested by José Fonseca, 2013-04-09.

   Language -std=gnu99 (with gcc-specific attributes).
   Original versions tested:  gcc 4.7.2.
*/

// Configurable LEAFLOOP:  how many iterations in leaf invocation.
#ifndef LEAFLOOP
#define LEAFLOOP 200000000
#endif

// Configurable EACHLOOP:  how many iterations in nonleaf invocations.
// #define EACHLOOP 1000000

// Configurable DEPTH:  depth of recursion.
#ifndef DEPTH
#define DEPTH 512
#endif

#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdbool.h>

uint64_t accumulator=1;
double   adder=0;

__attribute__((noinline,optimize("no-optimize-sibling-calls")))
void cycfn (uint64_t depth) {
  if (depth) {
    #ifdef EACHLOOP
    for (uint64_t looper=0; looper<EACHLOOP; ++looper)
      adder += M_PI*3, accumulator = accumulator*3 + adder;
    #endif
    cycfn (depth-1);
  } else
    for (uint64_t looper=0; looper<LEAFLOOP; ++looper)
      adder += M_PI*3, accumulator = accumulator*3 + adder;
}

int main() {
  cycfn (DEPTH);
  printf ("%" PRIu64 " %f\n", accumulator, adder);
  return 0;
}
