diff --git a/library.json b/library.json index 69f6941..cb598ae 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.38.11", + "version": "20.38.17", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index d13b639..5feed38 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.38.11 +version=20.38.17 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/src/etl/absolute.h b/src/etl/absolute.h index 5812f86..7bc5ea6 100644 --- a/src/etl/absolute.h +++ b/src/etl/absolute.h @@ -40,8 +40,10 @@ namespace etl // For signed types. //*************************************************************************** template - ETL_CONSTEXPR typename etl::enable_if::value, T>::type - absolute(T value) + ETL_NODISCARD + ETL_CONSTEXPR + typename etl::enable_if::value, T>::type + absolute(T value) ETL_NOEXCEPT { return (value < T(0)) ? -value : value; } @@ -50,8 +52,10 @@ namespace etl // For unsigned types. //*************************************************************************** template - ETL_CONSTEXPR typename etl::enable_if::value, T>::type - absolute(T value) + ETL_NODISCARD + ETL_CONSTEXPR + typename etl::enable_if::value, T>::type + absolute(T value) ETL_NOEXCEPT { return value; } @@ -65,8 +69,10 @@ namespace etl #else template #endif - ETL_CONSTEXPR typename etl::enable_if::value, TReturn>::type - absolute_unsigned(T value) + ETL_NODISCARD + ETL_CONSTEXPR + typename etl::enable_if::value, TReturn>::type + absolute_unsigned(T value) ETL_NOEXCEPT { return (value == etl::integral_limits::min) ? (etl::integral_limits::max / 2U) + 1U : (value < T(0)) ? TReturn(-value) : TReturn(value); @@ -77,8 +83,10 @@ namespace etl // Returns the result as the unsigned type. //*************************************************************************** template - ETL_CONSTEXPR typename etl::enable_if::value, T>::type - absolute_unsigned(T value) + ETL_NODISCARD + ETL_CONSTEXPR + typename etl::enable_if::value, T>::type + absolute_unsigned(T value) ETL_NOEXCEPT { return etl::absolute(value); } diff --git a/src/etl/algorithm.h b/src/etl/algorithm.h index cc989d1..59f8b9b 100644 --- a/src/etl/algorithm.h +++ b/src/etl/algorithm.h @@ -43,6 +43,7 @@ SOFTWARE. #include "iterator.h" #include "functional.h" #include "utility.h" +#include "gcd.h" #include #include @@ -169,6 +170,18 @@ namespace etl return first2; } + //*************************************************************************** + // generate + template + ETL_CONSTEXPR14 + void generate(TIterator db, TIterator de, TFunction funct) + { + while (db != de) + { + *db++ = funct(); + } + } + //*************************************************************************** // copy #if ETL_USING_STL && ETL_USING_CPP20 @@ -1144,21 +1157,148 @@ namespace etl //*************************************************************************** namespace private_algorithm { +#if ETL_USING_CPP11 //********************************* + // For random access iterators template ETL_CONSTEXPR14 - TIterator rotate_general(TIterator first, TIterator middle, TIterator last) + typename etl::enable_if::value, TIterator>::type + rotate_general(TIterator first, TIterator middle, TIterator last) { - TIterator next = middle; + if (first == middle || middle == last) + { + return first; + } - while (first != next) + typedef typename etl::iterator_traits::value_type value_type; + + int n = last - first; + int m = middle - first; + int gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m); + + TIterator result = first + (last - middle); + + for (int i = 0; i < gcd_nm; i++) { - using ETL_OR_STD::swap; // Allow ADL + value_type temp = etl::move(*(first + i)); + int j = i; + + while (true) + { + int k = j + m; + + if (k >= n) + { + k = k - n; + } + + if (k == i) + { + break; + } - swap(*first, *next); + *(first + j) = etl::move(*(first + k)); + j = k; + } - ++first; - ++next; + *(first + j) = etl::move(temp); + } + + return result; + } +#else + //********************************* + // For random access iterators + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, TIterator>::type + rotate_general(TIterator first, TIterator middle, TIterator last) + { + if (first == middle || middle == last) + { + return first; + } + + typedef typename etl::iterator_traits::value_type value_type; + + int n = last - first; + int m = middle - first; + int gcd_nm = (n == 0 || m == 0) ? n + m : etl::gcd(n, m); + + TIterator result = first + (last - middle); + + for (int i = 0; i < gcd_nm; i++) + { + value_type temp = *(first + i); + int j = i; + + while (true) + { + int k = j + m; + + if (k >= n) + { + k = k - n; + } + + if (k == i) + { + break; + } + + *(first + j) = *(first + k); + j = k; + } + + *(first + j) = temp; + } + + return result; + } +#endif + + //********************************* + // For bidirectional iterators + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, TIterator>::type + rotate_general(TIterator first, TIterator middle, TIterator last) + { + if (first == middle || middle == last) + { + return first; + } + + TIterator result = first; + etl::advance(result, etl::distance(middle, last)); + + reverse(first, middle); + reverse(middle, last); + reverse(first, last); + + return result; + } + + //********************************* + // For forward iterators + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, TIterator>::type + rotate_general(TIterator first, TIterator middle, TIterator last) + { + if (first == middle || middle == last) + { + return first; + } + + TIterator next = middle; + TIterator result = first; + etl::advance(result, etl::distance(middle, last)); + + while (first != next) + { + using ETL_OR_STD::swap; + swap(*first++, *next++); if (next == last) { @@ -1170,10 +1310,11 @@ namespace etl } } - return first; + return result; } //********************************* + // Simplified algorithm for rotate left by one template ETL_CONSTEXPR14 TIterator rotate_left_by_one(TIterator first, TIterator last) @@ -1194,6 +1335,7 @@ namespace etl } //********************************* + // Simplified for algorithm rotate right by one template ETL_CONSTEXPR14 TIterator rotate_right_by_one(TIterator first, TIterator last) @@ -1227,7 +1369,18 @@ namespace etl if (etl::next(middle) == last) { - return private_algorithm::rotate_right_by_one(first, last); +#if ETL_USING_CPP20 + if ETL_IF_CONSTEXPR(etl::is_forward_iterator::value) + { + return private_algorithm::rotate_general(first, middle, last); + } + else + { + return private_algorithm::rotate_right_by_one(first, last); + } +#else + return private_algorithm::rotate_general(first, middle, last); +#endif } return private_algorithm::rotate_general(first, middle, last); @@ -1989,19 +2142,33 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template - ETL_CONSTEXPR - const T& clamp(const T& value, const T& low, const T& high, TCompare compare) + ETL_CONSTEXPR + T clamp(const T& value, const T& low, const T& high, TCompare compare) { return compare(value, low) ? low : compare(high, value) ? high : value; } template - ETL_CONSTEXPR - const T& clamp(const T& value, const T& low, const T& high ) + ETL_CONSTEXPR + T clamp(const T& value, const T& low, const T& high) { return clamp(value, low, high, etl::less()); } + template + ETL_CONSTEXPR + T clamp(const T& value, TCompare compare) + { + return compare(value, Low) ? Low : compare(High, value) ? High : value; + } + + template + ETL_CONSTEXPR + T clamp(const T& value) + { + return clamp(value, etl::less()); + } + //*************************************************************************** /// Remove ///\ingroup algorithm @@ -2009,22 +2176,19 @@ namespace etl template ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T& value) - { + { first = etl::find(first, last, value); - + if (first != last) { TIterator itr = first; - while (itr != last) + while (++itr != last) { if (!(*itr == value)) { - *first = etl::move(*itr); - ++first; + *first++ = etl::move(*itr); } - - ++itr; } } @@ -2045,19 +2209,16 @@ namespace etl { TIterator itr = first; - while (itr != last) + while (++itr != last) { if (!predicate(*itr)) { - *first = etl::move(*itr); - ++first; + *first++ = etl::move(*itr); } - - ++itr; } } - return first; + return first; } } @@ -2177,7 +2338,7 @@ namespace etl //*************************************************************************** /// copy_if /// A safer form of copy_if where it terminates when the first end iterator is reached. - /// There is currently no STL equivelent. + /// There is currently no STL equivalent. ///\ingroup algorithm //*************************************************************************** template + ETL_CONSTEXPR14 + typename etl::enable_if::value, TIterator>::type + partition(TIterator first, TIterator last, TPredicate predicate) + { + first = etl::find_if_not(first, last, predicate); + + if (first == last) + { + return first; + } + + for (TIterator i = etl::next(first); i != last; ++i) + { + if (predicate(*i)) + { + using ETL_OR_STD::swap; + swap(*i, *first); + ++first; + } + } + + return first; + } + + //*************************************************************************** + /// partition + /// For iterators that support bidirectional iteration. + /// Does at most (etl::distance(first, last) / 2) swaps. + //*************************************************************************** + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, TIterator>::type + partition(TIterator first, TIterator last, TPredicate predicate) + { + while (first != last) + { + first = etl::find_if_not(first, last, predicate); + + if (first == last) + { + break; + } + + last = etl::find_if(etl::reverse_iterator(last), + etl::reverse_iterator(first), + predicate).base(); + + if (first == last) + { + break; + } + + --last; + using ETL_OR_STD::swap; + swap(*first, *last); + ++first; + } + + return first; + } + + //********************************************************* + namespace private_algorithm + { + using ETL_OR_STD::swap; + + template +#if (ETL_USING_CPP20 && ETL_USING_STL) || (ETL_USING_CPP14 && ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)) + constexpr +#endif + TIterator nth_partition(TIterator first, TIterator last, TCompare compare) + { + typedef typename etl::iterator_traits::value_type value_type; + + TIterator pivot = last; // Maybe find a better pivot choice? + value_type pivot_value = *pivot; + + // Swap the pivot with the last, if necessary. + if (pivot != last) + { + swap(*pivot, *last); + } + + TIterator i = first; + + for (TIterator j = first; j < last; ++j) + { + if (!compare(pivot_value, *j)) // Hack to get '*j <= pivot_value' in terms of 'pivot_value < *j' + { + swap(*i, *j); + ++i; + } + } + + swap(*i, *last); + + return i; + } + } + + //********************************************************* + /// nth_element + /// see https://en.cppreference.com/w/cpp/algorithm/nth_element + //********************************************************* +#if ETL_USING_CPP11 + template ::value_type>> +#if (ETL_USING_CPP20 && ETL_USING_STL) || (ETL_USING_CPP14 && ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)) + constexpr +#endif + typename etl::enable_if::value, void>::type + nth_element(TIterator first, TIterator nth, TIterator last, TCompare compare = TCompare()) + { + if (first == last) + { + return; + } + + // 'last' must point to the actual last value. + --last; + + while (first <= last) + { + TIterator p = private_algorithm::nth_partition(first, last, compare); + + if (p == nth) + { + return; + } + else if (p > nth) + { + last = p - 1; + } + else + { + first = p + 1; + } + } + } + +#else + + //********************************************************* + template + typename etl::enable_if::value, void>::type + nth_element(TIterator first, TIterator nth, TIterator last, TCompare compare) + { + if (first == last) + { + return; + } + + // 'last' must point to the actual last value. + --last; + + while (first <= last) + { + TIterator p = private_algorithm::nth_partition(first, last, compare); + + if (p == nth) + { + return; + } + else if (p > nth) + { + last = p - 1; + } + else + { + first = p + 1; + } + } + } + + //********************************************************* + template + typename etl::enable_if::value, void>::type + nth_element(TIterator first, TIterator nth, TIterator last) + { + typedef etl::less::value_type> compare_t; + + nth_element(first, last, compare_t()); + } +#endif } #include "private/minmax_pop.h" diff --git a/src/etl/array.h b/src/etl/array.h index 52f0f65..0a41fae 100644 --- a/src/etl/array.h +++ b/src/etl/array.h @@ -94,15 +94,15 @@ namespace etl static ETL_CONSTANT size_t SIZE = SIZE_; - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; @@ -115,6 +115,7 @@ namespace etl ///\param i The index of the element to access. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 reference at(size_t i) { ETL_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range)); @@ -141,6 +142,7 @@ namespace etl ///\param i The index of the element to access. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 reference operator[](size_t i) { return _buffer[i]; @@ -161,6 +163,7 @@ namespace etl /// Returns a reference to the first element. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 reference front() { return _buffer[0]; @@ -179,6 +182,7 @@ namespace etl /// Returns a reference to the last element. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 reference back() { return _buffer[SIZE - 1]; @@ -197,6 +201,7 @@ namespace etl /// Returns a pointer to the first element of the internal buffer. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 pointer data() ETL_NOEXCEPT { return &_buffer[0]; @@ -219,6 +224,7 @@ namespace etl /// Returns an iterator to the beginning of the array. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 iterator begin() ETL_NOEXCEPT { return &_buffer[0]; @@ -246,6 +252,7 @@ namespace etl /// Returns an iterator to the end of the array. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 iterator end() ETL_NOEXCEPT { return _buffer + SIZE; @@ -273,6 +280,7 @@ namespace etl // Returns an reverse iterator to the reverse beginning of the array. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 reverse_iterator rbegin() ETL_NOEXCEPT { return reverse_iterator(end()); @@ -300,6 +308,7 @@ namespace etl /// Returns a reverse iterator to the end of the array. //************************************************************************* ETL_NODISCARD + ETL_CONSTEXPR14 reverse_iterator rend() ETL_NOEXCEPT { return reverse_iterator(begin()); @@ -386,11 +395,12 @@ namespace etl /// If the range is smaller than the array then the unused array elements are left unmodified. ///\param first The iterator to the first item in the range. ///\param last The iterator to one past the final item in the range. + ///\return An iterator to the first unassigned array element, or end(). //************************************************************************* template - void assign(TIterator first, const TIterator last) + iterator assign(TIterator first, const TIterator last) { - etl::copy_s(first, last, begin(), end()); + return etl::copy_s(first, last, begin(), end()); } //************************************************************************* @@ -398,15 +408,18 @@ namespace etl /// If the range is smaller than the array then the unused array elements are initialised with the supplied value. ///\param first The iterator to the first item in the range. ///\param last The iterator to one past the final item in the range. + ///\return An iterator to the first array element set to 'value', or end(). //************************************************************************* template - void assign(TIterator first, const TIterator last, parameter_t value) + iterator assign(TIterator first, const TIterator last, parameter_t value) { // Copy from the range. - iterator p = etl::copy(first, last, begin()); + iterator p = etl::copy_s(first, last, begin(), end()); // Initialise any that are left. etl::fill(p, end(), value); + + return p; } //************************************************************************* diff --git a/src/etl/atomic/atomic_gcc_sync.h b/src/etl/atomic/atomic_gcc_sync.h index 152279d..9e7399a 100644 --- a/src/etl/atomic/atomic_gcc_sync.h +++ b/src/etl/atomic/atomic_gcc_sync.h @@ -167,7 +167,7 @@ namespace etl T operator --(int) volatile { - return __atomic_fetch_sub(&value, 1), etl::memory_order_seq_cst; + return __atomic_fetch_sub(&value, 1, etl::memory_order_seq_cst); } // Add diff --git a/src/etl/basic_format_spec.h b/src/etl/basic_format_spec.h index 90a48c1..36c2d74 100644 --- a/src/etl/basic_format_spec.h +++ b/src/etl/basic_format_spec.h @@ -172,10 +172,10 @@ namespace etl static ETL_CONSTANT private_basic_format_spec::base_spec hex(16U); //********************************* - static ETL_CONSTANT private_basic_format_spec::left_spec left; + static ETL_CONSTANT private_basic_format_spec::left_spec left = private_basic_format_spec::left_spec(); //********************************* - static ETL_CONSTANT private_basic_format_spec::right_spec right; + static ETL_CONSTANT private_basic_format_spec::right_spec right = private_basic_format_spec::right_spec(); //********************************* static ETL_CONSTANT private_basic_format_spec::boolalpha_spec boolalpha(true); diff --git a/src/etl/basic_string.h b/src/etl/basic_string.h index 8afdf18..6b01c61 100644 --- a/src/etl/basic_string.h +++ b/src/etl/basic_string.h @@ -1262,7 +1262,7 @@ namespace etl /// Erases a sequence. ///\param position Position to start from. ///\param length Number of characters. - ///\return A refernce to this string. + ///\return A reference to this string. //********************************************************************* etl::ibasic_string& erase(size_type position, size_type length_ = npos) { diff --git a/src/etl/basic_string_stream.h b/src/etl/basic_string_stream.h index e91ee1f..2b46605 100644 --- a/src/etl/basic_string_stream.h +++ b/src/etl/basic_string_stream.h @@ -58,28 +58,28 @@ namespace etl } //************************************************************************* - /// Construct from text and format spec. + /// Construct from text and format fmt. //************************************************************************* basic_string_stream(TIString& text_, const TFormat& spec_) : text(text_) - , spec(spec_) + , format(spec_) { } //************************************************************************* - /// Set the format spec. + /// Set the format fmt. //************************************************************************* void set_format(const TFormat& spec_) { - spec = spec_; + format = spec_; } //************************************************************************* - /// Get a const reference to the format spec. + /// Get a const reference to the format fmt. //************************************************************************* const TFormat& get_format() const { - return spec; + return format; } //************************************************************************* @@ -121,27 +121,27 @@ namespace etl //********************************* /// TFormat //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, const TFormat& spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, const TFormat& fmt) { - ss.spec = spec; + ss.format = fmt; return ss; } //********************************* /// etl::base_spec from etl::setbase, etl::bin, etl::oct, etl::dec & etl::hex stream manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::base_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::base_spec fmt) { - ss.spec.base(spec.base); + ss.format.base(fmt.base); return ss; } //********************************* /// etl::width_spec from etl::setw stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::width_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::width_spec fmt) { - ss.spec.width(spec.width); + ss.format.width(fmt.width); return ss; } @@ -149,63 +149,63 @@ namespace etl /// etl::fill_spec from etl::setfill stream manipulator //********************************* template - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::fill_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::fill_spec fmt) { - ss.spec.fill(spec.fill); + ss.format.fill(fmt.fill); return ss; } //********************************* /// etl::precision_spec from etl::setprecision stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::precision_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::precision_spec fmt) { - ss.spec.precision(spec.precision); + ss.format.precision(fmt.precision); return ss; } //********************************* /// etl::boolalpha_spec from etl::boolalpha & etl::noboolalpha stream manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::boolalpha_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::boolalpha_spec fmt) { - ss.spec.boolalpha(spec.boolalpha); + ss.format.boolalpha(fmt.boolalpha); return ss; } //********************************* /// etl::uppercase_spec from etl::uppercase & etl::nouppercase stream manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::uppercase_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::uppercase_spec fmt) { - ss.spec.upper_case(spec.upper_case); + ss.format.upper_case(fmt.upper_case); return ss; } //********************************* /// etl::showbase_spec from etl::showbase & etl::noshowbase stream manipulators //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::showbase_spec spec) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::showbase_spec fmt) { - ss.spec.show_base(spec.show_base); + ss.format.show_base(fmt.show_base); return ss; } //********************************* /// etl::left_spec from etl::left stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::left_spec /*spec*/) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::left_spec /*fmt*/) { - ss.spec.left(); + ss.format.left(); return ss; } //********************************* /// etl::right_spec from etl::left stream manipulator //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::right_spec /*spec*/) + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::right_spec /*fmt*/) { - ss.spec.right(); + ss.format.right(); return ss; } @@ -214,7 +214,7 @@ namespace etl //********************************* friend basic_string_stream& operator <<(basic_string_stream& ss, TStringView view) { - etl::to_string(view, ss.text, ss.spec, true); + etl::to_string(view, ss.text, ss.format, true); return ss; } @@ -241,9 +241,9 @@ namespace etl //********************************* /// From a string interface //********************************* - friend basic_string_stream& operator <<(basic_string_stream& ss, const TIString& text) + friend basic_string_stream& operator <<(basic_string_stream& ss, const TIString& t) { - etl::to_string(text, ss.text, ss.spec, true); + etl::to_string(t, ss.text, ss.format, true); return ss; } @@ -251,9 +251,9 @@ namespace etl /// From a string //********************************* template