Merge branch 'update_complexity' of git://github.com/ismaelJimenez/benchmark into ismaelJimenez-update_complexity
diff --git a/README.md b/README.md
index 5d7f6d8..377fe10 100644
--- a/README.md
+++ b/README.md
@@ -139,7 +139,7 @@
 
 ```c++
 BENCHMARK(BM_StringCompare)
-    ->RangeMultiplier(2)->Range(1<<10, 1<<18)->Complexity(benchmark::oAuto);
+    ->RangeMultiplier(2)->Range(1<<10, 1<<18)->Complexity();
 ```
 
 ### Templated benchmarks
diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h
index 4167553..9f3be61 100644
--- a/include/benchmark/benchmark_api.h
+++ b/include/benchmark/benchmark_api.h
@@ -154,7 +154,6 @@
 #include <stdint.h>
 
 #include "macros.h"
-#include "complexity.h"
 
 namespace benchmark {
 class BenchmarkReporter;
@@ -237,6 +236,20 @@
   kMillisecond
 };
 
+// BigO is passed to a benchmark in order to specify the asymptotic computational 
+// complexity for the benchmark. In case oAuto is selected, complexity will be 
+// calculated automatically to the best fit.
+enum BigO {
+  oNone,
+  o1,
+  oN,
+  oNSquared,
+  oNCubed,
+  oLogN,
+  oNLogN,
+  oAuto
+};
+
 // State is passed to a running Benchmark and contains state for the
 // benchmark to use.
 class State {
@@ -523,7 +536,7 @@
 
   // Set the asymptotic computational complexity for the benchmark. If called
   // the asymptotic computational complexity will be shown on the output. 
-  Benchmark* Complexity(BigO complexity);
+  Benchmark* Complexity(BigO complexity = benchmark::oAuto);
 
   // Support for running multiple copies of the same benchmark concurrently
   // in multiple threads.  This may be useful when measuring the scaling
diff --git a/include/benchmark/complexity.h b/include/benchmark/complexity.h
deleted file mode 100644
index 93b26de..0000000
--- a/include/benchmark/complexity.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef COMPLEXITY_H_
-#define COMPLEXITY_H_
-
-#include <string>
-
-namespace benchmark {
-
-// BigO is passed to a benchmark in order to specify the asymptotic computational 
-// complexity for the benchmark. In case oAuto is selected, complexity will be 
-// calculated automatically to the best fit.
-enum BigO {
-  oNone,
-  o1,
-  oN,
-  oNSquared,
-  oNCubed,
-  oLogN,
-  oNLogN,
-  oAuto
-};
-
-inline std::string GetBigO(BigO complexity) {
-  switch (complexity) {
-    case oN:
-      return "* N";
-    case oNSquared:
-      return "* N**2";
-    case oNCubed:
-      return "* N**3";
-    case oLogN:
-      return "* lgN";
-    case oNLogN:
-      return "* NlgN";
-    case o1:
-      return "* 1";
-    default:
-      return "";
-  }
-}
-
-} // end namespace benchmark
-#endif // COMPLEXITY_H_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a681b35..6dab64b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,7 +5,7 @@
 set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc"
                  "console_reporter.cc" "csv_reporter.cc" "json_reporter.cc"
                  "log.cc" "reporter.cc" "sleep.cc" "string_util.cc"
-                 "sysinfo.cc" "walltime.cc" "minimal_leastsq.cc")
+                 "sysinfo.cc" "walltime.cc" "complexity.cc")
 # Determine the correct regular expression engine to use
 if(HAVE_STD_REGEX)
   set(RE_FILES "re_std.cc")
