[fbl] Add min_element and max_element.

Change-Id: Ib52514620566c3d179f16c09cfeaf1fa75163e70
diff --git a/system/ulib/fbl/include/fbl/algorithm.h b/system/ulib/fbl/include/fbl/algorithm.h
index ba9c2df..e864b3d 100644
--- a/system/ulib/fbl/include/fbl/algorithm.h
+++ b/system/ulib/fbl/include/fbl/algorithm.h
@@ -72,6 +72,76 @@
                 (val / multiple) * multiple;
 }
 
+// Returns an iterator to the maximum element in the range [|first|, |last|).
+//
+// |first| and |last| must be forward iterators.
+//
+// Similar to: <http://en.cppreference.com/w/cpp/algorithm/max_element>
+template<class FwIterator>
+FwIterator max_element(FwIterator first, FwIterator last) {
+    FwIterator max = first;
+    while (first < last) {
+        if (*first > *max) {
+            max = first;
+        }
+        first++;
+    }
+    return max;
+}
+
+// Returns an iterator to the maximum element in the range [|first|, |last|).
+// using |comp| to compare elements instead of operator>
+//
+// |first| and |last| must be forward iterators.
+//
+// Similar to: <http://en.cppreference.com/w/cpp/algorithm/max_element>
+template<class FwIterator, class Compare>
+FwIterator max_element(FwIterator first, FwIterator last, Compare comp) {
+    FwIterator max = first;
+    while (first < last) {
+        if (comp(*first, *max)) {
+            max = first;
+        }
+        first++;
+    }
+    return max;
+}
+
+// Returns an iterator to the minimum element in the range [|first|, |last|).
+//
+// |first| and |last| must be forward iterators.
+//
+// Similar to: <http://en.cppreference.com/w/cpp/algorithm/min_element>
+template<class FwIterator>
+FwIterator min_element(FwIterator first, FwIterator last) {
+    FwIterator min = first;
+    while (first < last) {
+        if (*first < *min) {
+            min = first;
+        }
+        first++;
+    }
+    return min;
+}
+
+// Returns an iterator to the minimum element in the range [|first|, |last|)
+// using |comp| to compare elements instead of operator<
+//
+// |first| and |last| must be forward iterators.
+//
+// Similar to: <http://en.cppreference.com/w/cpp/algorithm/min_element>
+template<class FwIterator, class Compare>
+FwIterator min_element(FwIterator first, FwIterator last, Compare comp) {
+    FwIterator min = first;
+    while (first < last) {
+        if (comp(*first, *min)) {
+            min = first;
+        }
+        first++;
+    }
+    return min;
+}
+
 // Returns a pointer to the first element that is not less than |value|, or
 // |last| if no such element is found.
 //
diff --git a/system/utest/fbl/algorithm_tests.cpp b/system/utest/fbl/algorithm_tests.cpp
index a57a900..ebed25c 100644
--- a/system/utest/fbl/algorithm_tests.cpp
+++ b/system/utest/fbl/algorithm_tests.cpp
@@ -111,6 +111,82 @@
     END_TEST;
 }
 
+bool max_element_test() {
+    BEGIN_TEST;
+    int* null = nullptr;
+    EXPECT_EQ(fbl::max_element(null, null), null);
+
+    int value = 5;
+    EXPECT_EQ(fbl::max_element(&value, &value), &value);
+
+    int values[] = { 1, 3, 7, -2, 5, 7 };
+    constexpr size_t count = fbl::count_of(values);
+    int* first = values;
+    int* last = values + count;
+    EXPECT_EQ(fbl::max_element(first, last), values + 2);
+
+    END_TEST;
+}
+
+bool max_compare(int a, int b) {
+    return a > b;
+}
+
+bool max_element_compare_test() {
+    BEGIN_TEST;
+    int* null = nullptr;
+    EXPECT_EQ(fbl::max_element(null, null, max_compare), null);
+
+    int value = 5;
+    EXPECT_EQ(fbl::max_element(&value, &value, max_compare), &value);
+
+    int values[] = { 1, 3, 7, -2, 5, 7 };
+    constexpr size_t count = fbl::count_of(values);
+    int* first = values;
+    int* last = values + count;
+    EXPECT_EQ(fbl::max_element(first, last, max_compare), values + 2);
+
+    END_TEST;
+}
+
+bool min_element_test() {
+    BEGIN_TEST;
+    int* null = nullptr;
+    EXPECT_EQ(fbl::min_element(null, null), null);
+
+    int value = 5;
+    EXPECT_EQ(fbl::min_element(&value, &value), &value);
+
+    int values[] = { 1, 3, -7, -2, 5, -7 };
+    constexpr size_t count = fbl::count_of(values);
+    int* first = values;
+    int* last = values + count;
+    EXPECT_EQ(fbl::min_element(first, last), values + 2);
+
+    END_TEST;
+}
+
+bool min_compare(int a, int b) {
+    return a < b;
+}
+
+bool min_element_compare_test() {
+    BEGIN_TEST;
+    int* null = nullptr;
+    EXPECT_EQ(fbl::min_element(null, null, min_compare), null);
+
+    int value = 5;
+    EXPECT_EQ(fbl::min_element(&value, &value, min_compare), &value);
+
+    int values[] = { 1, 3, -7, -2, 5, -7 };
+    constexpr size_t count = fbl::count_of(values);
+    int* first = values;
+    int* last = values + count;
+    EXPECT_EQ(fbl::min_element(first, last, min_compare), values + 2);
+
+    END_TEST;
+}
+
 bool lower_bound_test() {
     BEGIN_TEST;
 
@@ -299,6 +375,10 @@
 RUN_NAMED_TEST("is_pow2<uint32_t>", is_pow2_test<uint32_t>)
 RUN_NAMED_TEST("is_pow2<uint64_t>", is_pow2_test<uint64_t>)
 RUN_NAMED_TEST("is_pow2<size_t>",   is_pow2_test<size_t>)
+RUN_NAMED_TEST("max_element test", max_element_test)
+RUN_NAMED_TEST("max_element_compare test", max_element_compare_test)
+RUN_NAMED_TEST("min_element test", min_element_test)
+RUN_NAMED_TEST("min_element_compare test", min_element_compare_test)
 RUN_NAMED_TEST("lower_bound test", lower_bound_test)
 RUN_NAMED_TEST("lower_bound_compare test", lower_bound_compare_test)
 RUN_NAMED_TEST("gcd_test<uint8_t>",  gcd_test<uint8_t>)