// Copyright 2012 Google Inc. All Rights Reserved.
// Author: martint@google.com (Martin Thuresson)

#include "third_party/open64_libacml_mv/acml_trace.h"

#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <memory>
#include <vector>

#include "base/commandlineflags.h"
#include "base/examine_stack.h"
#include "base/googleinit.h"
#include "base/init_google.h"
#include "base/logging.h"
#include "file/base/file.h"
#include "file/base/path.h"
#include "testing/base/public/benchmark.h"
#include "testing/base/public/googletest.h"
#include "third_party/open64_libacml_mv/libacml.h"


int main(int argc, char** argv) {
  InitGoogle(argv[0], &argc, &argv, true);
  RunSpecifiedBenchmarks();
  return 0;
}

namespace {

// Local typedefs to avoid repeating complex types all over the function.
typedef std::unique_ptr<std::vector<double>> DoubleListPtr;
typedef std::unique_ptr<std::vector<float>> FloatListPtr;
typedef std::unique_ptr<std::vector<std::pair<double,
                                              double>>> DoublePairListPtr;

/////////////////////////
// Benchmark log() calls.
/////////////////////////

// Measure time spent iterating through the values.
static void BM_math_trace_read_log(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoubleListPtr trace(GetTraceDouble(file::JoinPath(FLAGS_test_srcdir,
                                                     LOG_LOGFILE).c_str()));
  StartBenchmarkTiming();
  // Process trace.
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += *iter;
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark acml_log().
static void BM_math_trace_acmllog(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoubleListPtr trace(GetTraceDouble(file::JoinPath(FLAGS_test_srcdir,
                                                     LOG_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += acml_log(*iter);
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark log().
static void BM_math_trace_log(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoubleListPtr trace(GetTraceDouble(file::JoinPath(FLAGS_test_srcdir,
                                                     LOG_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += log(*iter);
    }
  }
  CHECK_NE(d, 0.0);
}


/////////////////////////
// Benchmark exp() calls.
/////////////////////////

// Measure time spent iterating through the values.
static void BM_math_trace_read_exp(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoubleListPtr trace(GetTraceDouble(file::JoinPath(FLAGS_test_srcdir,
                                                    EXP_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += *iter;
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark acml_exp().
static void BM_math_trace_acmlexp(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoubleListPtr trace(GetTraceDouble(file::JoinPath(FLAGS_test_srcdir,
                                                    EXP_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += acml_exp(*iter);
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark exp().
static void BM_math_trace_exp(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoubleListPtr trace(GetTraceDouble(file::JoinPath(FLAGS_test_srcdir,
                                                    EXP_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += exp(*iter);
    }
  }
  CHECK_NE(d, 0.0);
}

/////////////////////////
// Benchmark expf() calls.
/////////////////////////

// Measure time spent iterating through the values.
static void BM_math_trace_read_expf(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  FloatListPtr trace(GetTraceFloat(file::JoinPath(FLAGS_test_srcdir,
                                                  EXPF_LOGFILE).c_str()));
  StartBenchmarkTiming();
  float d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += *iter;
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark acml_exp().
static void BM_math_trace_acmlexpf(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  FloatListPtr trace(GetTraceFloat(file::JoinPath(FLAGS_test_srcdir,
                                                  EXPF_LOGFILE).c_str()));
  StartBenchmarkTiming();
  float d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += acml_expf(*iter);
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark exp().
static void BM_math_trace_expf(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  FloatListPtr trace(GetTraceFloat(file::JoinPath(FLAGS_test_srcdir,
                                                  EXPF_LOGFILE).c_str()));
  StartBenchmarkTiming();
  float d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto iter = trace->begin(); iter != trace->end(); ++iter) {
      d += expf(*iter);
    }
  }
  CHECK_NE(d, 0.0);
}


/////////////////////////
// Benchmark pow() calls.
/////////////////////////

// Measure time spent iterating through the values.
static void BM_math_trace_read_pow(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoublePairListPtr trace(GetTraceDoublePair(file::JoinPath(
      FLAGS_test_srcdir, POW_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto itr = trace->begin(); itr != trace->end(); ++itr) {
      d += (*itr).first + (*itr).second;
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark acml_pow().
static void BM_math_trace_acmlpow(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoublePairListPtr trace(GetTraceDoublePair(file::JoinPath(
      FLAGS_test_srcdir, POW_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto itr = trace->begin(); itr != trace->end(); ++itr) {
      d += acml_pow((*itr).first,
                    (*itr).second);
    }
  }
  CHECK_NE(d, 0.0);
}

// Benchmark pow().
static void BM_math_trace_pow(int iters) {
  // Read trace file into memory.
  StopBenchmarkTiming();
  DoublePairListPtr trace(GetTraceDoublePair(file::JoinPath(
      FLAGS_test_srcdir, POW_LOGFILE).c_str()));
  StartBenchmarkTiming();
  double d = 0.0;
  for (int iter = 0; iter < iters; ++iter) {
    for (auto itr = trace->begin(); itr != trace->end(); ++itr) {
      d += pow((*itr).first,
               (*itr).second);
    }
  }
  CHECK_NE(d, 0.0);
}


BENCHMARK(BM_math_trace_read_exp);
BENCHMARK(BM_math_trace_acmlexp);
BENCHMARK(BM_math_trace_exp);

BENCHMARK(BM_math_trace_read_log);
BENCHMARK(BM_math_trace_acmllog);
BENCHMARK(BM_math_trace_log);

BENCHMARK(BM_math_trace_read_pow);
BENCHMARK(BM_math_trace_acmlpow);
BENCHMARK(BM_math_trace_pow);

BENCHMARK(BM_math_trace_read_expf);
BENCHMARK(BM_math_trace_acmlexpf);
BENCHMARK(BM_math_trace_expf);

}  // namespace
