// module benchmark1.cpp
// simple portable bechmark (Linux / Windows)
// Uses no IO
// Simple integer arithmetic
// simple double arithmetic
// simple string handling (without libraries)
// by E.Huckert 12-2016

// results: 
// huckert9:      28 sec  (g++ compiler V5.1.0, 64 Bit, optim.level 2).
//                      48 sec (DMD compiler V2.07, -inline, -betterC, -m64)
// huckert30:     91 sec.  (Digital Mars C++, 32 Bit, Opt. level "-o+speed", 60KB code)
//                       75 sec (ditto, but option -ff for "fast inline 8087 code")
//                       39 sec (g++ compiler V5.1, 32 bits, opt.level 2, 4 CPUs, 210 KB code)
//                       6:23 Min for the D version (compiler DMD, uses dynamic array in proc3)
//                       59 secs for the D version (static array instead of dynamic array in proc3)
// raspberry 3:             94 sec (g++ V4.9.2, optim. level 2, 4 CPUs, 1 used)
// BeagleBone black:     135 sec (g++ V4.9.2, optim. level 2, 1 CPU, 1 used)

#include <stdio.h>
#include <string.h>
#include "hu_utils.h"

#define LOOPMAX1 500000
#define LOOPMAX2  2000

// ----------------------------------------------------------------------
// simple integer arithmetic
int proc1()
{
  int ret = 0;
  // odd values as we want to avoid compiler optimizations
  ret = (365 * 5) / 3;
  return ret;
}   // end proc1()

// ----------------------------------------------------------------------
// simple double arithmetic
double proc2()
{
  double ret = 0.0;
  // odd values as we want to avoid compiler optimizations
  ret = ((double)365.6565 * 5.17) / (double)3.2518;
  return ret;
}   // end proc2()

// ----------------------------------------------------------------------
// simple string handling
// we avoid deliberately the call of library routines
const char * proc3()
{
  char s[] = "abcdefghijklmnopqrstuvwxyz";
  const char *pRet = NULL;
  //pRet = ::strchr(s, 'w');  // we don't want to test the C library
  // making array s static brings not much better performance
  // It should hoever be static as we return a pointer to it (is on the stack - dangerous!)
  const char *p = (const char *)s;
  while (*p != 0)
  {
    if (*p == 'w')
    {
      pRet = p;
      break;
    }
    p++;
  }
  // g++ warning: "function may return address of local variable" - this is a correct warning
  return pRet;
}   // end proc3()

// ----------------------------------------------------------------------
int main()
{
  long t1, t2;
  long v1, v2;
  double d1, d2;
  const char * s1;
  //
  t1 = ::get_epoch_time();
  //
  for (int n=0; n < LOOPMAX2; n++)
  {
    v2  = 0L;
    for (unsigned i= 0; i < LOOPMAX1; i++)
    {
      v1 = proc1();
      v2 = v2  + v1;
    }
    //
    for (unsigned i= 0; i < LOOPMAX1; i++)
    {
      s1 = proc3();
    }
    //
    d2  = 0.0;
    for (unsigned i= 0; i < LOOPMAX1; i++)
    {
      d1 = proc2();
      d2 = d2  + d1;
    }
  }   // end for n...
  //
  printf("v2 = %ld\n", v2);
  printf("d2 = %lf\n", d2);
  //
  t2 = ::get_epoch_time();
  //
  printf("Zeit: %f\n", (float)(t2 - t1) / 1000.0);
  return 0;
}   // end main()
