COMPMID-887 Valgrind invalid read in print_measurements

Change-Id: I595d9ac7a616b3ab21ccc889251d0895c9ac9fb0
Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/119099
Tested-by: Jenkins <bsgcomp@arm.com>
Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com>
diff --git a/arm_compute/core/utils/misc/utility.h b/arm_compute/core/utils/misc/utility.h
index e8d823b..8ba9231 100644
--- a/arm_compute/core/utils/misc/utility.h
+++ b/arm_compute/core/utils/misc/utility.h
@@ -24,8 +24,11 @@
 #ifndef __ARM_COMPUTE_MISC_UTILITY_H__
 #define __ARM_COMPUTE_MISC_UTILITY_H__
 
+#include <algorithm>
 #include <array>
 #include <limits>
+#include <numeric>
+#include <vector>
 
 namespace arm_compute
 {
@@ -140,6 +143,28 @@
     const auto high = static_cast<U>(std::numeric_limits<T>::max());
     return static_cast<T>(clamp(val, low, high));
 }
+
+/** Perform an index sort of a given vector.
+ *
+ * @param[in] v Vector to sort
+ *
+ * @return Sorted index vector.
+ */
+template <typename T>
+std::vector<size_t> sort_indices(const std::vector<T> &v)
+{
+    std::vector<size_t> idx(v.size());
+    std::iota(idx.begin(), idx.end(), 0);
+
+    std::sort(idx.begin(), idx.end(),
+              [&v](size_t i1, size_t i2)
+    {
+        return v[i1] < v[i2];
+    });
+
+    return idx;
+}
+
 } // namespace utility
 } // namespace arm_compute
 #endif /* __ARM_COMPUTE_MISC_UTILITY_H__ */
diff --git a/tests/framework/instruments/InstrumentsStats.cpp b/tests/framework/instruments/InstrumentsStats.cpp
index 2b05e45..6fad8f3 100644
--- a/tests/framework/instruments/InstrumentsStats.cpp
+++ b/tests/framework/instruments/InstrumentsStats.cpp
@@ -22,6 +22,7 @@
  * SOFTWARE.
  */
 #include "InstrumentsStats.h"
+#include "arm_compute/core/utils/misc/utility.h"
 
 namespace arm_compute
 {
@@ -32,25 +33,16 @@
 InstrumentsStats::InstrumentsStats(const std::vector<Measurement> &measurements)
     : _min(nullptr), _max(nullptr), _median(nullptr), _mean(measurements.begin()->value().is_floating_point), _stddev(0.0)
 {
-    auto cmp_measurements = [](const Measurement & a, const Measurement & b)
-    {
-        return a.value() < b.value();
-    };
-
     auto add_measurements = [](Measurement::Value a, const Measurement & b)
     {
         return a + b.value();
     };
 
-    //Calculate min & max
-    const auto values = std::minmax_element(measurements.begin(), measurements.end(), cmp_measurements);
-    _min              = &(*values.first);
-    _max              = &(*values.second);
-
-    // Calculate the median value
-    auto copy = measurements;
-    std::nth_element(copy.begin(), copy.begin() + (copy.size() / 2), copy.end(), cmp_measurements);
-    _median = &copy[copy.size() / 2];
+    //Calculate min, max & median values
+    auto indices = arm_compute::utility::sort_indices(measurements);
+    _median      = &measurements[indices[measurements.size() / 2]];
+    _min         = &measurements[indices[0]];
+    _max         = &measurements[indices[measurements.size() - 1]];
 
     Measurement::Value sum_values = std::accumulate(measurements.begin(), measurements.end(), Measurement::Value(_min->value().is_floating_point), add_measurements);
 
diff --git a/tests/framework/instruments/Measurement.h b/tests/framework/instruments/Measurement.h
index 9fb75d7..1beacf6 100644
--- a/tests/framework/instruments/Measurement.h
+++ b/tests/framework/instruments/Measurement.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -208,6 +208,17 @@
         bool is_floating_point; /**< Is the stored value floating point or integer ? */
     };
 
+    /** Compare the stored value with another value
+     *
+     * @param[in] b Value to compare against
+     *
+     * @return The result of stored value < b
+     */
+    bool operator<(const Measurement &b) const
+    {
+        return _value < b.value();
+    }
+
     /** Stream output operator to print the measurement.
      *
      * Prints value and unit.