diff --git a/src/complexity.cc b/src/complexity.cc
new file mode 100644
index 0000000..1f6fee0
--- /dev/null
+++ b/src/complexity.cc
@@ -0,0 +1,164 @@
+// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Source project : https://github.com/ismaelJimenez/cpp.leastsq
+// Adapted to be used with google benchmark
+
+#include "benchmark/benchmark_api.h"
+
+#include "complexity.h"
+#include "check.h"
+#include <math.h>
+#include <functional>
+
+namespace benchmark {
+  
+// Internal function to calculate the different scalability forms
+std::function<double(int)> FittingCurve(BigO complexity) {
+  switch (complexity) {
+    case oN:
+      return [](int n) {return n; };
+    case oNSquared:
+      return [](int n) {return n*n; };
+    case oNCubed:
+      return [](int n) {return n*n*n; };
+    case oLogN:
+      return [](int n) {return log2(n); };
+    case oNLogN:
+      return [](int n) {return n * log2(n); };
+    case o1:
+    default:
+      return [](int) {return 1; };
+  }
+}
+
+// Function to return an string for the calculated complexity
+std::string GetBigOString(BigO complexity) {
+  switch (complexity) {
+    case oN:
+      return "* N";
+    case oNSquared:
+      return "* N**2";
+    case oNCubed:
+      return "* N**3";
+    case oLogN:
+      return "* lgN";
+    case oNLogN:
+      return "* NlgN";
+    case o1:
+      return "* 1";
+    default:
+      return "";
+  }
+}
+
+// Find the coefficient for the high-order term in the running time, by 
+// minimizing the sum of squares of relative error, for the fitting curve 
+// given by the lambda expresion.
+//   - n             : Vector containing the size of the benchmark tests.
+//   - time          : Vector containing the times for the benchmark tests.
+//   - fitting_curve : lambda expresion (e.g. [](int n) {return n; };).
+
+// For a deeper explanation on the algorithm logic, look the README file at
+// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit
+
+// This interface is currently not used from the oustide, but it has been 
+// provided for future upgrades. If in the future it is not needed to support 
+// Cxx03, then all the calculations could be upgraded to use lambdas because 
+// they are more powerful and provide a cleaner inferface than enumerators, 
+// but complete implementation with lambdas will not work for Cxx03 
+// (e.g. lack of std::function).
+// In case lambdas are implemented, the interface would be like :
+//   -> Complexity([](int n) {return n;};)
+// and any arbitrary and valid  equation would be allowed, but the option to 
+// calculate the best fit to the most common scalability curves will still 
+// be kept.
+
+LeastSq CalculateLeastSq(const std::vector<int>& n, 
+                         const std::vector<double>& time, 
+                         std::function<double(int)> fitting_curve) {
+  double sigma_gn = 0.0;
+  double sigma_gn_squared = 0.0;
+  double sigma_time = 0.0;
+  double sigma_time_gn = 0.0;
+
+  // Calculate least square fitting parameter
+  for (size_t i = 0; i < n.size(); ++i) {
+    double gn_i = fitting_curve(n[i]);
+    sigma_gn += gn_i;
+    sigma_gn_squared += gn_i * gn_i;
+    sigma_time += time[i];
+    sigma_time_gn += time[i] * gn_i;
+  }
+
+  LeastSq result;
+
+  // Calculate complexity.
+  result.coef = sigma_time_gn / sigma_gn_squared;
+
+  // Calculate RMS
+  double rms = 0.0;
+  for (size_t i = 0; i < n.size(); ++i) {
+    double fit = result.coef * fitting_curve(n[i]);
+    rms += pow((time[i] - fit), 2);
+  }
+
+  // Normalized RMS by the mean of the observed values
+  double mean = sigma_time / n.size();
+  result.rms = sqrt(rms / n.size()) / mean;
+
+  return result;
+}
+
+// Find the coefficient for the high-order term in the running time, by
+// minimizing the sum of squares of relative error.
+//   - n          : Vector containing the size of the benchmark tests.
+//   - time       : Vector containing the times for the benchmark tests.
+//   - complexity : If different than oAuto, the fitting curve will stick to
+//                  this one. If it is oAuto, it will be calculated the best
+//                  fitting curve.
+LeastSq MinimalLeastSq(const std::vector<int>& n,
+                       const std::vector<double>& time,
+                       const BigO complexity) {
+  CHECK_EQ(n.size(), time.size());
+  CHECK_GE(n.size(), 2);  // Do not compute fitting curve is less than two benchmark runs are given
+  CHECK_NE(complexity, oNone);
+
+  LeastSq best_fit;
+
+  if(complexity == oAuto) {
+    std::vector<BigO> fit_curves = {
+      oLogN, oN, oNLogN, oNSquared, oNCubed };
+
+    // Take o1 as default best fitting curve
+    best_fit = CalculateLeastSq(n, time, FittingCurve(o1));
+    best_fit.complexity = o1;
+
+    // Compute all possible fitting curves and stick to the best one
+    for (const auto& fit : fit_curves) {
+      LeastSq current_fit = CalculateLeastSq(n, time, FittingCurve(fit));
+      if (current_fit.rms < best_fit.rms) {
+        best_fit = current_fit;
+        best_fit.complexity = fit;
+      }
+    }
+  } else {
+    best_fit = CalculateLeastSq(n, time, FittingCurve(complexity));
+    best_fit.complexity = complexity;
+  }
+
+  return best_fit;
+}
+
+}  // end namespace benchmark
diff --git a/src/minimal_leastsq.h b/src/complexity.h
similarity index 81%
rename from src/minimal_leastsq.h
rename to src/complexity.h
index 0dc12b7..dd68362 100644
--- a/src/minimal_leastsq.h
+++ b/src/complexity.h
@@ -15,12 +15,15 @@
 // Source project : https://github.com/ismaelJimenez/cpp.leastsq
 // Adapted to be used with google benchmark
 
