diff --git a/.github/workflows/compile_examples.yml b/.github/workflows/compile_examples.yml index 786f5ea..0dc094c 100644 --- a/.github/workflows/compile_examples.yml +++ b/.github/workflows/compile_examples.yml @@ -8,7 +8,7 @@ on: jobs: unittests-linux-generic: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest container: image: ghcr.io/modm-ext/modm-build-avr:latest @@ -19,7 +19,7 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Check environment run: | diff --git a/README.md b/README.md index 5d9fdeb..0fff531 100644 --- a/README.md +++ b/README.md @@ -238,12 +238,9 @@ and their directly relevant code sequences have been removed. Simple mechanisms such as those found in `` and ``, however, remain mostly available. -- **``:** Even though the intended compilers are built with no threading, -the `` library and its use as a dependency has -been removed. This means that atomic functions and -atomic store/load functions are not available. So if you are sharing -data in an operating system or mixed program/interrupt mode, -self-written atomic primitives are needed. +- **``:** The `` library is being handled +specifically in the draft of +[avr-libstdcpp/pull/36](https://github.com/modm-io/avr-libstdcpp/pull/36). - **``:** There is no source of entropy whatsoever on these platforms in their standard configuration. So `std::random_device` @@ -280,12 +277,6 @@ The widths depend on the compiler command line options `-mdouble=32` `std::exp()` and the like will, therefore, have input and output widths according to these command line options. -- **``:** In compiler versions of `avr-gcc` 11 and higher, -slight discrepancies in the signatures of functions like -`isnan()`, `isinf()`, etc. seem to be in the process of being corrected. -Future patches of math function signatures in `` -may be needed as the `` header continues to evolve. - ## C++20 `constexpr` support The following is a rather advanced, highly useful topic. @@ -337,18 +328,24 @@ int main() ``` See also the [numeric.cpp](./examples/numeric/numeric.cpp) file -in the [./examples/numeric](./examples/numeric) directory. +in the [/examples/numeric](./examples/numeric) directory. ## Additional details `avr-libstdcpp` is intended for a modern `avr-gcc` -such as the 11.2 port available in the [modm-io project](https://github.com/modm-io/avr-gcc) -repository. Tests show usability also for `avr-gcc` 10 through 13 (and beyond). +such as the port available in the [modm-io project](https://github.com/modm-io/avr-gcc) +repository. Tests show usability for `avr-gcc` 7 through 15. + +This library has been checked for compatibility on `avr-gcc` +with language standards C++11,14,17,20,23 and 2c. -Using the port way back to `avr-gcc` 5, however, does not work +Using the port way back to `avr-gcc` 5 does not work at the moment with today's form of the checked-in library, -as the older compiler's lexical parser is not capable of -properly handling some of the library's template code. +and `avr-gcc` 7 or higher is required. +This is because the very old compiler lexical parsers are not capable +of properly handling some of the library's template code. +See also [avr-libstdcpp/issues/15](https://github.com/modm-io/avr-libstdcpp/issues/15) +which is closed and includes justification for its closure. ## Licensing @@ -357,6 +354,6 @@ and the library include files in [`include/` and its subfolders](./include/) (with two exceptions for the sources, as mentioned below) are licensed under [GNU General Public License Version 3](./COPYING3) or higher. -The [example codes](./examples/) and two library source files +All of the [example codes](./examples/) and also two library source files (namely `functexcept.cc` and `math.cc` in [`src/`](./src/)) are subject to the terms of the [Mozilla Public License Version 2.0](./COPYING.MPLv2). diff --git a/examples/cmath/cmath.cpp b/examples/cmath/cmath.cpp index 4674ee8..8bc6bca 100644 --- a/examples/cmath/cmath.cpp +++ b/examples/cmath/cmath.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Christopher Kormanyos + * Copyright (c) 2022, 2025, Christopher Kormanyos * * This file is part of the modm project. * @@ -33,7 +33,7 @@ auto integral real_value_type step = ((b - a) / 2U); real_value_type result = (real_function(a) + real_function(b)) * step; - const std::uint_fast8_t k_max = UINT8_C(32); + constexpr std::uint_fast8_t k_max { UINT8_C(32) }; for(std::uint_fast8_t k = UINT8_C(0); k < k_max; ++k) { @@ -80,12 +80,29 @@ auto is_close_fraction using floating_point_type = FloatingPointType; using std::fabs; + using std::fpclassify; - const floating_point_type ratio = fabs(floating_point_type((floating_point_type(1) * a) / b)); + const int fpc_a { fpclassify(a) }; + const int fpc_b { fpclassify(b) }; - const floating_point_type closeness = fabs(floating_point_type(1 - ratio)); + bool result_is_ok { }; - return (closeness < tol); + if(fpc_b == FP_ZERO) + { + const floating_point_type closeness { (fpc_a == FP_ZERO) ? floating_point_type { 0 } : fabs(a - b) }; + + result_is_ok = (closeness < tol); + } + else + { + const floating_point_type ratio = fabs(floating_point_type((floating_point_type(1) * a) / b)); + + const floating_point_type closeness = fabs(floating_point_type(1 - ratio)); + + result_is_ok = (closeness < tol); + } + + return result_is_ok; } // N[Pi, 51] @@ -108,7 +125,7 @@ auto cyl_bessel_j(const std::uint_fast8_t n, const FloatingPointType& x) noexcep using std::sin; using std::sqrt; - const auto tol = sqrt(epsilon); + const floating_point_type tol { sqrt(epsilon) }; const auto integration_result = detail::integral @@ -121,7 +138,7 @@ auto cyl_bessel_j(const std::uint_fast8_t n, const FloatingPointType& x) noexcep return cos(x * sin(t) - (t * static_cast(n))); }); - const auto jn = static_cast(integration_result / detail::pi_v); + const floating_point_type jn { static_cast(integration_result / detail::pi_v) }; return jn; } @@ -130,9 +147,9 @@ auto cyl_bessel_j(const std::uint_fast8_t n, const FloatingPointType& x) noexcep auto main() -> int { - using my_float_type = long double; + using my_float_type = std::float_t; - static_assert((std::numeric_limits::digits >= 24), "Error: Incorrect my_float_type type definition"); + static_assert((std::numeric_limits::digits == 24), "Error: Incorrect my_float_type type definition"); constexpr my_float_type my_tol = static_cast diff --git a/include/bits/stl_iterator.h b/include/bits/stl_iterator.h index 130748e..7d293ce 100644 --- a/include/bits/stl_iterator.h +++ b/include/bits/stl_iterator.h @@ -2150,6 +2150,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const counted_iterator<_It2>& __y) { return __y._M_length <=> __x._M_length; } + private: + template friend class counted_iterator; + + _It _M_current = _It(); + iter_difference_t<_It> _M_length = 0; + friend constexpr iter_rvalue_reference_t<_It> iter_move(const counted_iterator& __i) noexcept(noexcept(ranges::iter_move(__i._M_current))) @@ -2162,12 +2168,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const counted_iterator<_It2>& __y) noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) { ranges::iter_swap(__x._M_current, __y._M_current); } - - private: - template friend class counted_iterator; - - _It _M_current = _It(); - iter_difference_t<_It> _M_length = 0; }; template diff --git a/include/cmath b/include/cmath index 6654ee1..2232ef2 100644 --- a/include/cmath +++ b/include/cmath @@ -611,8 +611,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #undef islessgreater #undef isunordered +#if !defined(FP_NAN) && !defined(FP_INFINITE) && !defined(FP_ZERO) \ + && !defined(FP_SUBNORMAL) && !defined(FP_NORMAL) +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 +#elif !defined(FP_NAN) || !defined(FP_INFINITE) || !defined(FP_ZERO) \ + || !defined(FP_SUBNORMAL) || !defined(FP_NORMAL) +#error "Some floating-point number classification macros are missing." +#error "Either define all of them or define none of them so that can do it." +#endif + #if __cplusplus >= 201103L +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr int + fpclassify(float __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } + + constexpr int + fpclassify(double __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } + + constexpr int + fpclassify(long double __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + int>::__type + fpclassify(_Tp __x) + { return __x != 0 ? FP_NORMAL : FP_ZERO; } +#endif + #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr bool isfinite(float __x)