Containers (STL-compatible) StateMachines MessageBus and more for Embedded Systems. See www.etlcpp.com

Revision:
0:b47c2a7920c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/algorithm.h	Fri Mar 16 16:34:18 2018 +0000
@@ -0,0 +1,1120 @@
+///\file
+
+/******************************************************************************
+The MIT License(MIT)
+
+Embedded Template Library.
+https://github.com/ETLCPP/etl
+http://www.etlcpp.com
+
+Copyright(c) 2014 jwellbelove
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files(the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions :
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+******************************************************************************/
+
+#ifndef __ETL_ALGORITHM__
+#define __ETL_ALGORITHM__
+
+///\defgroup algorithm algorithm
+/// Reverse engineered algorithms from C++ 0x11
+/// Additional new variants of certain algorithms.
+///\ingroup utilities
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+#include <functional>
+#include <iterator>
+#include <stdint.h>
+
+#include "platform.h"
+#include "iterator.h"
+#include "type_traits.h"
+
+namespace etl
+{
+  //***************************************************************************
+  /// Finds the greatest and the smallest element in the range (begin, end).<br>
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax_element"></a>
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TIterator,
+            typename TCompare>
+  std::pair<TIterator, TIterator> minmax_element(TIterator begin,
+                                                 TIterator end,
+                                                 TCompare  compare)
+  {
+    TIterator minimum = begin;
+    TIterator maximum = begin;
+
+    while (begin != end)
+    {
+      if (compare(*begin, *minimum))
+      {
+        minimum = begin;
+      }
+
+      if (compare(*maximum, *begin))
+      {
+        maximum = begin;
+      }
+
+      ++begin;
+    }
+
+    return std::pair<TIterator, TIterator>(minimum, maximum);
+  }
+
+  //***************************************************************************
+  /// minmax_element
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax_element"></a>
+  //***************************************************************************
+  template <typename TIterator>
+  std::pair<TIterator, TIterator> minmax_element(TIterator begin,
+                                                 TIterator end)
+  {
+      typedef typename std::iterator_traits<TIterator>::value_type value_t;
+
+      return etl::minmax_element(begin, end, std::less<value_t>());
+  }
+
+  //***************************************************************************
+  /// minmax
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax"></a>
+  //***************************************************************************
+  template <typename T>
+  std::pair<const T&, const T&> minmax(const T& a,
+                                       const T& b)
+  {
+    return (b < a) ? std::pair<const T&, const T&>(b, a) : std::pair<const T&, const T&>(a, b);
+  }
+
+  //***************************************************************************
+  /// minmax
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax"></a>
+  //***************************************************************************
+  template <typename T,
+            typename TCompare>
+  std::pair<const T&, const T&> minmax(const T& a,
+                                       const T& b,
+                                       TCompare compare)
+  {
+    return compare(b, a) ? std::pair<const T&, const T&>(b, a) : std::pair<const T&, const T&>(a, b);
+  }
+
+  //***************************************************************************
+  /// is_sorted_until
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"></a>
+  //***************************************************************************
+  template <typename TIterator>
+  TIterator is_sorted_until(TIterator begin,
+                            TIterator end)
+  {
+    if (begin != end)
+    {
+      TIterator next = begin;
+
+      while (++next != end)
+      {
+        if (*next < *begin)
+        {
+          return next;
+        }
+
+        ++begin;
+      }
+    }
+
+    return end;
+  }
+
+  //***************************************************************************
+  /// is_sorted_until
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TCompare>
+  TIterator is_sorted_until(TIterator begin,
+                            TIterator end,
+                            TCompare  compare)
+  {
+    if (begin != end)
+    {
+      TIterator next = begin;
+
+      while (++next != end)
+      {
+        if (compare(*next, *begin))
+        {
+          return next;
+        }
+
+        ++begin;
+      }
+    }
+
+    return end;
+  }
+
+  //***************************************************************************
+  /// is_sorted
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted"></a>
+  //***************************************************************************
+  template<typename TIterator>
+  bool is_sorted(TIterator begin,
+                 TIterator end)
+  {
+    return etl::is_sorted_until(begin, end) == end;
+  }
+
+  //***************************************************************************
+  /// is_sorted
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted"></a>
+  //***************************************************************************
+  template<typename TIterator,
+           typename TCompare>
+  bool is_sorted(TIterator begin,
+                 TIterator end,
+                 TCompare  compare)
+  {
+    return etl::is_sorted_until(begin, end, compare) == end;
+  }
+
+  //***************************************************************************
+  /// copy
+  /// A form of copy where the smallest of the two ranges is used.
+  /// There is currently no STL equivalent.
+  /// Specialisation for random access iterators.
+  ///\param i_begin Beginning of the input range.
+  ///\param i_end   End of the input range.
+  ///\param o_begin Beginning of the output range.
+  ///\param o_end   End of the output range.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TOutputIterator>
+  typename etl::enable_if<etl::is_random_iterator<TInputIterator>::value &&
+                          etl::is_random_iterator<TOutputIterator>::value, TOutputIterator>::type
+   copy(TInputIterator  i_begin,
+        TInputIterator  i_end,
+        TOutputIterator o_begin,
+        TOutputIterator o_end)
+  {
+      size_t s_size = std::distance(i_begin, i_end);
+      size_t d_size = std::distance(o_begin, o_end);
+      size_t size   = (s_size < d_size) ? s_size : d_size;
+
+      return std::copy(i_begin, i_begin + size, o_begin);
+  }
+
+  //***************************************************************************
+  /// copy
+  /// A form of copy where the smallest of the two ranges is used.
+  /// There is currently no STL equivalent.
+  /// Specialisation for non random access iterators.
+  ///\param i_begin Beginning of the input range.
+  ///\param i_end   End of the input range.
+  ///\param o_begin Beginning of the output range.
+  ///\param o_end   End of the output range.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TOutputIterator>
+  typename etl::enable_if<!etl::is_random_iterator<TInputIterator>::value ||
+                          !etl::is_random_iterator<TOutputIterator>::value, TOutputIterator>::type
+   copy(TInputIterator  i_begin,
+        TInputIterator  i_end,
+        TOutputIterator o_begin,
+        TOutputIterator o_end)
+  {
+    while ((i_begin != i_end) && (o_begin != o_end))
+    {
+      *o_begin++ = *i_begin++;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// copy_n (Random input iterators)
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/copy_n"></a>
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator>
+  typename etl::enable_if<etl::is_random_iterator<TInputIterator>::value, TOutputIterator>::type
+   copy_n(TInputIterator  i_begin,
+          TSize           n,
+          TOutputIterator o_begin)
+  {
+    return std::copy(i_begin, i_begin + n, o_begin);
+  }
+
+  //***************************************************************************
+  /// copy_n (Non-random input iterators)
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/copy_n"></a>
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator>
+  typename etl::enable_if<!etl::is_random_iterator<TInputIterator>::value, TOutputIterator>::type
+   copy_n(TInputIterator  i_begin,
+          TSize           n,
+          TOutputIterator o_begin)
+  {
+    while (n-- > 0)
+    {
+      *o_begin++ = *i_begin++;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// copy_n
+  /// A form of copy_n where the smallest of the two ranges is used.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator>
+  TOutputIterator copy_n(TInputIterator  i_begin,
+                         TSize           n,
+                         TOutputIterator o_begin,
+                         TOutputIterator o_end)
+  {
+    while ((n-- > 0) && (o_begin != o_end))
+    {
+      *o_begin++ = *i_begin++;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// copy_n
+  /// A form of copy_n where the smallest of the two ranges is used.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize1,
+            typename TOutputIterator,
+            typename TSize2>
+  TOutputIterator copy_n(TInputIterator  i_begin,
+                         TSize1          n1,
+                         TOutputIterator o_begin,
+                         TSize2          n2)
+  {
+    while ((n1-- > 0) && (n2-- > 0))
+    {
+      *o_begin++ = *i_begin++;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// copy_if
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/copy"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TOutputIterator,
+            typename TUnaryPredicate>
+  TOutputIterator copy_if(TIterator       begin,
+                          TIterator       end,
+                          TOutputIterator out,
+                          TUnaryPredicate predicate)
+  {
+    while (begin != end)
+    {
+      if (predicate(*begin))
+      {
+        *out++ = *begin;
+      }
+
+      ++begin;
+    }
+
+    return out;
+  }
+
+  //***************************************************************************
+  /// copy_if
+  /// A form of copy_if where it terminates when the first end iterator is reached.
+  /// There is currently no STL equivelent.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TOutputIterator,
+            typename TUnaryPredicate>
+  TOutputIterator copy_if(TInputIterator  i_begin,
+                          TInputIterator  i_end,
+                          TOutputIterator o_begin,
+                          TOutputIterator o_end,
+                          TUnaryPredicate predicate)
+  {
+    while ((i_begin != i_end) && (o_begin != o_end))
+    {
+      if (predicate(*i_begin))
+      {
+        *o_begin++ = *i_begin;
+      }
+
+      ++i_begin;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// copy_n_if
+  /// Combination of copy_n and copy_if.
+  ///\ingroup algorithm
+    //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator,
+            typename TUnaryPredicate>
+  TOutputIterator copy_n_if(TInputIterator  i_begin,
+                            TSize           n,
+                            TOutputIterator o_begin,
+                            TUnaryPredicate predicate)
+  {
+    while (n-- > 0)
+    {
+      if (predicate(*i_begin))
+      {
+        *o_begin++ = *i_begin;
+      }
+
+      ++i_begin;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// binary_find
+  ///\ingroup algorithm
+  /// Does a binary search and returns an iterator to the value or end if not found.
+  //***************************************************************************
+  template <typename TIterator,
+            typename TValue>
+    TIterator binary_find(TIterator     begin,
+                          TIterator     end,
+                          const TValue& value)
+  {
+    TIterator it = std::lower_bound(begin, end, value);
+
+    if ((it == end) || (*it != value))
+    {
+      it = end;
+    }
+
+    return it;
+  }
+
+  //***************************************************************************
+  /// binary_find
+  ///\ingroup algorithm
+  /// Does a binary search and returns an iterator to the value or end if not found.
+  //***************************************************************************
+  template <typename TIterator,
+            typename TValue,
+            typename TBinaryPredicate,
+            typename TBinaryEquality>
+    TIterator binary_find(TIterator        begin,
+                          TIterator        end,
+                          const TValue&    value,
+                          TBinaryPredicate predicate,
+                          TBinaryEquality  equality)
+  {
+    TIterator it = std::lower_bound(begin, end, value, predicate);
+
+    if ((it == end) || !equality(*it, value))
+    {
+      it = end;
+    }
+
+    return it;
+  }
+
+  //***************************************************************************
+  /// find_if_not
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/find"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryPredicate>
+  TIterator find_if_not(TIterator       begin,
+                        TIterator       end,
+                        TUnaryPredicate predicate)
+  {
+    while (begin != end)
+    {
+      if (!predicate(*begin))
+      {
+        return begin;
+      }
+
+      ++begin;
+    }
+
+    return end;
+  }
+
+  //***************************************************************************
+  /// all_of
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryPredicate>
+  bool all_of(TIterator       begin,
+              TIterator       end,
+              TUnaryPredicate predicate)
+  {
+    return etl::find_if_not(begin, end, predicate) == end;
+  }
+
+  //***************************************************************************
+  /// any_of
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryPredicate>
+  bool any_of(TIterator       begin,
+              TIterator       end,
+              TUnaryPredicate predicate)
+  {
+    return std::find_if(begin, end, predicate) != end;
+  }
+
+  //***************************************************************************
+  /// none_of
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryPredicate>
+  bool none_of(TIterator       begin,
+               TIterator       end,
+               TUnaryPredicate predicate)
+  {
+    return std::find_if(begin, end, predicate) == end;
+  }
+
+  //***************************************************************************
+  /// is_permutation
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
+  //***************************************************************************
+  template <typename TIterator1,
+            typename TIterator2>
+  bool is_permutation(TIterator1 begin1,
+                      TIterator1 end1,
+                      TIterator2 begin2)
+  {
+    if (begin1 != end1)
+    {
+      TIterator2 end2 = begin2;
+
+      std::advance(end2, std::distance(begin1, end1));
+
+      for (TIterator1 i = begin1; i != end1; ++i)
+      {
+        if (i == std::find(begin1, i, *i))
+        {
+          int32_t n = std::count(begin2, end2, *i);
+
+          if (n == 0 || std::count(i, end1, *i) != n)
+          {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  //***************************************************************************
+  /// is_permutation
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
+  //***************************************************************************
+  template <typename TIterator1,
+            typename TIterator2>
+  bool is_permutation(TIterator1 begin1,
+                      TIterator1 end1,
+                      TIterator2 begin2,
+                      TIterator2 end2)
+  {
+    if (begin1 != end1)
+    {
+      for (TIterator1 i = begin1; i != end1; ++i)
+      {
+        if (i == std::find(begin1, i, *i))
+        {
+          int32_t n = std::count(begin2, end2, *i);
+
+          if (n == 0 || std::count(i, end1, *i) != n)
+          {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  //***************************************************************************
+  /// is_permutation
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
+  //***************************************************************************
+  template <typename TIterator1,
+            typename TIterator2,
+            typename TBinaryPredicate>
+  bool is_permutation(TIterator1       begin1,
+                      TIterator1       end1,
+                      TIterator2       begin2,
+                      TBinaryPredicate predicate)
+  {
+    if (begin1 != end1)
+    {
+      TIterator2 end2 = begin2;
+
+      std::advance(end2, std::distance(begin1, end1));
+
+      for (TIterator1 i = begin1; i != end1; ++i)
+      {
+        if (i == std::find_if(begin1, i, std::bind1st(predicate, *i)))
+        {
+          int32_t n = std::count(begin2, end2, *i);
+
+          if (n == 0 || std::count(i, end1, *i) != n)
+          {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  //***************************************************************************
+  /// is_permutation
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
+  //***************************************************************************
+  template <typename TIterator1,
+            typename TIterator2,
+            typename TBinaryPredicate>
+  bool is_permutation(TIterator1       begin1,
+                      TIterator1       end1,
+                      TIterator2       begin2,
+                      TIterator2       end2,
+                      TBinaryPredicate predicate)
+  {
+    if (begin1 != end1)
+    {
+      for (TIterator1 i = begin1; i != end1; ++i)
+      {
+        if (i == std::find_if(begin1, i, std::bind1st(predicate, *i)))
+        {
+          int32_t n = std::count(begin2, end2, *i);
+
+          if (n == 0 || std::count(i, end1, *i) != n)
+          {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  //***************************************************************************
+  /// is_partitioned
+  ///\ingroup algorithm
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/is_partitioned"></a>
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryPredicate>
+  bool is_partitioned(TIterator       begin,
+                      TIterator       end,
+                      TUnaryPredicate predicate)
+  {
+    while (begin != end)
+    {
+      if (!predicate(*begin++))
+      {
+        break;
+      }
+    }
+
+    while (begin != end)
+    {
+      if (predicate(*begin++))
+      {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  //***************************************************************************
+  /// partition_point
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/partition_point"></a>
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryPredicate>
+  TIterator partition_point(TIterator       begin,
+                            TIterator       end,
+                            TUnaryPredicate predicate)
+  {
+    while (begin != end)
+    {
+      if (!predicate(*begin))
+      {
+        return begin;
+      }
+
+      ++begin;
+    }
+
+    return begin;
+  }
+
+  //***************************************************************************
+  /// Copies the elements from the range (begin, end) to two different ranges
+  /// depending on the value returned by the predicate.<br>
+  ///<a href="http://en.cppreference.com/w/cpp/algorithm/partition_copy"></a>
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TSource,
+            typename TDestinationTrue,
+            typename TDestinationFalse,
+            typename TUnaryPredicate>
+  std::pair<TDestinationTrue, TDestinationFalse> partition_copy(TSource           begin,
+                                                                TSource           end,
+                                                                TDestinationTrue  destination_true,
+                                                                TDestinationFalse destination_false,
+                                                                TUnaryPredicate   predicate)
+  {
+    while (begin != end)
+    {
+      if (predicate(*begin))
+      {
+        *destination_true++ = *begin++;
+      }
+      else
+      {
+        *destination_false++ = *begin++;
+      }
+    }
+
+    return std::pair<TDestinationTrue, TDestinationFalse>(destination_true, destination_false);
+  }
+
+  //***************************************************************************
+  /// Like std::for_each but applies a predicate before calling the function.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TIterator,
+            typename TUnaryFunction,
+            typename TUnaryPredicate>
+  TUnaryFunction for_each_if(TIterator       begin,
+                             const TIterator end,
+                             TUnaryFunction  function,
+                             TUnaryPredicate predicate)
+  {
+    while (begin != end)
+    {
+      if (predicate(*begin))
+      {
+        function(*begin);
+      }
+
+      ++begin;
+    }
+
+    return function;
+  }
+
+    //***************************************************************************
+  /// Like std::for_each but for 'n' iterations.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TIterator,
+            typename TSize,
+            typename TUnaryFunction>
+  TIterator for_each_n(TIterator       begin,
+                       TSize           n,
+                       TUnaryFunction  function)
+  {
+    while (n-- > 0)
+    {
+      function(*begin++);
+    }
+
+    return begin;
+  }
+
+  //***************************************************************************
+  /// Like std::for_each but applies a predicate before calling the function, for 'n' iterations
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TIterator,
+            typename TSize,
+            typename TUnaryFunction,
+            typename TUnaryPredicate>
+  TIterator for_each_n_if(TIterator       begin,
+                          TSize           n,
+                          TUnaryFunction  function,
+                          TUnaryPredicate predicate)
+  {
+    while (n-- > 0)
+    {
+      if (predicate(*begin))
+      {
+        function(*begin);
+      }
+
+      ++begin;
+    }
+
+    return begin;
+  }
+
+  //***************************************************************************
+  /// A form of std::transform where the transform returns when the first range
+  /// end is reached.
+  /// There is currently no STL equivalent.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TOutputIterator,
+            typename TUnaryFunction>
+  void transform(TInputIterator  i_begin,
+                 TInputIterator  i_end,
+                 TOutputIterator o_begin,
+                 TOutputIterator o_end,
+                 TUnaryFunction  function)
+  {
+    while ((i_begin != i_end) && (o_begin != o_end))
+    {
+      *o_begin++ = function(*i_begin++);
+    }
+  }
+
+  //***************************************************************************
+  /// Transform 'n' items.
+  /// Random iterators.
+  /// There is currently no STL equivalent.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator,
+            typename TUnaryFunction>
+  typename etl::enable_if<etl::is_random_iterator<TInputIterator>::value, void>::type
+   transform_n(TInputIterator  i_begin,
+               TSize           n,
+               TOutputIterator o_begin,
+               TUnaryFunction  function)
+  {
+    std::transform(i_begin, i_begin + n, o_begin, function);
+  }
+
+  //***************************************************************************
+  /// Transform 'n' items from two ranges.
+  /// Random iterators.
+  /// There is currently no STL equivalent.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator1,
+            typename TInputIterator2,
+            typename TSize,
+            typename TOutputIterator,
+            typename TBinaryFunction>
+  typename etl::enable_if<etl::is_random_iterator<TInputIterator1>::value &&
+                          etl::is_random_iterator<TInputIterator2>::value, void>::type
+   transform_n(TInputIterator1 i_begin1,
+               TInputIterator2 i_begin2,
+               TSize           n,
+               TOutputIterator o_begin,
+               TBinaryFunction function)
+  {
+    std::transform(i_begin1, i_begin1 + n, i_begin2, o_begin, function);
+  }
+
+  //***************************************************************************
+  /// Transform 'n' items.
+  /// Non-random iterators.
+  /// There is currently no STL equivalent.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator,
+            typename TUnaryFunction>
+  typename etl::enable_if<!etl::is_random_iterator<TInputIterator>::value, void>::type
+   transform_n(TInputIterator  i_begin,
+               TSize           n,
+               TOutputIterator o_begin,
+               TUnaryFunction  function)
+  {
+    while (n > 0)
+    {
+      *o_begin++ = function(*i_begin++);
+      --n;
+    }
+  }
+
+  //***************************************************************************
+  /// Transform 'n' items from two ranges.
+  /// Non-random iterators.
+  /// There is currently no STL equivalent.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator1,
+            typename TInputIterator2,
+            typename TSize,
+            typename TOutputIterator,
+            typename TBinaryFunction>
+  typename etl::enable_if<!etl::is_random_iterator<TInputIterator1>::value ||
+                          !etl::is_random_iterator<TInputIterator2>::value, void>::type
+   transform_n(TInputIterator1 i_begin1,
+               TInputIterator2 i_begin2,
+               TSize           n,
+               TOutputIterator o_begin,
+               TBinaryFunction function)
+  {
+    while (n > 0)
+    {
+      *o_begin++ = function(*i_begin1++, *i_begin2++);
+      --n;
+    }
+  }
+
+  //***************************************************************************
+  /// Like std::transform but applies a predicate before calling the function.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TOutputIterator,
+            typename TUnaryFunction,
+            typename TUnaryPredicate>
+  TOutputIterator transform_if(TInputIterator       i_begin,
+                               const TInputIterator i_end,
+                               TOutputIterator      o_begin,
+                               TUnaryFunction       function,
+                               TUnaryPredicate      predicate)
+  {
+    while (i_begin != i_end)
+    {
+      if (predicate(*i_begin))
+      {
+        *o_begin++ = function(*i_begin);
+      }
+
+      ++i_begin;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// Like etl::transform_if but inputs from two ranges.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator1,
+            typename TInputIterator2,
+            typename TOutputIterator,
+            typename TBinaryFunction,
+            typename TBinaryPredicate>
+  TOutputIterator transform_if(TInputIterator1       i_begin1,
+                               const TInputIterator1 i_end1,
+                               TInputIterator2       i_begin2,
+                               TOutputIterator       o_begin,
+                               TBinaryFunction       function,
+                               TBinaryPredicate      predicate)
+  {
+    while (i_begin1 != i_end1)
+    {
+      if (predicate(*i_begin1, *i_begin2))
+      {
+        *o_begin++ = function(*i_begin1, *i_begin2);
+      }
+
+      ++i_begin1;
+      ++i_begin2;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// Like std::transform_if, for 'n' items.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator,
+            typename TSize,
+            typename TOutputIterator,
+            typename TUnaryFunction,
+            typename TUnaryPredicate>
+  TOutputIterator transform_n_if(TInputIterator  i_begin,
+                                 TSize           n,
+                                 TOutputIterator o_begin,
+                                 TUnaryFunction  function,
+                                 TUnaryPredicate predicate)
+  {
+    while (n-- > 0)
+    {
+      if (predicate(*i_begin))
+      {
+        *o_begin++ = function(*i_begin);
+      }
+
+      ++i_begin;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// Like etl::transform_if but inputs from two ranges for 'n' items.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TInputIterator1,
+            typename TInputIterator2,
+            typename TSize,
+            typename TOutputIterator,
+            typename TBinaryFunction,
+            typename TBinaryPredicate>
+  TOutputIterator transform_n_if(TInputIterator1  i_begin1,
+                                 TInputIterator2  i_begin2,
+                                 TSize            n,
+                                 TOutputIterator  o_begin,
+                                 TBinaryFunction  function,
+                                 TBinaryPredicate predicate)
+  {
+    while (n-- > 0)
+    {
+      if (predicate(*i_begin1, *i_begin2))
+      {
+        *o_begin++ = function(*i_begin1, *i_begin2);
+      }
+
+      ++i_begin1;
+      ++i_begin2;
+    }
+
+    return o_begin;
+  }
+
+  //***************************************************************************
+  /// Transforms the elements from the range (begin, end) to two different ranges
+  /// depending on the value returned by the predicate.<br>
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TSource, typename TDestinationTrue, typename TDestinationFalse,
+            typename TUnaryFunctionTrue, typename TUnaryFunctionFalse,
+            typename TUnaryPredicate>
+  std::pair<TDestinationTrue, TDestinationFalse> partition_transform(TSource             begin,
+                                                                     TSource             end,
+                                                                     TDestinationTrue    destination_true,
+                                                                     TDestinationFalse   destination_false,
+                                                                     TUnaryFunctionTrue  function_true,
+                                                                     TUnaryFunctionFalse function_false,
+                                                                     TUnaryPredicate     predicate)
+  {
+    while (begin != end)
+    {
+      if (predicate(*begin))
+      {
+        *destination_true++ = function_true(*begin++);
+      }
+      else
+      {
+        *destination_false++ = function_false(*begin++);
+      }
+    }
+
+    return std::pair<TDestinationTrue, TDestinationFalse>(destination_true, destination_false);
+  }
+
+  //***************************************************************************
+  /// Transforms the elements from the ranges (begin1, end1) & (begin2)
+  /// to two different ranges depending on the value returned by the predicate.
+  ///\ingroup algorithm
+  //***************************************************************************
+  template <typename TSource1,
+            typename TSource2,
+            typename TDestinationTrue,
+            typename TDestinationFalse,
+            typename TBinaryFunctionTrue,
+            typename TBinaryFunctionFalse,
+            typename TBinaryPredicate>
+  std::pair<TDestinationTrue, TDestinationFalse> partition_transform(TSource1             begin1,
+                                                                     TSource1             end1,
+                                                                     TSource2             begin2,
+                                                                     TDestinationTrue     destination_true,
+                                                                     TDestinationFalse    destination_false,
+                                                                     TBinaryFunctionTrue  function_true,
+                                                                     TBinaryFunctionFalse function_false,
+                                                                     TBinaryPredicate     predicate)
+  {
+    while (begin1 != end1)
+    {
+      if (predicate(*begin1, *begin2))
+      {
+        *destination_true++ = function_true(*begin1++, *begin2++);
+      }
+      else
+      {
+        *destination_false++ = function_false(*begin1++, *begin2++);
+      }
+    }
+
+    return std::pair<TDestinationTrue, TDestinationFalse>(destination_true, destination_false);
+  }
+}
+
+#endif
+
+