-#if !defined(MINIMAL_LEASTSQ_H_)
-#define MINIMAL_LEASTSQ_H_
+#ifndef COMPLEXITY_H_
+#define COMPLEXITY_H_
+
+#include <string>
+#include <vector>
 
 #include "benchmark/benchmark_api.h"
 
-#include <vector>
+namespace benchmark {
 
 // This data structure will contain the result returned by MinimalLeastSq
 //   - coef        : Estimated coeficient for the high-order term as
@@ -33,19 +36,23 @@
 
 struct LeastSq {
   LeastSq() :
-    coef(0),
-    rms(0),
-    complexity(benchmark::oNone) {}
+    coef(0.0),
+    rms(0.0),
+    complexity(oNone) {}
 
   double coef;
   double rms;
-  benchmark::BigO complexity;
+  BigO complexity;
 };
 
+// Function to return an string for the calculated complexity
+std::string GetBigOString(BigO complexity);
+
 // Find the coefficient for the high-order term in the running time, by
 // minimizing the sum of squares of relative error.
 LeastSq MinimalLeastSq(const std::vector<int>& n,
                        const std::vector<double>& time,
-                       const benchmark::BigO complexity = benchmark::oAuto);
+                       const BigO complexity = oAuto);
 
-#endif
+} // end namespace benchmark
+#endif // COMPLEXITY_H_
diff --git a/src/console_reporter.cc b/src/console_reporter.cc
index 3944666..5dd98f6 100644
--- a/src/console_reporter.cc
+++ b/src/console_reporter.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "benchmark/reporter.h"
+#include "complexity.h"
 
 #include <cstdint>
 #include <cstdio>
