/* example program calling a high level PAPI function */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <memory.h>
#include <malloc.h>
#include "papi.h"


double comp(void);
int factorial(int);


#define INDEX 100

static void test_fail(char *file, int line, char *call, int retval);

int main(int argc, char **argv) {
  float real_time[5], proc_time[5], mflops[5];
  long long flpins[5];
  unsigned long long fac=0;
  int retval;
  int i,j,k , n, post;
  double c;

  /* Setup PAPI library and begin collecting data from the counters */
post=0;
    retval=PAPI_flops( &real_time[post], &proc_time[post], &flpins[post], &mflops[post]);
    if (retval != PAPI_OK) { printf("PAPI error, site 0 !\n"); exit(1); }
    printf("\n              \treal_time,\tproc_time,\tflpins,\t\tmflops\td flpins/d t_real\td flpins/d t_proc\n");
    printf("post %i: \t%5.6f \t%5.6f \t%7ld \t%5.6f\n", post, real_time[post], proc_time[post], flpins[post], mflops[post]);


/*** Here follows the original code section to be analyzed ***/

post=1;
    retval=PAPI_flops( &real_time[post], &proc_time[post], &flpins[post], &mflops[post]);
    if (retval != PAPI_OK) { printf("PAPI error, site 0 !\n"); exit(1); }
    printf("post %i: \t%5.6f \t%5.6f \t%7ld \t%5.6f \t%5.6f \t%5.6f\n", post, real_time[post], proc_time[post], flpins[post], mflops[post],
            (flpins[post]-flpins[post-1])/(real_time[post]-real_time[post-1])/1e6,
            (flpins[post]-flpins[post-1])/(proc_time[post]-proc_time[post-1])/1e6);

   n=10; fac=factorial(n);

post=2;
    retval=PAPI_flops( &real_time[post], &proc_time[post], &flpins[post], &mflops[post]);
    if (retval != PAPI_OK) { printf("PAPI error, site 0 !\n"); exit(1); }
    printf("post %i: \t%5.6f \t%5.6f \t%7ld \t%5.6f \t%5.6f \t%5.6f\tafter n!\n", post, real_time[post], proc_time[post], flpins[post], mflops[post],
            (flpins[post]-flpins[post-1])/(real_time[post]-real_time[post-1])/1e6,
            (flpins[post]-flpins[post-1])/(proc_time[post]-proc_time[post-1])/1e6);

   c = comp() ;

post=3;
    retval=PAPI_flops( &real_time[post], &proc_time[post], &flpins[post], &mflops[post]);
    if (retval != PAPI_OK) { printf("PAPI error, site 0 !\n"); exit(1); }
    printf("post %i: \t%5.6f \t%5.6f \t%7ld \t%5.6f \t%5.6f \t%5.6f\tafter comp()\n", post, real_time[post], proc_time[post], flpins[post], mflops[post],
            (flpins[post]-flpins[post-1])/(real_time[post]-real_time[post-1])/1e6,
            (flpins[post]-flpins[post-1])/(proc_time[post]-proc_time[post-1])/1e6);

/*** Here ends the original code section to be analyzed ***/
 


  /* Collect the data into the variables passed in */
post=4;
    retval=PAPI_flops( &real_time[post], &proc_time[post], &flpins[post], &mflops[post]);
    if (retval != PAPI_OK) { printf("PAPI error, site 0 !\n"); exit(1); }
    printf("post %i: \t%5.6f \t%5.6f \t%7ld \t%5.6f \t%5.6f \t%5.6f\n", post, real_time[post], proc_time[post], flpins[post], mflops[post],
            (flpins[post]-flpins[post-1])/(real_time[post]-real_time[post-1])/1e6,
            (flpins[post]-flpins[post-1])/(proc_time[post]-proc_time[post-1])/1e6);

  printf("\n%s\tPASSED\n\n", __FILE__);
  PAPI_shutdown();
  exit(0);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */


static void test_fail(char *file, int line, char *call, int retval){
    printf("%s\tFAILED\nLine # %d\n", file, line);
    if ( retval == PAPI_ESYS ) {
        char buf[128];
        memset( buf, '\0', sizeof(buf) );
        sprintf(buf, "System error in %s:", call );
        perror(buf);
    }
    else if ( retval > 0 ) {
        printf("Error calculating: %s\n", call );
    }
    else {
        printf("Error in %s: %s\n", call, PAPI_strerror(retval) );
    }
    printf("\n");
    exit(1);
}

int factorial(int n)
{
   unsigned long long f, fac = 1;
        for(f=1; f<=n; f++)
        {
            fac *= f;
        }
    return fac;
}

double comp(void) 
{
    int i;
    double a, b;
    
    a = (double) 3.14159;
    b = (double) 0;
    for (i=0; i<1000000; i++) {
        b += a;
    }
    return(b);
}