@@ -129,7 +130,7 @@
   std::tie(timeLabel, multiplier) = GetTimeUnitAndMultiplier(result.time_unit);
 
   if(result.report_big_o) {
-    std::string big_o = result.report_big_o ? GetBigO(result.complexity) : "";
+    std::string big_o = result.report_big_o ? GetBigOString(result.complexity) : "";
     ColorPrintf(COLOR_YELLOW, "%10.4f %s %10.4f %s ",
                 result.real_accumulated_time * multiplier,
                 big_o.c_str(),
diff --git a/src/minimal_leastsq.cc b/src/minimal_leastsq.cc
deleted file mode 100644
index 2a73887..0000000
--- a/src/minimal_leastsq.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Source project : https://github.com/ismaelJimenez/cpp.leastsq
-// Adapted to be used with google benchmark
-
-#include "minimal_leastsq.h"
-#include "check.h"
-#include <math.h>
-
-// Internal function to calculate the different scalability forms
-double FittingCurve(double n, benchmark::BigO complexity) {
-  switch (complexity) {
-    case benchmark::oN:
-      return n;
-    case benchmark::oNSquared:
-      return pow(n, 2);
-    case benchmark::oNCubed:
-      return pow(n, 3);
-    case benchmark::oLogN:
-      return log2(n);
-    case benchmark::oNLogN:
-      return n * log2(n);
-    case benchmark::o1:
-    default:
-      return 1;
-  }
-}
-
-// Internal function to find the coefficient for the high-order term in the
-// running time, by minimizing the sum of squares of relative error.
-//   - n          : Vector containing the size of the benchmark tests.
-//   - time       : Vector containing the times for the benchmark tests.
-//   - complexity : Fitting curve.
-// For a deeper explanation on the algorithm logic, look the README file at
-// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit
-
-LeastSq CalculateLeastSq(const std::vector<int>& n,
-                         const std::vector<double>& time,
-                         const benchmark::BigO complexity) {
-  CHECK_NE(complexity, benchmark::oAuto);
-
-  double sigma_gn = 0;
-  double sigma_gn_squared = 0;
-  double sigma_time = 0;
-  double sigma_time_gn = 0;
-
-  // Calculate least square fitting parameter
-  for (size_t i = 0; i < n.size(); ++i) {
-    double gn_i = FittingCurve(n[i], complexity);
-    sigma_gn += gn_i;
-    sigma_gn_squared += gn_i * gn_i;
-    sigma_time += time[i];
-    sigma_time_gn += time[i] * gn_i;
-  }
-
-  LeastSq result;
-  result.complexity = complexity;
-
-  // Calculate complexity.
-  // o1 is treated as an special case
-  if (complexity != benchmark::o1) {
-    result.coef = sigma_time_gn / sigma_gn_squared;
-  } else {
-    result.coef = sigma_time / n.size();
-  }
-
-  // Calculate RMS
-  double rms = 0;
-  for (size_t i = 0; i < n.size(); ++i) {
-    double fit = result.coef * FittingCurve(n[i], complexity);
-    rms += pow((time[i] - fit), 2);
-  }
-
-  double mean = sigma_time / n.size();
-
-  // Normalized RMS by the mean of the observed values
-  result.rms = sqrt(rms / n.size()) / mean;
-
-  return result;
-}
-
-// Find the coefficient for the high-order term in the running time, by
-// minimizing the sum of squares of relative error.
-//   - n          : Vector containing the size of the benchmark tests.
-//   - time       : Vector containing the times for the benchmark tests.
-//   - complexity : If different than oAuto, the fitting curve will stick to
-//                  this one. If it is oAuto, it will be calculated the best
-//                  fitting curve.
-LeastSq MinimalLeastSq(const std::vector<int>& n,
-                       const std::vector<double>& time,
-                       const benchmark::BigO complexity) {
-  CHECK_EQ(n.size(), time.size());
-  CHECK_GE(n.size(), 2);  // Do not compute fitting curve is less than two benchmark runs are given
-  CHECK_NE(complexity, benchmark::oNone);
-
-  if(complexity == benchmark::oAuto) {
-    std::vector<benchmark::BigO> fit_curves = {
-      benchmark::oLogN, benchmark::oN, benchmark::oNLogN, benchmark::oNSquared,
-      benchmark::oNCubed };
-
-    // Take o1 as default best fitting curve
-    LeastSq best_fit = CalculateLeastSq(n, time, benchmark::o1);
-
-    // Compute all possible fitting curves and stick to the best one
-    for (const auto& fit : fit_curves) {
-      LeastSq current_fit = CalculateLeastSq(n, time, fit);
-      if (current_fit.rms < best_fit.rms) {
-        best_fit = current_fit;
-      }
-    }
-
-    return best_fit;
-  }
-
-  return CalculateLeastSq(n, time, complexity);
-}
diff --git a/src/reporter.cc b/src/reporter.cc
index 6296532..d0a80e6 100644
--- a/src/reporter.cc
+++ b/src/reporter.cc
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 #include "benchmark/reporter.h"
-#include "minimal_leastsq.h"
+#include "complexity.h"
 
 #include <cstdlib>
 #include <vector>
diff --git a/test/complexity_test.cc b/test/complexity_test.cc
index 6e6ae3c..225a181 100644
--- a/test/complexity_test.cc
+++ b/test/complexity_test.cc
@@ -40,7 +40,7 @@
   state.SetComplexityN(state.range_x());
 }
 BENCHMARK(BM_Complexity_O_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> Complexity(benchmark::oN);
-BENCHMARK(BM_Complexity_O_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> Complexity(benchmark::oAuto);
+BENCHMARK(BM_Complexity_O_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> Complexity();
 
 static void BM_Complexity_O_N_Squared(benchmark::State& state) {
   std::string s1(state.range_x(), '-');
@@ -93,7 +93,7 @@
   state.SetComplexityN(state.range_x());
 }
 BENCHMARK(BM_Complexity_O_N_log_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> Complexity(benchmark::oNLogN);
-BENCHMARK(BM_Complexity_O_N_log_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> Complexity(benchmark::oAuto);
+BENCHMARK(BM_Complexity_O_N_log_N) -> RangeMultiplier(2) -> Range(1<<10, 1<<16) -> Complexity();
 
 // Test benchmark with no range and check no complexity is calculated.
 void BM_Extreme_Cases(benchmark::State& state) {
@@ -101,6 +101,6 @@
   }
 }
 BENCHMARK(BM_Extreme_Cases) -> Complexity(benchmark::oNLogN);
-BENCHMARK(BM_Extreme_Cases) -> Arg(42) -> Complexity(benchmark::oAuto);
+BENCHMARK(BM_Extreme_Cases) -> Arg(42) -> Complexity();
 
 BENCHMARK_MAIN()