From f09c2b6fe4b35b3235c7dab4a80415ee97aea104 Mon Sep 17 00:00:00 2001 From: Christopher Kormanyos Date: Sun, 25 Feb 2024 11:45:17 +0100 Subject: [PATCH] Initial update example chapter04_04 --- examples/chapter04_04/chapter04_04.vcxproj | 74 +- .../chapter04_04/chapter04_04.vcxproj.filters | 77 +- examples/chapter04_04/libwinpthread-1.dll | Bin 59643 -> 0 bytes .../src/mcal/avr/mcal_pwm_timer1.h | 5 +- examples/chapter04_04/src/mcal/mcal.cpp | 5 +- examples/chapter04_04/src/mcal/mcal.h | 2 +- .../src/mcal/mcal_gcc_cxx_completion.cpp | 86 +- examples/chapter04_04/src/mcal/mcal_helper.h | 66 + .../src/mcal/mcal_reg_access_dynamic.h | 57 +- .../src/mcal/mcal_reg_access_static.h | 55 +- .../chapter04_04/src/mcal_led/mcal_led_base.h | 23 +- .../mcal_led/mcal_led_boolean_state_base.h | 34 + .../src/mcal_led/mcal_led_console.h | 40 +- .../chapter04_04/src/mcal_led/mcal_led_port.h | 31 +- .../src/mcal_led/mcal_led_port_inverted.h | 39 + .../chapter04_04/src/mcal_led/mcal_led_pwm.h | 30 +- .../src/mcal_led/mcal_led_rgb_base.h | 99 + .../mcal_memory_progmem_iterator.h | 16 +- .../src/mcal_memory/mcal_memory_sram_ptr.h | 4 +- .../mcal_memory/mcal_memroy_sram_iterator.h | 16 +- .../chapter04_04/src/mcal_pwm/mcal_pwm_base.h | 28 +- .../src/mcal_pwm/mcal_pwm_console.h | 20 +- .../src/mcal_pwm/mcal_pwm_dummy.h | 19 +- .../chapter04_04/src/mcal_pwm/mcal_pwm_port.h | 74 + .../src/mcal_spi/mcal_spi_software_dummy.h | 16 +- .../mcal_spi/mcal_spi_software_port_driver.h | 8 +- examples/chapter04_04/src/os/os.cpp | 75 +- examples/chapter04_04/src/os/os.h | 16 +- examples/chapter04_04/src/os/os_cfg.h | 59 +- .../src/os/os_task_control_block.cpp | 8 +- .../src/os/os_task_control_block.h | 62 +- .../chapter04_04/src/util/STD_LIBC/memory.c | 87 + .../chapter04_04/src/util/STD_LIBC/memory.cpp | 83 - examples/chapter04_04/src/util/STL/algorithm | 171 +- examples/chapter04_04/src/util/STL/array | 77 +- examples/chapter04_04/src/util/STL/cassert | 13 + examples/chapter04_04/src/util/STL/cerrno | 13 + examples/chapter04_04/src/util/STL/charconv | 47 + examples/chapter04_04/src/util/STL/chrono | 9 +- examples/chapter04_04/src/util/STL/cinttypes | 23 + examples/chapter04_04/src/util/STL/ciso646 | 15 + examples/chapter04_04/src/util/STL/cmath | 892 +++++--- examples/chapter04_04/src/util/STL/complex | 6 +- examples/chapter04_04/src/util/STL/cstdint | 29 +- examples/chapter04_04/src/util/STL/cstdlib | 24 +- examples/chapter04_04/src/util/STL/cstring | 21 +- examples/chapter04_04/src/util/STL/functional | 16 +- .../src/util/STL/impl/alloc_traits.h | 302 +++ .../src/util/STL/impl/avr/avr_atomic.h | 4 +- .../util/STL/impl/avr/avr_float_limits.cpp | 69 - .../impl/avr/avr_hardware_random_device.cpp | 41 + .../src/util/STL/impl/cmath_impl_gamma.cpp | 140 -- .../util/STL/impl/cmath_impl_hyperbolic.cpp | 84 - .../src/util/STL/impl/ptr_traits.h | 183 ++ .../src/util/STL/impl/stl_local_constexpr.h | 26 +- .../src/util/STL/impl/stl_local_noexcept.h | 2 + .../src/util/STL/impl/xcmath_impl.h | 27 +- examples/chapter04_04/src/util/STL/iterator | 109 +- examples/chapter04_04/src/util/STL/limits | 1295 ++++++------ examples/chapter04_04/src/util/STL/memory | 111 +- examples/chapter04_04/src/util/STL/random | 1785 +++++++++++++++-- examples/chapter04_04/src/util/STL/ratio | 2 +- examples/chapter04_04/src/util/STL/stdexcept | 110 + examples/chapter04_04/src/util/STL/string | 6 + examples/chapter04_04/src/util/STL/time.h | 4 +- examples/chapter04_04/src/util/STL/tuple | 578 +++--- .../chapter04_04/src/util/STL/type_traits | 319 ++- examples/chapter04_04/src/util/STL/utility | 45 +- .../src/util/STL_C++XX_stdfloat/cstdfloat | 2 +- .../src/util/memory/util_factory.h | 2 +- .../util/memory/util_n_slot_array_allocator.h | 195 ++ .../src/util/memory/util_placed_pointer.h | 2 +- .../src/util/memory/util_ring_allocator.h | 4 +- .../src/util/memory/util_static_allocator.h | 4 +- .../src/util/utility/util_alignas.h | 2 +- .../src/util/utility/util_baselexical_cast.h | 173 ++ .../src/util/utility/util_communication.h | 69 +- .../utility/util_constexpr_algorithm_unsafe.h | 200 ++ .../utility/util_constexpr_cmath_unsafe.h | 90 + .../src/util/utility/util_display.h | 44 + .../src/util/utility/util_dynamic_array.h | 455 +++-- .../util/utility/util_linear_interpolate.h | 2 +- .../src/util/utility/util_narrow_cast.h | 22 + .../src/util/utility/util_noncopyable.h | 50 +- .../chapter04_04/src/util/utility/util_swdm.h | 4 +- .../chapter04_04/src/util/utility/util_time.h | 104 +- .../utility/util_two_part_data_manipulation.h | 2 +- .../src/util/utility/util_utype_helper.h | 2 +- examples/chapter04_04/target.vcxproj | 4 +- .../chapter04_04/target/app/make/app_make.gmk | 202 +- .../target/app/make/app_rules.gmk | 48 +- examples/chapter04_04/target/build/build.bat | 14 +- .../target/micros/avr/make/avr.ld | 29 +- .../target/micros/avr/make/avr_files.gmk | 2 +- .../target/micros/avr/make/avr_flags.gmk | 40 +- .../target/micros/avr/startup/crt0.cpp | 4 +- .../micros/avr/startup/crt0_init_ram.cpp | 35 +- .../target/micros/avr/startup/crt1.cpp | 31 +- .../target/micros/avr/startup/int_vect.cpp | 73 +- 99 files changed, 7080 insertions(+), 2742 deletions(-) delete mode 100644 examples/chapter04_04/libwinpthread-1.dll create mode 100644 examples/chapter04_04/src/mcal/mcal_helper.h create mode 100644 examples/chapter04_04/src/mcal_led/mcal_led_boolean_state_base.h create mode 100644 examples/chapter04_04/src/mcal_led/mcal_led_port_inverted.h create mode 100644 examples/chapter04_04/src/mcal_led/mcal_led_rgb_base.h create mode 100644 examples/chapter04_04/src/mcal_pwm/mcal_pwm_port.h create mode 100644 examples/chapter04_04/src/util/STD_LIBC/memory.c delete mode 100644 examples/chapter04_04/src/util/STD_LIBC/memory.cpp create mode 100644 examples/chapter04_04/src/util/STL/cassert create mode 100644 examples/chapter04_04/src/util/STL/cerrno create mode 100644 examples/chapter04_04/src/util/STL/charconv create mode 100644 examples/chapter04_04/src/util/STL/cinttypes create mode 100644 examples/chapter04_04/src/util/STL/ciso646 create mode 100644 examples/chapter04_04/src/util/STL/impl/alloc_traits.h delete mode 100644 examples/chapter04_04/src/util/STL/impl/avr/avr_float_limits.cpp create mode 100644 examples/chapter04_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp delete mode 100644 examples/chapter04_04/src/util/STL/impl/cmath_impl_gamma.cpp delete mode 100644 examples/chapter04_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp create mode 100644 examples/chapter04_04/src/util/STL/impl/ptr_traits.h create mode 100644 examples/chapter04_04/src/util/STL/stdexcept create mode 100644 examples/chapter04_04/src/util/memory/util_n_slot_array_allocator.h create mode 100644 examples/chapter04_04/src/util/utility/util_baselexical_cast.h create mode 100644 examples/chapter04_04/src/util/utility/util_constexpr_algorithm_unsafe.h create mode 100644 examples/chapter04_04/src/util/utility/util_constexpr_cmath_unsafe.h create mode 100644 examples/chapter04_04/src/util/utility/util_display.h create mode 100644 examples/chapter04_04/src/util/utility/util_narrow_cast.h diff --git a/examples/chapter04_04/chapter04_04.vcxproj b/examples/chapter04_04/chapter04_04.vcxproj index aca37832a..6e7523a33 100644 --- a/examples/chapter04_04/chapter04_04.vcxproj +++ b/examples/chapter04_04/chapter04_04.vcxproj @@ -232,19 +232,11 @@ - + true true - - true - true - - - true - true - - + true true @@ -335,6 +327,7 @@ + @@ -351,12 +344,14 @@ + + @@ -364,10 +359,18 @@ true true + + true + true + true true + + true + true + true true @@ -386,18 +389,22 @@ + + + + + - @@ -409,7 +416,10 @@ true true - + + true + true + true true @@ -422,14 +432,38 @@ true true + + true + true + + + true + true + + + true + true + true true + + true + true + true true + + true + true + + + true + true + true true @@ -458,6 +492,10 @@ true true + + true + true + true true @@ -486,10 +524,22 @@ true true + + true + true + true true + + true + true + + + true + true + true true diff --git a/examples/chapter04_04/chapter04_04.vcxproj.filters b/examples/chapter04_04/chapter04_04.vcxproj.filters index dc4e995a0..fd076a794 100644 --- a/examples/chapter04_04/chapter04_04.vcxproj.filters +++ b/examples/chapter04_04/chapter04_04.vcxproj.filters @@ -87,12 +87,6 @@ src\mcal - - src\util\STL\impl\avr - - - src\util\STD_LIBC - src\app\led @@ -165,11 +159,11 @@ src\mcal\host - - src\util\STL\impl + + src\util\STD_LIBC - - src\util\STL\impl + + src\util\STL\impl\avr @@ -293,9 +287,6 @@ src\util\utility - - src\util\utility - src\util\utility @@ -425,6 +416,36 @@ src\util\STL\impl + + src\util\utility + + + src\util\utility + + + src\util\utility + + + src\util\utility + + + src\util\utility + + + src\util\memory + + + src\util\STL\impl + + + src\util\STL\impl + + + src\mcal + + + src\mcal_pwm + @@ -511,5 +532,35 @@ src\util\STL + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + + + src\util\STL + \ No newline at end of file diff --git a/examples/chapter04_04/libwinpthread-1.dll b/examples/chapter04_04/libwinpthread-1.dll deleted file mode 100644 index 39abad74fd87e8e00158f39aa8df05dde77a7349..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59643 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::reg_set(mcal::reg::ocr1a, - base_class_type::my_duty_cycle); + base_class_type::get_duty()); } }; diff --git a/examples/chapter04_04/src/mcal/mcal.cpp b/examples/chapter04_04/src/mcal/mcal.cpp index 3fa1fcdfc..8ea5c9de1 100644 --- a/examples/chapter04_04/src/mcal/mcal.cpp +++ b/examples/chapter04_04/src/mcal/mcal.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,8 +23,7 @@ void mcal::init() mcal::ser::init(nullptr); mcal::spi::init(nullptr); mcal::pwm::init(nullptr); + mcal::eep::init(nullptr); mcal::cpu::post_init(); - - mcal::eep::init(nullptr); } diff --git a/examples/chapter04_04/src/mcal/mcal.h b/examples/chapter04_04/src/mcal/mcal.h index 8ae9d30a8..588e01b00 100644 --- a/examples/chapter04_04/src/mcal/mcal.h +++ b/examples/chapter04_04/src/mcal/mcal.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/mcal/mcal_gcc_cxx_completion.cpp b/examples/chapter04_04/src/mcal/mcal_gcc_cxx_completion.cpp index 1aaa4b8e8..4b04d32d6 100644 --- a/examples/chapter04_04/src/mcal/mcal_gcc_cxx_completion.cpp +++ b/examples/chapter04_04/src/mcal/mcal_gcc_cxx_completion.cpp @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,13 +10,18 @@ #include #include +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-declarations" +#endif + // Implement std::chrono::high_resolution_clock::now() // for the standard library's high-resolution clock. namespace std { namespace chrono { - high_resolution_clock::time_point high_resolution_clock::now() UTIL_NOEXCEPT + high_resolution_clock::time_point high_resolution_clock::now() noexcept { // The source of the high-resolution clock is microseconds. using microsecond_time_point_type = @@ -37,12 +42,7 @@ namespace std } } -void operator delete(void*) UTIL_NOEXCEPT; -void operator delete(void*, void*) UTIL_NOEXCEPT; - -void* operator new(std::size_t size) UTIL_NOEXCEPT; - -void* operator new(std::size_t size) UTIL_NOEXCEPT +void* operator new(std::size_t size) noexcept { // This is a naive and not completely functional // implementation of operator new(). In particular, there is @@ -70,10 +70,13 @@ void* operator new(std::size_t size) UTIL_NOEXCEPT return static_cast(const_cast(p)); } -void operator delete(void*) UTIL_NOEXCEPT { } -void operator delete(void*, void*) UTIL_NOEXCEPT { } +void operator delete(void*) noexcept { } +#if (defined(__GNUC__) && (__GNUC__ >= 12)) +#else +void operator delete(void*, void*) noexcept { } +#endif #if(__cplusplus >= 201400L) -void operator delete(void*, std::size_t) UTIL_NOEXCEPT { } +void operator delete(void*, std::size_t) noexcept { } #endif extern "C" @@ -84,15 +87,13 @@ extern "C" // Also provide stubbed copies of certain empirically found library functions // and objects. - typedef struct struct_unwind_exception_type { unsigned dummy; } _Unwind_Exception; - - void abort () UTIL_NOEXCEPT __attribute__((noreturn)); - int atexit (void (*)()) UTIL_NOEXCEPT; - int at_quick_exit (void (*)()) UTIL_NOEXCEPT; - void _Exit (int) UTIL_NOEXCEPT __attribute__((noreturn)); - void exit (int) __attribute__((noreturn)); - void quick_exit (int) __attribute__((noreturn)); - int _exit (int); + void abort (void) __attribute__((noreturn)); + int atexit (void (*)(void)); + int at_quick_exit (void (*)(void)); + void _Exit (int) __attribute__((noreturn)); + void exit (int) __attribute__((noreturn)); + void quick_exit (int) __attribute__((noreturn)); + void _exit (int) __attribute__((noreturn)); int _isatty (int); int _lseek (int, int, int); int _open (const char*, int, int); @@ -101,21 +102,20 @@ extern "C" int _write (int, char*, int); int _fstat (int, void*); const void* _sbrk (int); - int _getpid (); + int _getpid (void); int _kill (int, int); - void __cxa_pure_virtual (); + void __cxa_pure_virtual (void); char* __cxa_demangle (const char*, char*, size_t*, int*); - void __cxa_call_terminate(_Unwind_Exception*); // Implementations of patched functions. - void abort () UTIL_NOEXCEPT { for(;;) { mcal::cpu::nop(); } } - int atexit (void (*)()) UTIL_NOEXCEPT { return 0; } - int at_quick_exit (void (*)()) UTIL_NOEXCEPT { return 0; } - void _Exit (int) UTIL_NOEXCEPT { for(;;) { mcal::cpu::nop(); } } + void abort (void) { for(;;) { mcal::cpu::nop(); } } + int atexit (void (*)()) { return 0; } + int at_quick_exit (void (*)()) { return 0; } + void _Exit (int) { for(;;) { mcal::cpu::nop(); } } void exit (int) { for(;;) { mcal::cpu::nop(); } } void quick_exit (int) { _Exit(0); } - int _exit (int) { return -1; } + void _exit (int) { for(;;) { mcal::cpu::nop(); } } int _isatty (int) { return 1; } int _lseek (int, int, int) { return 0; } int _open (const char*, int, int) { return -1; } @@ -124,26 +124,34 @@ extern "C" int _write (int, char*, int) { return 0; } int _fstat (int, void*) { return 0; } const void* _sbrk (int) { return nullptr; } - int _getpid () { return 1; } + int _getpid (void) { return 1; } int _kill (int, int) { return -1; } - void __cxa_pure_virtual () { } + void __cxa_pure_virtual (void) { } char* __cxa_demangle (const char*, char*, size_t*, int*) { return nullptr; } - void __cxa_call_terminate(_Unwind_Exception*) { } + + #if defined(environ) + #undef environ + #endif // Provide some patched data values. const char* const __env[1U] = { nullptr }; const char** const environ = { nullptr }; - int __errno = 0; - std::uint8_t __fdlib_version = UINT8_C(0); + #if (defined(__GNUC__) && defined(__v850__)) + #else + extern int* __errno(void); + int* __errno(void) { return nullptr; } + #endif + + std::uint8_t __fdlib_version; } -// Provide some stubs for specific GCC error handling mechanisms. namespace std { - void __throw_length_error(char const*); - void __throw_logic_error (char const*); + [[noreturn]] + void __throw_out_of_range_fmt(char const*, ...) { for(;;) { ; } } } -void std::__throw_length_error(char const*) { } -void std::__throw_logic_error (char const*) { } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif diff --git a/examples/chapter04_04/src/mcal/mcal_helper.h b/examples/chapter04_04/src/mcal/mcal_helper.h new file mode 100644 index 000000000..135197861 --- /dev/null +++ b/examples/chapter04_04/src/mcal/mcal_helper.h @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2021. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_HELPER_2020_05_21_H_ + #define MCAL_HELPER_2020_05_21_H_ + + #include + #include + + #include + #include + + namespace mcal { namespace helper { + + template + typename std::enable_if<(1U < nop_count) && (nop_count <= 12U), void>::type nop_maker() + { + nop_maker(); + + mcal::cpu::nop(); + } + + template + typename std::enable_if<(nop_count == 1U), void>::type nop_maker() { mcal::cpu::nop(); } + + template + typename std::enable_if<(nop_count == 0U), void>::type nop_maker() { } + + template + typename std::enable_if<(12U < nop_count), void>::type nop_maker() + { + for(std::uint_fast16_t i = 0U; i < nop_count; ++i) + { + mcal::cpu::nop(); + } + } + + template + void disable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if<(has_disable_enable_interrupts == true)>::type* = nullptr) noexcept + { + mcal::irq::disable_all(); + } + + template + void enable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if<(has_disable_enable_interrupts == true)>::type* = nullptr) noexcept + { + mcal::irq::enable_all(); + } + + template + void disable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if<(has_disable_enable_interrupts == false)>::type* = nullptr) noexcept { } + + template + void enable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if<(has_disable_enable_interrupts == false)>::type* = nullptr) noexcept { } + + } } // namespace mcal::helper + +#endif // MCAL_HELPER_2020_05_21_H_ diff --git a/examples/chapter04_04/src/mcal/mcal_reg_access_dynamic.h b/examples/chapter04_04/src/mcal/mcal_reg_access_dynamic.h index 85cd37341..e23db33d0 100644 --- a/examples/chapter04_04/src/mcal/mcal_reg_access_dynamic.h +++ b/examples/chapter04_04/src/mcal/mcal_reg_access_dynamic.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2013 - 2019. +// Copyright Christopher Kormanyos 2013 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,30 +8,53 @@ #ifndef MCAL_REG_ACCESS_DYNAMIC_2013_12_13_H_ #define MCAL_REG_ACCESS_DYNAMIC_2013_12_13_H_ + #if defined(__GNUC__) && (__GNUC__ >= 12) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + #endif + namespace mcal { namespace reg { - template + template struct reg_access_dynamic final { - static register_value_type - reg_get(const register_address_type address) { return *reinterpret_cast(address); } - - static void reg_set(const register_address_type address, const register_value_type value) { *reinterpret_cast(address) = value; } - static void reg_and(const register_address_type address, const register_value_type value) { *reinterpret_cast(address) &= value; } - static void reg_or (const register_address_type address, const register_value_type value) { *reinterpret_cast(address) |= value; } - static void reg_not(const register_address_type address, const register_value_type value) { *reinterpret_cast(address) &= register_value_type(~value); } - static void reg_msk(const register_address_type address, const register_value_type value, - const register_value_type mask_value) { *reinterpret_cast(address) = register_value_type(register_value_type(reg_get(address) & register_value_type(~mask_value)) | register_value_type(value & mask_value)); } - - static void bit_set(const register_address_type address, const register_value_type value) { *reinterpret_cast(address) |= static_cast(1UL << value); } - static void bit_clr(const register_address_type address, const register_value_type value) { *reinterpret_cast(address) &= static_cast(~static_cast(1UL << value)); } - static void bit_not(const register_address_type address, const register_value_type value) { *reinterpret_cast(address) ^= static_cast(1UL << value); } - static bool bit_get(const register_address_type address, const register_value_type value) { return (static_cast(reg_get(address) & static_cast(1UL << value)) != static_cast(0U)); } + using register_address_type = RegisterAddressType; + using register_value_type = RegisterValueType; + + static auto reg_get(const register_address_type address) -> register_value_type { return *reinterpret_cast(address); } + static auto reg_set(const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = value; } + static auto reg_and(const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & value); } + static auto reg_or (const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa | value); } + static auto reg_not(const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & static_cast(~value)); } + + static auto reg_msk(const register_address_type address, + const register_value_type value, + const register_value_type mask_value) -> void + { + volatile register_value_type* pa = reinterpret_cast(address); + + *pa = + static_cast + ( + static_cast(reg_get(address) & static_cast(~mask_value)) + | value + ); + } + + static auto bit_set(const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa | static_cast(1UL << value)); } + static auto bit_clr(const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & static_cast(~static_cast(1UL << value))); } + static auto bit_not(const register_address_type address, const register_value_type value) -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa ^ static_cast(1UL << value)); } + static auto bit_get(const register_address_type address, const register_value_type value) -> bool { return (static_cast(reg_get(address) & static_cast(1UL << value)) != static_cast(0U)); } }; } } + #if defined(__GNUC__) && (__GNUC__ >= 12) + // -Warray-bounds + #pragma GCC diagnostic pop + #endif + #endif // MCAL_REG_ACCESS_DYNAMIC_2013_12_13_H_ diff --git a/examples/chapter04_04/src/mcal/mcal_reg_access_static.h b/examples/chapter04_04/src/mcal/mcal_reg_access_static.h index 457ffa60a..13385af2b 100644 --- a/examples/chapter04_04/src/mcal/mcal_reg_access_static.h +++ b/examples/chapter04_04/src/mcal/mcal_reg_access_static.h @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,32 +8,53 @@ #ifndef MCAL_REG_ACCESS_STATIC_2010_12_01_H_ #define MCAL_REG_ACCESS_STATIC_2010_12_01_H_ + #if defined(__GNUC__) && (__GNUC__ >= 12) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + #endif + namespace mcal { namespace reg { - template(0)> + template(0U)> struct reg_access_static final { - static void reg_set() { *reinterpret_cast(address) = value; } - static void reg_and() { *reinterpret_cast(address) &= value; } - static void reg_or () { *reinterpret_cast(address) |= value; } - static void reg_not() { *reinterpret_cast(address) &= register_value_type(~value); } - static register_value_type - reg_get() { return *reinterpret_cast(address); } + using register_value_type = RegisterValueType; + using register_address_type = RegisterAddressType; + + static auto reg_get() -> register_value_type { volatile register_value_type* pa = reinterpret_cast(address); return *pa; } + static auto reg_set() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = value; } + static auto reg_and() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & value); } + static auto reg_or () -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa | value); } + static auto reg_not() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & static_cast(~value)); } template - static void reg_msk() { *reinterpret_cast(address) = register_value_type(register_value_type(reg_get() & register_value_type(~mask_value)) | register_value_type(value & mask_value)); } + static auto reg_msk() -> void + { + volatile register_value_type* pa = reinterpret_cast(address); - static void bit_set() { *reinterpret_cast(address) |= static_cast(1ULL << value); } - static void bit_clr() { *reinterpret_cast(address) &= static_cast(~static_cast(1ULL << value)); } - static void bit_not() { *reinterpret_cast(address) ^= static_cast(1ULL << value); } - static bool bit_get() { return (static_cast(reg_get() & static_cast(1ULL << value)) != static_cast(0U)); } + *pa = + static_cast + ( + static_cast(reg_get() & static_cast(~mask_value)) + | value + ); + } + + static auto bit_set() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa | static_cast(1ULL << value)); } + static auto bit_clr() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & static_cast(~static_cast(1ULL << value))); } + static auto bit_not() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa ^ static_cast(1ULL << value)); } + static auto bit_get() -> bool { return (static_cast(reg_get() & static_cast(1ULL << value)) != static_cast(0U)); } }; } } + #if defined(__GNUC__) && (__GNUC__ >= 12) + #pragma GCC diagnostic pop + #endif + #endif // MCAL_REG_ACCESS_STATIC_2010_12_01_H_ diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_base.h b/examples/chapter04_04/src/mcal_led/mcal_led_base.h index 8b2f00511..e9d099b72 100644 --- a/examples/chapter04_04/src/mcal_led/mcal_led_base.h +++ b/examples/chapter04_04/src/mcal_led/mcal_led_base.h @@ -1,5 +1,12 @@ -#ifndef MCAL_LED_BASE_2020_04_32_H_ - #define MCAL_LED_BASE_2020_04_32_H_ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_LED_BASE_2020_04_32_H + #define MCAL_LED_BASE_2020_04_32_H #include @@ -8,15 +15,15 @@ class led_base : private util::noncopyable { public: - virtual void toggle() = 0; - virtual bool state_is_on() const = 0; + virtual auto toggle() -> void = 0; - virtual ~led_base() = default; + virtual auto state_is_on() const -> bool = 0; protected: - led_base() = default; + constexpr led_base() = default; }; - } } // namespace mcal::led + } // namespace led + } // namespace mcal -#endif // MCAL_LED_BASE_2020_04_32_H_ +#endif // MCAL_LED_BASE_2020_04_32_H diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_boolean_state_base.h b/examples/chapter04_04/src/mcal_led/mcal_led_boolean_state_base.h new file mode 100644 index 000000000..e74ed23b2 --- /dev/null +++ b/examples/chapter04_04/src/mcal_led/mcal_led_boolean_state_base.h @@ -0,0 +1,34 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_LED_BOOLEAN_STATE_BASE_2020_08_07_H + #define MCAL_LED_BOOLEAN_STATE_BASE_2020_08_07_H + + #include + + namespace mcal { namespace led { + + class led_boolean_state_base : public mcal::led::led_base + { + protected: + constexpr led_boolean_state_base() = default; + + auto toggle() -> void override + { + // Toggle the LED state. + is_on = (!is_on); + } + + auto state_is_on() const -> bool override { return is_on; } + + private: + bool is_on { }; + }; + + } } // namespace mcal::led + +#endif // MCAL_LED_BOOLEAN_STATE_BASE_2020_08_07_H diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_console.h b/examples/chapter04_04/src/mcal_led/mcal_led_console.h index 134d89b05..92516cd2e 100644 --- a/examples/chapter04_04/src/mcal_led/mcal_led_console.h +++ b/examples/chapter04_04/src/mcal_led/mcal_led_console.h @@ -1,42 +1,44 @@ -#ifndef MCAL_LED_CONSOLE_2020_04_23_H_ - #define MCAL_LED_CONSOLE_2020_04_23_H_ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_LED_CONSOLE_2020_04_23_H + #define MCAL_LED_CONSOLE_2020_04_23_H #include #include - #include + #include namespace mcal { namespace led { - class led_console final : public mcal::led::led_base + class led_console final : public mcal::led::led_boolean_state_base { public: - led_console(const std::uint_fast8_t i = 0) - : index(i), - is_on(false) { } - - virtual ~led_console() = default; + explicit constexpr led_console(const std::uint_fast8_t i) + : my_index(i) { } - virtual void toggle() + auto toggle() -> void override { - // Toggle the LED state. - is_on = (!is_on); + using base_class_type = mcal::led::led_boolean_state_base; // Print the LED state. std::cout << "LED" - << unsigned(index) + << static_cast(my_index) << " is " - << (is_on ? "on" : "off") + << (base_class_type::state_is_on() ? "on" : "off") << std::endl; + + base_class_type::toggle(); } private: - const std::uint_fast8_t index; - bool is_on; - - virtual bool state_is_on() const { return is_on; } + const std::uint_fast8_t my_index; }; } } // namespace mcal::led -#endif // MCAL_LED_CONSOLE_2020_04_23_H_ +#endif // MCAL_LED_CONSOLE_2020_04_23_H diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_port.h b/examples/chapter04_04/src/mcal_led/mcal_led_port.h index 61508f995..f0d383ef7 100644 --- a/examples/chapter04_04/src/mcal_led/mcal_led_port.h +++ b/examples/chapter04_04/src/mcal_led/mcal_led_port.h @@ -1,44 +1,39 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2020. +// Copyright Christopher Kormanyos 2013 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef MCAL_LED_PORT_2020_04_23_H_ - #define MCAL_LED_PORT_2020_04_23_H_ +#ifndef MCAL_LED_PORT_2020_04_23_H + #define MCAL_LED_PORT_2020_04_23_H - #include + #include #include namespace mcal { namespace led { template - class led_port : public mcal::led::led_base + class led_port : public mcal::led::led_boolean_state_base { public: - led_port() : is_on(false) + led_port() { port_type::set_pin_low(); port_type::set_direction_output(); } - virtual ~led_port() = default; - - virtual void toggle() + auto toggle() -> void override { - // Toggle the LED state. - is_on = (!is_on); + using base_class_type = led_boolean_state_base; port_type::toggle_pin(); - } - virtual bool state_is_on() const { return is_on; } - - private: - bool is_on; + base_class_type::toggle(); + } }; - } } // namespace mcal::led + } // namespace led + } // namespace mcal -#endif // MCAL_LED_PORT_2020_04_23_H_ +#endif // MCAL_LED_PORT_2020_04_23_H diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_port_inverted.h b/examples/chapter04_04/src/mcal_led/mcal_led_port_inverted.h new file mode 100644 index 000000000..847661fad --- /dev/null +++ b/examples/chapter04_04/src/mcal_led/mcal_led_port_inverted.h @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_LED_PORT_INVERTED_2020_08_02_H + #define MCAL_LED_PORT_INVERTED_2020_08_02_H + + #include + #include + + namespace mcal { namespace led { + + template + class led_port_inverted : public mcal::led::led_boolean_state_base + { + public: + led_port_inverted() + { + port_type::set_pin_high(); + port_type::set_direction_output(); + } + + auto toggle() -> void override + { + using base_class_type = led_boolean_state_base; + + port_type::toggle_pin(); + + base_class_type::toggle(); + } + }; + + } // namespace led + } // namespace mcal + +#endif // MCAL_LED_PORT_INVERTED_2020_08_02_H diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_pwm.h b/examples/chapter04_04/src/mcal_led/mcal_led_pwm.h index 2ab392f91..d65c84527 100644 --- a/examples/chapter04_04/src/mcal_led/mcal_led_pwm.h +++ b/examples/chapter04_04/src/mcal_led/mcal_led_pwm.h @@ -1,5 +1,12 @@ -#ifndef MCAL_LED_PWM_2020_04_23_H_ - #define MCAL_LED_PWM_2020_04_23_H_ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_LED_PWM_2020_04_23_H + #define MCAL_LED_PWM_2020_04_23_H #include #include @@ -9,27 +16,30 @@ class led_pwm : public mcal::led::led_base { public: - led_pwm(mcal::pwm::pwm_base& pwm) : my_pwm(pwm) + explicit led_pwm(mcal::pwm::pwm_base& pwm) : my_pwm(pwm) { - my_pwm.set_duty(0U); + my_pwm.set_duty(static_cast(UINT8_C(0))); } - virtual ~led_pwm() = default; + auto state_is_on() const -> bool override { return (my_pwm.get_duty() > static_cast(UINT8_C(0))); } - virtual void toggle() + auto toggle() -> void override { // Toggle the duty cycle. - const std::uint16_t new_duty = ((my_pwm.get_duty() > 0U) ? 0U : 1000U); + const auto new_duty = + static_cast + ( + state_is_on() ? static_cast(UINT8_C(0)) + : static_cast(UINT16_C(1000)) + ); my_pwm.set_duty(new_duty); } - virtual bool state_is_on() const { return (my_pwm.get_duty() > 0U); } - private: mcal::pwm::pwm_base& my_pwm; }; } } // namespace mcal::led -#endif // MCAL_LED_PWM_2020_04_23_H_ +#endif // MCAL_LED_PWM_2020_04_23_H diff --git a/examples/chapter04_04/src/mcal_led/mcal_led_rgb_base.h b/examples/chapter04_04/src/mcal_led/mcal_led_rgb_base.h new file mode 100644 index 000000000..6277b28b8 --- /dev/null +++ b/examples/chapter04_04/src/mcal_led/mcal_led_rgb_base.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2017 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_LED_RGB_BASE_2023_07_12_H + #define MCAL_LED_RGB_BASE_2023_07_12_H + + #include + + #include + + namespace mcal { namespace led { + + class led_rgb_base : public mcal::led::led_boolean_state_base + { + public: + auto toggle() -> void override + { + using base_class_type = mcal::led::led_boolean_state_base; + + // Toggle the LED state. + (base_class_type::state_is_on() ? my_off() : my_on()); + + base_class_type::toggle(); + } + + auto set_color(const std::uint_fast8_t hue_r, + const std::uint_fast8_t hue_g, + const std::uint_fast8_t hue_b) -> void + { + my_hue_r = hue_r; + my_hue_g = hue_g; + my_hue_b = hue_b; + + this->apply_color(); + } + + auto set_color(const std::uint32_t color) -> void + { + set_color + ( + static_cast(color >> static_cast(UINT8_C( 0))), + static_cast(color >> static_cast(UINT8_C( 8))), + static_cast(color >> static_cast(UINT8_C(16))) + ); + } + + constexpr auto get_color() const noexcept -> std::uint32_t + { + return + static_cast + ( + static_cast(static_cast(my_hue_r) << static_cast(UINT8_C( 0))) + | static_cast(static_cast(my_hue_g) << static_cast(UINT8_C( 8))) + | static_cast(static_cast(my_hue_b) << static_cast(UINT8_C(16))) + ); + } + + constexpr auto get_hue_r() const noexcept -> std::uint_fast8_t { return my_hue_r; } + constexpr auto get_hue_g() const noexcept -> std::uint_fast8_t { return my_hue_g; } + constexpr auto get_hue_b() const noexcept -> std::uint_fast8_t { return my_hue_b; } + + protected: + constexpr led_rgb_base() = default; + + private: + std::uint_fast8_t my_hue_r { }; + std::uint_fast8_t my_hue_g { }; + std::uint_fast8_t my_hue_b { }; + + virtual void apply_color() = 0; + + auto my_on () -> void + { + set_color + ( + static_cast(UINT8_C(255)), + static_cast(UINT8_C(255)), + static_cast(UINT8_C(255)) + ); + } + + auto my_off() -> void + { + set_color + ( + static_cast(UINT8_C(0)), + static_cast(UINT8_C(0)), + static_cast(UINT8_C(0)) + ); + } + }; + + } } // namespace mcal::led + +#endif // MCAL_LED_RGB_BASE_2023_07_12_H diff --git a/examples/chapter04_04/src/mcal_memory/mcal_memory_progmem_iterator.h b/examples/chapter04_04/src/mcal_memory/mcal_memory_progmem_iterator.h index 6557477aa..bb5de5a95 100644 --- a/examples/chapter04_04/src/mcal_memory/mcal_memory_progmem_iterator.h +++ b/examples/chapter04_04/src/mcal_memory/mcal_memory_progmem_iterator.h @@ -17,12 +17,6 @@ namespace mcal { namespace memory { namespace progmem { - struct input_iterator_tag { }; - struct output_iterator_tag { }; - struct forward_iterator_tag : public input_iterator_tag { }; - struct bidirectional_iterator_tag : public forward_iterator_tag { }; - struct random_access_iterator_tag : public bidirectional_iterator_tag { }; - template struct iterator_traits { @@ -67,14 +61,14 @@ typename AddressType, typename AddressDifferenceType> class progmem_iterator - : public mcal::memory::progmem::iterator { private: using base_class_type = - mcal::memory::progmem::iterator; @@ -155,7 +149,7 @@ operator-(const progmem_iterator& x, const progmem_iterator& y) noexcept { - return (x.current.ptr - y.current.ptr); + return (x.current - y.current); } friend inline progmem_iterator @@ -167,11 +161,11 @@ }; template - typename mcal::memory::progmem::iterator_traits::difference_type + typename iterator_traits::difference_type distance(input_iterator first, input_iterator last) noexcept { using local_difference_type = - typename mcal::memory::progmem::iterator_traits::difference_type; + typename iterator_traits::difference_type; return local_difference_type(last - first); } diff --git a/examples/chapter04_04/src/mcal_memory/mcal_memory_sram_ptr.h b/examples/chapter04_04/src/mcal_memory/mcal_memory_sram_ptr.h index 33baf27c7..0043c89d4 100644 --- a/examples/chapter04_04/src/mcal_memory/mcal_memory_sram_ptr.h +++ b/examples/chapter04_04/src/mcal_memory/mcal_memory_sram_ptr.h @@ -25,7 +25,9 @@ using address_type = AddressType; public: - using reference = sram_ref; + using reference = sram_ref; using value_type = typename reference::value_type; using size_type = typename reference::size_type; using difference_type = typename reference::difference_type; diff --git a/examples/chapter04_04/src/mcal_memory/mcal_memroy_sram_iterator.h b/examples/chapter04_04/src/mcal_memory/mcal_memroy_sram_iterator.h index 787618263..e1aa24ec1 100644 --- a/examples/chapter04_04/src/mcal_memory/mcal_memroy_sram_iterator.h +++ b/examples/chapter04_04/src/mcal_memory/mcal_memroy_sram_iterator.h @@ -18,12 +18,6 @@ namespace mcal { namespace memory { namespace sram { - struct input_iterator_tag { }; - struct output_iterator_tag { }; - struct forward_iterator_tag : public input_iterator_tag { }; - struct bidirectional_iterator_tag : public forward_iterator_tag { }; - struct random_access_iterator_tag : public bidirectional_iterator_tag { }; - template struct iterator_traits { @@ -68,14 +62,14 @@ typename AddressType, typename AddressDifferenceType> class sram_iterator - : public mcal::memory::sram::iterator { private: using base_class_type = - mcal::memory::sram::iterator; @@ -166,7 +160,7 @@ operator-(const sram_iterator& x, const sram_iterator& y) noexcept { - return (x.current.ptr - y.current.ptr); + return (x.current - y.current); } friend inline sram_iterator @@ -178,11 +172,11 @@ }; template - typename mcal::memory::sram::iterator_traits::difference_type + typename iterator_traits::difference_type distance(input_iterator first, input_iterator last) noexcept { using local_difference_type = - typename mcal::memory::sram::iterator_traits::difference_type; + typename iterator_traits::difference_type; return local_difference_type(last - first); } diff --git a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_base.h b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_base.h index 0252db06b..5bae70e7f 100644 --- a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_base.h +++ b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_base.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2020. +// Copyright Christopher Kormanyos 2020 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef MCAL_PWM_BASE_2020_04_12_H_ - #define MCAL_PWM_BASE_2020_04_12_H_ +#ifndef MCAL_PWM_BASE_2020_04_12_H + #define MCAL_PWM_BASE_2020_04_12_H #include @@ -17,21 +17,25 @@ class pwm_base : private util::noncopyable { public: - virtual ~pwm_base() = default; + using duty_type = std::uint16_t; - virtual bool init() noexcept = 0; + virtual ~pwm_base() noexcept = default; - virtual void set_duty(const std::uint16_t duty_cycle) = 0; + virtual auto init() noexcept -> bool = 0; - std::uint16_t get_duty() const noexcept { return my_duty_cycle; } + virtual auto set_duty(const duty_type duty_cycle) noexcept -> void { my_duty_cycle = duty_cycle; } - protected: - pwm_base() : my_duty_cycle(0U) { } + auto get_duty() const noexcept -> duty_type { return my_duty_cycle; } protected: - std::uint16_t my_duty_cycle; + explicit pwm_base(const duty_type initial_duty = static_cast(UINT8_C(0))) noexcept + : my_duty_cycle(initial_duty) { } + + private: + duty_type my_duty_cycle { }; }; - } } + } // namespace pwm + } // namespace mcal -#endif // MCAL_PWM_BASE_2020_04_12_H_ +#endif // MCAL_PWM_BASE_2020_04_12_H diff --git a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_console.h b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_console.h index 61dfb95b0..3d49352d4 100644 --- a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_console.h +++ b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_console.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2020. +// Copyright Christopher Kormanyos 2020 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef MCAL_PWM_CONSOLE_2020_04_12_H_ - #define MCAL_PWM_CONSOLE_2020_04_12_H_ +#ifndef MCAL_PWM_CONSOLE_2020_04_12_H + #define MCAL_PWM_CONSOLE_2020_04_12_H #include #include @@ -24,13 +24,17 @@ public: pwm_console() = default; - virtual bool init() noexcept { return true; } + auto init() noexcept -> bool override { return true; } - virtual void set_duty(const std::uint16_t duty_cycle) noexcept + auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override { - base_class_type::my_duty_cycle = duty_cycle; + base_class_type::set_duty(duty_cycle); - const float duty_cycle_as_percent = float(duty_cycle) / 10.0F; + const auto duty_cycle_as_percent = + static_cast + ( + static_cast(base_class_type::get_duty()) / 10.0F + ); std::stringstream strm; @@ -43,7 +47,7 @@ std::cout << strm.str() + (std::string(2U, ' ') + "\r"); } - virtual ~pwm_console() = default; + ~pwm_console() override = default; }; } } diff --git a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_dummy.h b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_dummy.h index 0d022d854..e2d353eea 100644 --- a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_dummy.h +++ b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_dummy.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2020. +// Copyright Christopher Kormanyos 2020 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef MCAL_PWM_DUMMY_2020_04_29_H_ - #define MCAL_PWM_DUMMY_2020_04_29_H_ +#ifndef MCAL_PWM_DUMMY_2020_04_29_H + #define MCAL_PWM_DUMMY_2020_04_29_H #include @@ -20,16 +20,17 @@ public: pwm_dummy() = default; - virtual bool init() noexcept { return true; } + auto init() noexcept -> bool override { return true; } - virtual void set_duty(const std::uint16_t duty_cycle) noexcept + auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override { - base_class_type::my_duty_cycle = duty_cycle; + base_class_type::set_duty(duty_cycle); } - virtual ~pwm_dummy() = default; + ~pwm_dummy() override = default; }; - } } + } // namespace pwm + } // namespace mcal -#endif // MCAL_PWM_DUMMY_2020_04_29_H_ +#endif // MCAL_PWM_DUMMY_2020_04_29_H diff --git a/examples/chapter04_04/src/mcal_pwm/mcal_pwm_port.h b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_port.h new file mode 100644 index 000000000..5ce686fec --- /dev/null +++ b/examples/chapter04_04/src/mcal_pwm/mcal_pwm_port.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2024. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_PWM_PORT_2023_08_23_H + #define MCAL_PWM_PORT_2023_08_23_H + + #include + + namespace mcal { namespace pwm { + + // A software PWM template for a port-pin having the standard + // port interface for ref_app. The default resolution is 100 ticks. + + template(UINT8_C(100))> + class pwm_port : public pwm_base + { + private: + using base_class_type = pwm_base; + using port_pin_type = PortPinType; + + public: + using base_class_type::duty_type; + + explicit pwm_port(const duty_type initial_duty = static_cast(UINT8_C(0))) + : base_class_type(initial_duty), + my_duty_shadow(initial_duty) + { + port_pin_type::set_pin_low(); + port_pin_type::set_direction_output(); + } + + ~pwm_port() noexcept override = default; + + auto init() noexcept -> bool override + { + return true; + } + + auto set_duty(const duty_type duty_cycle) noexcept -> void override { my_duty_shadow = duty_cycle; } + + static constexpr auto get_resolution() noexcept -> duty_type { return MyResolution; } + + auto service() noexcept -> void + { + // Increment the cycle counter. + ++my_cycle_counter; + + ((my_cycle_counter <= base_class_type::get_duty()) ? port_pin_type::set_pin_high() : port_pin_type::set_pin_low()); + + if(my_cycle_counter == get_resolution()) + { + // Latch the duty cycle from the shadow register. + // This is done at the end of the running cycle. + base_class_type::set_duty(my_duty_shadow); + + // Reset the cycle counter for a new PWM period. + my_cycle_counter = static_cast(UINT8_C(0)); + } + } + + private: + duty_type my_cycle_counter { }; + duty_type my_duty_shadow { }; + }; + + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_PORT_2023_08_23_H diff --git a/examples/chapter04_04/src/mcal_spi/mcal_spi_software_dummy.h b/examples/chapter04_04/src/mcal_spi/mcal_spi_software_dummy.h index 334a62264..3aa5699e7 100644 --- a/examples/chapter04_04/src/mcal_spi/mcal_spi_software_dummy.h +++ b/examples/chapter04_04/src/mcal_spi/mcal_spi_software_dummy.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2020. +// Copyright Christopher Kormanyos 2020 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H_ - #define MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H_ +#ifndef MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H + #define MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H #include @@ -22,9 +22,9 @@ spi_software_dummy() = default; - virtual ~spi_software_dummy() = default; + ~spi_software_dummy() override = default; - virtual bool send(const std::uint8_t byte_to_send) + auto send(const std::uint8_t byte_to_send) noexcept -> bool override { static_cast(byte_to_send); @@ -33,10 +33,10 @@ return true; } - virtual void select() { } - virtual void deselect() { } + auto select() -> void override { } + auto deselect() -> void override { } }; } } // namespace mcal::spi -#endif // MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H_ +#endif // MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H diff --git a/examples/chapter04_04/src/mcal_spi/mcal_spi_software_port_driver.h b/examples/chapter04_04/src/mcal_spi/mcal_spi_software_port_driver.h index 60b7218ee..a73963bf3 100644 --- a/examples/chapter04_04/src/mcal_spi/mcal_spi_software_port_driver.h +++ b/examples/chapter04_04/src/mcal_spi/mcal_spi_software_port_driver.h @@ -99,9 +99,9 @@ port_pin_miso_type::set_direction_input(); } - virtual ~spi_software_port_driver() = default; + ~spi_software_port_driver() override = default; - virtual bool send(const std::uint8_t byte_to_send) + auto send(const std::uint8_t byte_to_send) noexcept -> bool override { base_class_type::recv_buffer = 0U; @@ -131,8 +131,8 @@ return true; } - virtual void select() { port_pin_csn__type::set_pin_low(); } - virtual void deselect() { port_pin_csn__type::set_pin_high(); } + auto select() -> void override { port_pin_csn__type::set_pin_low(); } + auto deselect() -> void override { port_pin_csn__type::set_pin_high(); } }; } } // namespace mcal::spi diff --git a/examples/chapter04_04/src/os/os.cpp b/examples/chapter04_04/src/os/os.cpp index 5578dc732..9afa6747b 100644 --- a/examples/chapter04_04/src/os/os.cpp +++ b/examples/chapter04_04/src/os/os.cpp @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,28 +8,29 @@ #include #include #include + #include #include #include -namespace +namespace local { - typedef std::array task_list_type; + using task_list_type = std::array; - typedef std::uint_fast8_t task_index_type; + using task_index_type = std::uint_fast8_t; // The one (and only one) operating system task list. - task_list_type os_task_list(OS_TASK_LIST); + task_list_type os_task_list(OS_TASK_LIST); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,cert-err58-cpp) // The index of the running task. - task_index_type os_task_index; -} + task_index_type os_task_index; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +} // namespace local -void os::start_os() +OS_NORETURN auto os::start_os() -> void { // Initialize each task once (and only once) before the task scheduling begins. - auto const it_init_func = std::for_each(os_task_list.cbegin(), - os_task_list.cend(), + const auto it_init_func = std::for_each(local::os_task_list.cbegin(), + local::os_task_list.cend(), [](const task_control_block& the_tcb) { the_tcb.initialize(); @@ -51,36 +52,38 @@ void os::start_os() const os::tick_type timepoint_of_ckeck_ready = os::timer_type::get_mark(); - os_task_index = static_cast(0U); + local::os_task_index = static_cast(0U); - const auto it_ready_task = - std::find_if(os_task_list.begin(), - os_task_list.end(), - [&timepoint_of_ckeck_ready](task_control_block& tcb) -> bool + const auto it_ready_task = // NOLINT(llvm-qualified-auto,readability-qualified-auto) + std::find_if(local::os_task_list.begin(), + local::os_task_list.end(), + [&timepoint_of_ckeck_ready](task_control_block& tcb) // NOLINT(modernize-use-trailing-return-type) { - const bool task_is_ready = tcb.execute(timepoint_of_ckeck_ready); + const auto task_is_ready = tcb.execute(timepoint_of_ckeck_ready); - ++os_task_index; + ++local::os_task_index; return task_is_ready; }); // If no ready-task was found, then service the idle task. - if(it_ready_task == os_task_list.end()) + if(it_ready_task == local::os_task_list.end()) { OS_IDLE_TASK_FUNC(); } } } -bool os::set_event(const task_id_type task_id, const event_type& event_to_set) +auto os::set_event(const task_id_type task_id, const event_type& event_to_set) -> bool { - if(task_id < task_id_end) + bool result_set_is_ok { }; + + if(task_id < task_id_type::task_id_end) { // Get the iterator of the control block corresponding to // the task id that has been supplied to this subroutine. - const auto it_task_id = ( os_task_list.begin() - + task_list_type::size_type(task_id)); + const auto it_task_id = ( local::os_task_list.begin() // NOLINT(llvm-qualified-auto,readability-qualified-auto) + + static_cast(task_id)); // Set the event of the corresponding task. mcal::irq::disable_all(); @@ -89,20 +92,18 @@ bool os::set_event(const task_id_type task_id, const event_type& event_to_set) mcal::irq::enable_all(); - return true; - } - else - { - return false; + result_set_is_ok = true; } + + return result_set_is_ok; } -void os::get_event(event_type& event_to_get) +auto os::get_event(event_type& event_to_get) -> void { // Get the iterator of the control block of the running task. - const auto it_running_task = (os_task_list.cbegin() + os_task_index); + const auto it_running_task = (local::os_task_list.cbegin() + local::os_task_index); // NOLINT(llvm-qualified-auto,readability-qualified-auto) - if(it_running_task != os_task_list.cend()) + if(it_running_task != local::os_task_list.cend()) { // Get the event of the running task. mcal::irq::disable_all(); @@ -115,23 +116,23 @@ void os::get_event(event_type& event_to_get) } else { - event_to_get = event_type(); + event_to_get = event_type { }; } } -void os::clear_event(const event_type& event_to_clear) +auto os::clear_event(const event_type& event_to_clear) -> void { // Get the iterator of the control block of the running task. - const auto it_running_task = (os_task_list.begin() + os_task_index); + const auto it_running_task = (local::os_task_list.begin() + local::os_task_index); // NOLINT(llvm-qualified-auto,readability-qualified-auto) - if(it_running_task != os_task_list.end()) + if(it_running_task != local::os_task_list.end()) { - const volatile event_type event_clear_mask(~event_to_clear); + volatile const auto event_clear_mask = static_cast(~event_to_clear); // Clear the event of the running task. mcal::irq::disable_all(); - it_running_task->my_event &= event_clear_mask; + it_running_task->my_event = static_cast(it_running_task->my_event & event_clear_mask); mcal::irq::enable_all(); } diff --git a/examples/chapter04_04/src/os/os.h b/examples/chapter04_04/src/os/os.h index fdd9ef67f..db4113a75 100644 --- a/examples/chapter04_04/src/os/os.h +++ b/examples/chapter04_04/src/os/os.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -13,12 +13,18 @@ #include #include + #if defined(_MSC_VER) + #define OS_NORETURN + #else + #define OS_NORETURN [[noreturn]] + #endif + namespace os { - void start_os (); - bool set_event (const task_id_type task_id, const event_type& event_to_set); - void get_event (event_type& event_to_get); - void clear_event(const event_type& event_to_clear); + OS_NORETURN auto start_os () -> void; + auto set_event (const task_id_type task_id, const event_type& event_to_set) -> bool; + auto get_event (event_type& event_to_get) -> void; + auto clear_event(const event_type& event_to_clear) -> void; } #endif // OS_2011_10_20_H_ diff --git a/examples/chapter04_04/src/os/os_cfg.h b/examples/chapter04_04/src/os/os_cfg.h index 7a2e140a4..7e8b84950 100644 --- a/examples/chapter04_04/src/os/os_cfg.h +++ b/examples/chapter04_04/src/os/os_cfg.h @@ -1,12 +1,12 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef OS_CFG_2011_10_20_H_ - #define OS_CFG_2011_10_20_H_ +#ifndef OS_CFG_2011_10_20_H + #define OS_CFG_2011_10_20_H #include #include @@ -15,34 +15,33 @@ #include // Declare the task initialization and the task function of the idle process. - namespace sys { namespace idle { void task_init(); void task_func(); } } + namespace sys { namespace idle { auto task_init() noexcept -> void; auto task_func() -> void; } } // Define symbols for the task initialization and the task function of the idle process. #define OS_IDLE_TASK_INIT() sys::idle::task_init() #define OS_IDLE_TASK_FUNC() sys::idle::task_func() // Declare all of the task initializations and the task functions. - namespace app { namespace led { void task_init(); void task_func(); } } - namespace app { namespace benchmark { void task_init(); void task_func(); } } + namespace app { namespace led { auto task_init() -> void; auto task_func() -> void; } } + namespace app { namespace benchmark { auto task_init() -> void; auto task_func() -> void; } } namespace os { // Enumerate the task IDs. Note that the order in this list must // be identical with the order of the tasks in the task list below. - typedef enum enum_task_id + enum class task_id_type { task_id_app_led, task_id_app_benchmark, task_id_end - } - task_id_type; + }; // Configure the operating system types. - typedef void(*function_type)(); + using function_type = void(*)(); - typedef util::timer timer_type; - typedef timer_type::tick_type tick_type; - typedef std::uint_fast16_t event_type; + using timer_type = util::timer; + using tick_type = timer_type::tick_type; + using event_type = std::uint_fast16_t; static_assert(std::numeric_limits::digits >= 32, "The operating system timer_type must be at least 32-bits wide."); @@ -61,22 +60,22 @@ // 4201, 4409, 4637, 4831, 5039, 5279, 5483, 5693, 5881, 6133, 6337, // 6571, 6793, 6997, 7237, 7499, 7687, 7919 - #define OS_TASK_COUNT static_cast(os::task_id_end) - - #define OS_TASK_LIST \ - { \ - { \ - os::task_control_block(app::led::task_init, \ - app::led::task_func, \ - os::timer_type::microseconds(UINT32_C( 2000)), \ - os::timer_type::microseconds(UINT32_C( 0))), \ - os::task_control_block(app::benchmark::task_init, \ - app::benchmark::task_func, \ - os::timer_type::microseconds(UINT32_C(50000)), \ - os::timer_type::microseconds(UINT32_C( 379))), \ - } \ + constexpr auto OS_TASK_COUNT = static_cast(os::task_id_type::task_id_end); + + #define OS_TASK_LIST \ + { \ + { \ + os::task_control_block(app::led::task_init, \ + app::led::task_func, \ + os::timer_type::microseconds(UINT32_C( 2000)), \ + os::timer_type::microseconds(UINT32_C( 0))), \ + os::task_control_block(app::benchmark::task_init, \ + app::benchmark::task_func, \ + os::timer_type::microseconds(UINT32_C( 50000)), \ + os::timer_type::microseconds(UINT32_C( 379))), \ + } \ } - static_assert(OS_TASK_COUNT > std::size_t(0U), "the task count must exceed zero"); + static_assert(OS_TASK_COUNT > static_cast(UINT8_C(0)), "the task count must exceed zero"); -#endif // OS_CFG_2011_10_20_H_ +#endif // OS_CFG_2011_10_20_H diff --git a/examples/chapter04_04/src/os/os_task_control_block.cpp b/examples/chapter04_04/src/os/os_task_control_block.cpp index 216068567..c1a030cb6 100644 --- a/examples/chapter04_04/src/os/os_task_control_block.cpp +++ b/examples/chapter04_04/src/os/os_task_control_block.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +// Copyright Christopher Kormanyos 2007 - 2021. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -7,10 +7,10 @@ #include -bool os::task_control_block::execute(const os::tick_type& timepoint_of_ckeck_ready) +auto os::task_control_block::execute(const os::tick_type& timepoint_of_ckeck_ready) -> bool { // Check for a task event. - const bool task_does_have_event = (my_event != event_type(0U)); + const auto task_does_have_event = (my_event != static_cast(UINT8_C(0))); if(task_does_have_event) { @@ -19,7 +19,7 @@ bool os::task_control_block::execute(const os::tick_type& timepoint_of_ckeck_rea } // Check for a task timeout. - const bool task_does_have_timeout = ( (my_cycle != os::tick_type(0U)) + const bool task_does_have_timeout = ( (my_cycle != static_cast(UINT8_C(0))) && my_timer.timeout_of_specific_timepoint(timepoint_of_ckeck_ready)); if(task_does_have_timeout) diff --git a/examples/chapter04_04/src/os/os_task_control_block.h b/examples/chapter04_04/src/os/os_task_control_block.h index 89f5530fa..aef76aa61 100644 --- a/examples/chapter04_04/src/os/os_task_control_block.h +++ b/examples/chapter04_04/src/os/os_task_control_block.h @@ -1,12 +1,12 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef OS_TASK_CONTROL_BLOCK_2013_07_30_H_ - #define OS_TASK_CONTROL_BLOCK_2013_07_30_H_ +#ifndef OS_TASK_CONTROL_BLOCK_2013_07_30_H + #define OS_TASK_CONTROL_BLOCK_2013_07_30_H #include #include @@ -21,39 +21,49 @@ task_control_block(const function_type init, const function_type func, const tick_type cycle, - const tick_type offset) : my_init (init), - my_func (func), - my_cycle(cycle), - my_timer(offset), - my_event() { } + const tick_type offset) noexcept + : my_init (init), + my_func (func), + my_cycle(cycle), + my_timer(offset) { } - task_control_block(const task_control_block& other_tcb) : my_init (other_tcb.my_init), - my_func (other_tcb.my_func), - my_cycle(other_tcb.my_cycle), - my_timer(other_tcb.my_timer), - my_event(other_tcb.my_event) { } + task_control_block(const task_control_block& other_tcb) noexcept + : my_init (other_tcb.my_init), + my_func (other_tcb.my_func), + my_cycle(other_tcb.my_cycle), + my_timer(other_tcb.my_timer), + my_event(other_tcb.my_event) { } - ~task_control_block() { } + task_control_block(task_control_block&& other_tcb) noexcept + : my_init (other_tcb.my_init), + my_func (other_tcb.my_func), + my_cycle(other_tcb.my_cycle), + my_timer(other_tcb.my_timer), + my_event(other_tcb.my_event) { } + + task_control_block() = delete; + + ~task_control_block() = default; + + auto operator=(const task_control_block&) -> task_control_block& = delete; + auto operator=(task_control_block&&) noexcept -> task_control_block& = delete; private: const function_type my_init; const function_type my_func; const tick_type my_cycle; timer_type my_timer; - event_type my_event; - - void initialize() const { my_init(); } + event_type my_event { }; - bool execute(const tick_type& timepoint_of_ckeck_ready); + auto initialize() const -> void { my_init(); } - task_control_block(); - task_control_block& operator=(const task_control_block&); + auto execute(const tick_type& timepoint_of_ckeck_ready) -> bool; - friend void start_os (); - friend bool set_event (const task_id_type, const event_type&); - friend void get_event (event_type&); - friend void clear_event(const event_type&); + friend auto start_os () -> void; + friend auto set_event (const task_id_type, const event_type&) -> bool; + friend auto get_event (event_type&) -> void; + friend auto clear_event(const event_type&) -> void; }; } -#endif // OS_TASK_CONTROL_BLOCK_2013_07_30_H_ +#endif // OS_TASK_CONTROL_BLOCK_2013_07_30_H diff --git a/examples/chapter04_04/src/util/STD_LIBC/memory.c b/examples/chapter04_04/src/util/STD_LIBC/memory.c new file mode 100644 index 000000000..19eeb68b7 --- /dev/null +++ b/examples/chapter04_04/src/util/STD_LIBC/memory.c @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2011 - 2021. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +// Implement some memory functions from the standard C library. +// If this file is included in the project, the linker will take these +// functions instead of its own corresponding functions from the C-library. +// The functions in this file *might* potentially save some code and/or +// runtime in the executable. + +void* memset (void* dest, int val, size_t count) __attribute__((used, noinline)); +void* memcpy (void* dest, const void* src, size_t count) __attribute__((used, noinline)); +void* memmove(void* dst, const void* src, size_t n) __attribute__((used, noinline)); + +void* memset(void* dest, int val, size_t count) +{ + unsigned char* puchar_dest = (uint8_t*) dest; + + for(size_t i = 0U; i < count; ++i) + { + puchar_dest[i] = (uint8_t) val; + } + + return dest; +} + +void* memcpy(void* dest, const void* src, size_t count) +{ + unsigned char* puchar_dest = ( uint8_t*) dest; + const unsigned char* puchar_src = (const uint8_t*) src; + + for(size_t i = 0U; i < count; ++i) + { + puchar_dest[i] = puchar_src[i]; + } + + return (void*) puchar_dest; +} + +void* memmove(void* dest, const void* src, size_t n) +{ + uint8_t* from = (uint8_t*) src; + uint8_t* to = (uint8_t*) dest; + + if(from == to || n == 0) + { + return dest; + } + + if(to > from && (ptrdiff_t) (to - from) < (ptrdiff_t) n) + { + // to overlaps with from + // + // + // copy in reverse, to avoid overwriting from + for(ptrdiff_t i = (ptrdiff_t) (n - 1); i >= 0; --i) + { + to[i] = from[i]; + } + + return dest; + } + + if(from > to && (ptrdiff_t) (from - to) < (ptrdiff_t) n) + { + // to overlaps with from + // + // + // copy forwards, to avoid overwriting from */ + for(size_t i = 0U; i < n; ++i) + { + to[i] = from[i]; + } + + return dest; + } + + memcpy(dest, src, n); + + return dest; +} diff --git a/examples/chapter04_04/src/util/STD_LIBC/memory.cpp b/examples/chapter04_04/src/util/STD_LIBC/memory.cpp deleted file mode 100644 index 1519647a4..000000000 --- a/examples/chapter04_04/src/util/STD_LIBC/memory.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2011 - 2015. -// Distributed under the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include - -// Implement some efficient memory functions from the standard C library. -// If this file is included in the project, the linker will take these -// functions instead of its own corresponding functions from the C-library. -// The functions in this file *might* potentially save some code and/or -// runtime in the executable. - -extern "C" -void* memset(void* dst, int c, size_t n) -{ - // Convert the value c to unsigned char and copy it to the destination n times. - - std::uint8_t* the_dst = reinterpret_cast(dst); - - for( ; n > static_cast(0U); --n) - { - *the_dst = static_cast(c); - ++the_dst; - } - - return dst; -} - -extern "C" -void* memcpy(void* dst, const void* src, size_t n) -{ - std::uint8_t* the_dst = reinterpret_cast< std::uint8_t*>(dst); - const std::uint8_t* the_src = reinterpret_cast(src); - - for( ; n > static_cast(0U); --n) - { - *the_dst = *the_src; - ++the_dst; - ++the_src; - } - - return dst; -} - -extern "C" -void* memmove(void* dst, const void* src, size_t n) -{ - // The function memmove *does* work properly even when its operands overlap. - - std::uint8_t* the_dst = static_cast< std::uint8_t*>(dst); - const std::uint8_t* the_src = static_cast(src); - - // Check for a range overlap. - if((the_src < the_dst) && (the_dst < (the_src + n))) - { - the_dst += n; - the_src += n; - - for( ; n > static_cast(0U); --n) - { - // Perform a backwards copy. - --the_dst; - --the_src; - *the_dst = *the_src; - } - } - else - { - for( ; n > static_cast(0U); --n) - { - // Perform a forwards copy. - *the_dst = *the_src; - ++the_dst; - ++the_src; - } - } - - return dst; -} diff --git a/examples/chapter04_04/src/util/STL/algorithm b/examples/chapter04_04/src/util/STL/algorithm index 6d6915226..7ea5e58af 100644 --- a/examples/chapter04_04/src/util/STL/algorithm +++ b/examples/chapter04_04/src/util/STL/algorithm @@ -8,6 +8,7 @@ #ifndef ALGORITHM_2010_02_23_ #define ALGORITHM_2010_02_23_ + #include #include #include #include @@ -18,25 +19,31 @@ namespace std { + // Forward declaration. + template + STL_LOCAL_CONSTEXPR_ALGORITHMS void iter_swap(input_iterator1 left, + input_iterator2 right); + template - const value_type& (min)(const value_type& a, - const value_type& b) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (min)(value_type a, + value_type b) { return ((a < b) ? a : b); } template - const value_type& (min)(const value_type& a, - const value_type& b, - binary_function_type binary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (min)(value_type a, + value_type b, + binary_function_type binary_function) { return (binary_function(b, a) ? b : a); } template - forward_iterator min_element(forward_iterator first, - forward_iterator last) + STL_LOCAL_CONSTEXPR_ALGORITHMS forward_iterator min_element(forward_iterator first, + forward_iterator last) { forward_iterator minimum_value = first; @@ -58,9 +65,9 @@ template - forward_iterator min_element(forward_iterator first, - forward_iterator last, - binary_function_type binary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS forward_iterator min_element(forward_iterator first, + forward_iterator last, + binary_function_type binary_function) { forward_iterator minimum_value = first; @@ -81,15 +88,15 @@ } template - value_type (min)(std::initializer_list my_initializer_list) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (min)(std::initializer_list my_initializer_list) { return *std::min_element(my_initializer_list.begin(), my_initializer_list.end()); } template - value_type (min)(std::initializer_list my_initializer_list, - binary_function_type binary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (min)(std::initializer_list my_initializer_list, + binary_function_type binary_function) { return *std::min_element(my_initializer_list.begin(), my_initializer_list.end(), @@ -97,23 +104,23 @@ } template - const value_type& (max)(const value_type& a, - const value_type& b) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (max)(value_type a, + value_type b) { return ((a > b) ? a : b); } template - const value_type& (max)(const value_type& a, - const value_type& b, - binary_function_type binary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (max)(value_type a, + value_type b, + binary_function_type binary_function) { return (binary_function(a, b) ? a : b); } template - forward_iterator max_element(forward_iterator first, forward_iterator last) + STL_LOCAL_CONSTEXPR_ALGORITHMS forward_iterator max_element(forward_iterator first, forward_iterator last) { forward_iterator maximum_value = first; @@ -135,9 +142,9 @@ template - forward_iterator max_element(forward_iterator first, - forward_iterator last, - binary_function_type binary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS forward_iterator max_element(forward_iterator first, + forward_iterator last, + binary_function_type binary_function) { forward_iterator maximum_value = first; @@ -158,15 +165,15 @@ } template - value_type (max)(std::initializer_list my_initializer_list) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (max)(std::initializer_list my_initializer_list) { return *std::max_element(my_initializer_list.begin(), my_initializer_list.end()); } template - value_type (max)(std::initializer_list my_initializer_list, - binary_function_type binary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS value_type (max)(std::initializer_list my_initializer_list, + binary_function_type binary_function) { return *std::max_element(my_initializer_list.begin(), my_initializer_list.end(), @@ -220,9 +227,9 @@ template - output_iterator copy(input_iterator first, - input_iterator last, - output_iterator result) + STL_LOCAL_CONSTEXPR_ALGORITHMS output_iterator copy(input_iterator first, + input_iterator last, + output_iterator result) { for( ; first != last; ++result, ++first) { @@ -234,9 +241,9 @@ template - bidirectional_output_iterator2 copy_backward(bidirectional_input__iterator1 first1, - bidirectional_input__iterator1 last1, - bidirectional_output_iterator2 last2) + STL_LOCAL_CONSTEXPR_ALGORITHMS bidirectional_output_iterator2 copy_backward(bidirectional_input__iterator1 first1, + bidirectional_input__iterator1 last1, + bidirectional_output_iterator2 last2) { while (first1 != last1) { @@ -257,11 +264,13 @@ output_iterator result, unary_function_type unary_function) { + using output_value_type = typename std::iterator_traits::value_type; + while(first != last) { if(unary_function(*first)) { - *result = *first; + *result = output_value_type(*first); ++result; } @@ -274,22 +283,24 @@ template - void fill(forward_iterator first, - forward_iterator last, - const value_type& value) + STL_LOCAL_CONSTEXPR_ALGORITHMS void fill(forward_iterator first, + forward_iterator last, + const value_type& value) { + using forward_value_type = typename std::iterator_traits::value_type; + for( ; first != last; ++first) { - *first = value; + *first = forward_value_type(value); } } template - output_iterator fill_n(output_iterator first, - size_type count, - const value_type& value) + STL_LOCAL_CONSTEXPR_ALGORITHMS output_iterator fill_n(output_iterator first, + size_type count, + const value_type& value) { const output_iterator last(first + count); @@ -304,9 +315,11 @@ forward_iterator last, generator_type generator) { + using forward_value_type = typename std::iterator_traits::value_type; + while(first != last) { - *first = generator(); + *first = forward_value_type(generator()); ++first; } @@ -319,9 +332,11 @@ size_type count, generator_type generator) { + using output_value_type = typename std::iterator_traits::value_type; + for(size_type i = size_type(0); i < count; ++i) { - *first = generator(); + *first = output_value_type(generator()); ++first; } @@ -330,24 +345,11 @@ } template - void reverse(bidirectional_iterator first, bidirectional_iterator last) + STL_LOCAL_CONSTEXPR_ALGORITHMS void reverse(bidirectional_iterator first, bidirectional_iterator last) { - if(first != last) + while((first != last) && (first != --last)) { - --last; - - while(first != last) - { - typedef typename std::iterator_traits::value_type value_type; - - const value_type tmp(*first); - - *first = *last; - *last = tmp; - - ++first; - --last; - } + std::iter_swap(first++, last); } } @@ -359,9 +361,11 @@ output_iterator result, unary_function_type unary_function) { + using output_value_type = typename std::iterator_traits::value_type; + for( ; first != last; ++first, ++result) { - *result = unary_function(*first); + *result = output_value_type(unary_function(*first)); } return result; @@ -377,9 +381,11 @@ output_iterator result, binary_function_type binary_function) { + using output_value_type = typename std::iterator_traits::value_type; + for( ; first1 != last1; ++first1, ++first2, ++result) { - *result = binary_function(*first1, *first2); + *result = output_value_type(binary_function(*first1, *first2)); } return result; @@ -429,9 +435,9 @@ template - bool all_of(iterator_type first, - iterator_type last, - unary_function_type unary_function) + STL_LOCAL_CONSTEXPR_ALGORITHMS bool all_of(iterator_type first, + iterator_type last, + unary_function_type unary_function) { while((first != last) && unary_function(*first)) { @@ -552,6 +558,19 @@ return count_value; } + template + STL_LOCAL_CONSTEXPR_ALGORITHMS std::pair mismatch(InputIt1 first1, + InputIt1 last1, + InputIt2 first2) + { + while(first1 != last1 && *first1 == *first2) + { + ++first1, ++first2; + } + + return std::make_pair(first1, first2); + } + template typename std::iterator_traits::difference_type @@ -746,8 +765,8 @@ } template - void swap(swap_type& left, - swap_type& right) + STL_LOCAL_CONSTEXPR_ALGORITHMS void swap(swap_type& left, + swap_type& right) { if(&left != &right) { @@ -758,10 +777,20 @@ } } + template + STL_LOCAL_CONSTEXPR_ALGORITHMS void swap(swap_type&& left, + swap_type&& right) + { + const swap_type tmp(left); + + left = right; + right = tmp; + } + template - void iter_swap(input_iterator1 left, - input_iterator2 right) + STL_LOCAL_CONSTEXPR_ALGORITHMS void iter_swap(input_iterator1 left, + input_iterator2 right) { typedef typename std::iterator_traits::value_type value_left_type; typedef typename std::iterator_traits::value_type value_right_type; @@ -774,9 +803,9 @@ template - input_iterator2 swap_ranges(input_iterator1 first1, - input_iterator1 last1, - input_iterator2 first2) + STL_LOCAL_CONSTEXPR_ALGORITHMS input_iterator2 swap_ranges(input_iterator1 first1, + input_iterator1 last1, + input_iterator2 first2) { while(first1 != last1) { @@ -791,8 +820,8 @@ template - void swap(value_type(&left) [N], - value_type(&right)[N]) + STL_LOCAL_CONSTEXPR_ALGORITHMS void swap(value_type(&left) [N], + value_type(&right)[N]) { swap_ranges(&left[0U], &left[N], &right[0U]); } diff --git a/examples/chapter04_04/src/util/STL/array b/examples/chapter04_04/src/util/STL/array index f3798d9db..d409196a9 100644 --- a/examples/chapter04_04/src/util/STL/array +++ b/examples/chapter04_04/src/util/STL/array @@ -8,41 +8,41 @@ #ifndef ARRAY_2010_02_23_ #define ARRAY_2010_02_23_ + #include + #include #include #include #include - #include - // Implement most of std::array for compilers that do not yet support it. // See ISO/IEC 14882:2011 Chapter 23.3.2. namespace std { - template + template class array { public: // Standard container-local type definitions. - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; value_type elems[N]; static STL_LOCAL_CONSTEXPR size_type static_size = N; - iterator begin() { return elems; } - iterator end () { return elems + N; } + STL_LOCAL_CONSTEXPR_ALGORITHMS iterator begin() { return elems; } + STL_LOCAL_CONSTEXPR_ALGORITHMS iterator end () { return elems + N; } STL_LOCAL_CONSTEXPR const_iterator begin() const { return elems; } STL_LOCAL_CONSTEXPR const_iterator end () const { return elems + N; } @@ -50,8 +50,8 @@ STL_LOCAL_CONSTEXPR const_iterator cbegin() const { return elems; } STL_LOCAL_CONSTEXPR const_iterator cend () const { return elems + N; } - reverse_iterator rbegin() { return reverse_iterator(elems + N); } - reverse_iterator rend () { return reverse_iterator(elems); } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator rbegin() { return reverse_iterator(elems + N); } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator rend () { return reverse_iterator(elems); } STL_LOCAL_CONSTEXPR const_reverse_iterator rbegin() const { return const_reverse_iterator(elems + N); } STL_LOCAL_CONSTEXPR const_reverse_iterator rend () const { return const_reverse_iterator(elems); } @@ -59,53 +59,54 @@ STL_LOCAL_CONSTEXPR const_reverse_iterator crbegin() const { return const_reverse_iterator(elems + N); } STL_LOCAL_CONSTEXPR const_reverse_iterator crend () const { return const_reverse_iterator(elems); } - reference operator[](const size_type i) { return elems[i]; } - STL_LOCAL_CONSTEXPR const_reference operator[](const size_type i) const { return elems[i]; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reference operator[](const size_type i) { return elems[i]; } + STL_LOCAL_CONSTEXPR const_reference operator[](const size_type i) const { return elems[i]; } - reference at(const size_type i) { return elems[i]; } - STL_LOCAL_CONSTEXPR const_reference at(const size_type i) const { return elems[i]; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reference at(const size_type i) { return elems[i]; } + STL_LOCAL_CONSTEXPR const_reference at(const size_type i) const { return elems[i]; } - reference front() { return elems[0U]; } - STL_LOCAL_CONSTEXPR const_reference front() const { return elems[0U]; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reference front() { return elems[0U]; } + STL_LOCAL_CONSTEXPR const_reference front() const { return elems[0U]; } - reference back() { return elems[N - 1U]; } - STL_LOCAL_CONSTEXPR const_reference back() const { return elems[N - 1U]; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reference back() { return elems[N - 1U]; } + STL_LOCAL_CONSTEXPR const_reference back() const { return elems[N - 1U]; } static STL_LOCAL_CONSTEXPR size_type size() { return N; } static STL_LOCAL_CONSTEXPR bool empty() { return false; } static STL_LOCAL_CONSTEXPR size_type max_size() { return N; } template - void swap(array& y) + STL_LOCAL_CONSTEXPR_ALGORITHMS void swap(array& y) { std::swap_ranges(begin(), end(), y.begin()); } - STL_LOCAL_CONSTEXPR const_pointer data() const { return elems; } - pointer data() { return elems; } + STL_LOCAL_CONSTEXPR const_pointer data() const { return elems; } + STL_LOCAL_CONSTEXPR_ALGORITHMS pointer data() { return elems; } pointer c_array() { return elems; } template - array& operator=(const array& y) + STL_LOCAL_CONSTEXPR_ALGORITHMS array& operator=(const array& y) { std::copy(y.begin(), y.end(), begin()); + return *this; } - void assign(const value_type& value) + STL_LOCAL_CONSTEXPR_ALGORITHMS void assign(const value_type& value) { std::fill_n(elems, N, value); } - void fill(const value_type& value) + STL_LOCAL_CONSTEXPR_ALGORITHMS void fill(const value_type& value) { std::fill_n(elems, N, value); } }; template - bool operator==(const array& left, const array& right) + STL_LOCAL_CONSTEXPR_ALGORITHMS bool operator==(const array& left, const array& right) { return std::equal(left.begin(), left.end(), right.begin()); } @@ -120,31 +121,31 @@ } template - bool operator!=(const array& left, const array& right) + STL_LOCAL_CONSTEXPR_ALGORITHMS bool operator!=(const array& left, const array& right) { return ((left == right) == false); } template - bool operator>(const array& left, const array& right) + STL_LOCAL_CONSTEXPR_ALGORITHMS bool operator>(const array& left, const array& right) { return (right < left); } template - bool operator>=(const array& left, const array& right) + STL_LOCAL_CONSTEXPR_ALGORITHMS bool operator>=(const array& left, const array& right) { return ((left < right) == false); } template - bool operator<=(const array& left, const array& right) + STL_LOCAL_CONSTEXPR_ALGORITHMS bool operator<=(const array& left, const array& right) { return ((right < left) == false); } template - void swap(array& x, array& y) + STL_LOCAL_CONSTEXPR_ALGORITHMS void swap(array& x, array& y) { swap_ranges(x.begin(), x.end(), y.begin()); } diff --git a/examples/chapter04_04/src/util/STL/cassert b/examples/chapter04_04/src/util/STL/cassert new file mode 100644 index 000000000..a31576237 --- /dev/null +++ b/examples/chapter04_04/src/util/STL/cassert @@ -0,0 +1,13 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021 - 2022. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CASSERT_2021_10_21_ + #define CASSERT_2021_10_21_ + + #include + +#endif // CASSERT_2021_10_21_ diff --git a/examples/chapter04_04/src/util/STL/cerrno b/examples/chapter04_04/src/util/STL/cerrno new file mode 100644 index 000000000..a20898ca3 --- /dev/null +++ b/examples/chapter04_04/src/util/STL/cerrno @@ -0,0 +1,13 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021 - 2022. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CERRNO_2021_10_21_ + #define CERRNO_2021_10_21_ + + #include + +#endif // CERRNO_2021_10_21_ diff --git a/examples/chapter04_04/src/util/STL/charconv b/examples/chapter04_04/src/util/STL/charconv new file mode 100644 index 000000000..1cb80c4ec --- /dev/null +++ b/examples/chapter04_04/src/util/STL/charconv @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021 - 2024. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CHARCONV_2021_04_12_ + #define CHARCONV_2021_04_12_ + + // Implement some of for compilers that do not yet support it. + // At the moment, this contains nothing more than the implementation + // of the struct std::to_chars_result. + + #include + + namespace std + { + enum errc + { + my_unknown_errc = 0, + value_too_large = 1, + }; + } + + namespace std + { + struct to_chars_result + { + to_chars_result() : ptr(nullptr), + ec (my_unknown_errc) { } + char* ptr; + errc ec; + friend bool operator==(const to_chars_result&, const to_chars_result&) = default; + }; + + //to_chars_result to_chars(char* first, char* last, + // /* see description */ value, int base = 10); + + to_chars_result to_chars(char* first, char* last, bool value, int base = 10) = delete; + + inline to_chars_result to_chars(char* first, char* last, float value) { static_cast(first); static_cast(last); static_cast(value); return to_chars_result{ }; } + inline to_chars_result to_chars(char* first, char* last, double value) { static_cast(first); static_cast(last); static_cast(value); return to_chars_result{ }; } + inline to_chars_result to_chars(char* first, char* last, long double value) { static_cast(first); static_cast(last); static_cast(value); return to_chars_result{ }; } + } + +#endif // CHARCONV_2021_04_12_ diff --git a/examples/chapter04_04/src/util/STL/chrono b/examples/chapter04_04/src/util/STL/chrono index 0e7154ef8..f2bd53724 100644 --- a/examples/chapter04_04/src/util/STL/chrono +++ b/examples/chapter04_04/src/util/STL/chrono @@ -1,5 +1,12 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2011 - 2022. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + /////////////////////////////////////////////////////////////////////////////// -/// \author (c) Marco Paland (info@paland.com) +/// \author (c) Marco Paland (info (AT) paland.com) /// 2011-2012, PALANDesign Hannover, Germany /// /// \license LGPLv3 diff --git a/examples/chapter04_04/src/util/STL/cinttypes b/examples/chapter04_04/src/util/STL/cinttypes new file mode 100644 index 000000000..2c06e0981 --- /dev/null +++ b/examples/chapter04_04/src/util/STL/cinttypes @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CINTTYPES_2021_10_19_ + #define CINTTYPES_2021_10_19_ + + #include + #include + + namespace std + { + struct imaxdiv_t { std::intmax_t quot; std::intmax_t rem; }; + + inline std::intmax_t imaxabs(std::intmax_t n) { return ((n < 0) ? -n : n); } + + inline std::imaxdiv_t imaxdiv(std::intmax_t x, std::intmax_t y) { const std::imaxdiv_t result = { x / y, x % y }; return result; } + } + +#endif // CINTTYPES_2021_10_19_ diff --git a/examples/chapter04_04/src/util/STL/ciso646 b/examples/chapter04_04/src/util/STL/ciso646 new file mode 100644 index 000000000..9d7087bec --- /dev/null +++ b/examples/chapter04_04/src/util/STL/ciso646 @@ -0,0 +1,15 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CISO646_2023_08_15 + #define CISO646_2023_08_15 + + // Implement some of for compilers that do not yet support it. + + #include + +#endif // CISO646_2023_08_15 diff --git a/examples/chapter04_04/src/util/STL/cmath b/examples/chapter04_04/src/util/STL/cmath index b8ea9c420..3796fd976 100644 --- a/examples/chapter04_04/src/util/STL/cmath +++ b/examples/chapter04_04/src/util/STL/cmath @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,246 +8,668 @@ #ifndef CMATH_2010_02_23_ #define CMATH_2010_02_23_ - // Implement most of for compilers that do not yet support it. + #include - #include - - #if defined(__GNUC__) - - namespace std - { - #if defined(__AVR__) - #define __BUILTIN_FABSF __builtin_fabs - #define __BUILTIN_FMODF __builtin_fmod - #define __BUILTIN_MODFF __builtin_modff - #define __BUILTIN_FLOORF __builtin_floor - #define __BUILTIN_CEILF __builtin_ceil - #define __BUILTIN_FREXPF __builtin_frexp - #define __BUILTIN_LDEXPF __builtin_ldexp - #define __BUILTIN_SQRTF __builtin_sqrt - #define __BUILTIN_SINF __builtin_sin - #define __BUILTIN_COSF __builtin_cos - #define __BUILTIN_TANF __builtin_tan - #define __BUILTIN_ASINF __builtin_asin - #define __BUILTIN_ACOSF __builtin_acos - #define __BUILTIN_ATANF __builtin_atan - #define __BUILTIN_ATAN2F __builtin_atan2 - #define __BUILTIN_EXPF __builtin_exp - #define __BUILTIN_POWF __builtin_pow - #define __BUILTIN_LOGF __builtin_log - #define __BUILTIN_LOG10F __builtin_log10 - #define __BUILTIN_SINHF __builtin_sinh - #define __BUILTIN_COSHF __builtin_cosh - #define __BUILTIN_TANHF __builtin_tanh - #else - #define __BUILTIN_FABSF __builtin_fabsf - #define __BUILTIN_FMODF __builtin_fmodf - #define __BUILTIN_MODFF __builtin_modff - #define __BUILTIN_FLOORF __builtin_floorf - #define __BUILTIN_CEILF __builtin_ceilf - #define __BUILTIN_FREXPF __builtin_frexpf - #define __BUILTIN_LDEXPF __builtin_ldexpf - #define __BUILTIN_SQRTF __builtin_sqrtf - #define __BUILTIN_SINF __builtin_sinf - #define __BUILTIN_COSF __builtin_cosf - #define __BUILTIN_TANF __builtin_tanf - #define __BUILTIN_ASINF __builtin_asinf - #define __BUILTIN_ACOSF __builtin_acosf - #define __BUILTIN_ATANF __builtin_atanf - #define __BUILTIN_ATAN2F __builtin_atan2f - #define __BUILTIN_EXPF __builtin_expf - #define __BUILTIN_POWF __builtin_powf - #define __BUILTIN_LOGF __builtin_logf - #define __BUILTIN_LOG10F __builtin_log10f - #define __BUILTIN_SINHF __builtin_sinhf - #define __BUILTIN_COSHF __builtin_coshf - #define __BUILTIN_TANHF __builtin_tanhf - #endif // __AVR__ or not __AVR__ stuff - - #define __BUILTIN_FABS __builtin_fabs - #define __BUILTIN_FMOD __builtin_fmod - #define __BUILTIN_MODF __builtin_modf - #define __BUILTIN_FLOOR __builtin_floor - #define __BUILTIN_CEIL __builtin_ceil - #define __BUILTIN_FREXP __builtin_frexp - #define __BUILTIN_LDEXP __builtin_ldexp - #define __BUILTIN_SQRT __builtin_sqrt - #define __BUILTIN_SIN __builtin_sin - #define __BUILTIN_COS __builtin_cos - #define __BUILTIN_TAN __builtin_tan - #define __BUILTIN_ASIN __builtin_asin - #define __BUILTIN_ACOS __builtin_acos - #define __BUILTIN_ATAN __builtin_atan - #define __BUILTIN_ATAN2 __builtin_atan2 - #define __BUILTIN_EXP __builtin_exp - #define __BUILTIN_POW __builtin_pow - #define __BUILTIN_LOG __builtin_log - #define __BUILTIN_LOG10 __builtin_log10 - #define __BUILTIN_SINH __builtin_sinh - #define __BUILTIN_COSH __builtin_cosh - #define __BUILTIN_TANH __builtin_tanh - - #define __BUILTIN_FABSL __builtin_fabsl - #define __BUILTIN_FMODL __builtin_fmodl - #define __BUILTIN_MODFL __builtin_modfl - #define __BUILTIN_FLOORL __builtin_floorl - #define __BUILTIN_CEILL __builtin_ceill - #define __BUILTIN_FREXPL __builtin_frexpl - #define __BUILTIN_LDEXPL __builtin_ldexpl - #define __BUILTIN_SQRTL __builtin_sqrtl - #define __BUILTIN_SINL __builtin_sinl - #define __BUILTIN_COSL __builtin_cosl - #define __BUILTIN_TANL __builtin_tanl - #define __BUILTIN_ASINL __builtin_asinl - #define __BUILTIN_ACOSL __builtin_acosl - #define __BUILTIN_ATANL __builtin_atanl - #define __BUILTIN_ATAN2L __builtin_atan2l - #define __BUILTIN_EXPL __builtin_expl - #define __BUILTIN_POWL __builtin_powl - #define __BUILTIN_LOGL __builtin_logl - #define __BUILTIN_LOG10L __builtin_log10l - #define __BUILTIN_SINHL __builtin_sinhl - #define __BUILTIN_COSHL __builtin_coshl - #define __BUILTIN_TANHL __builtin_tanhl - - inline float abs (float x) { return __BUILTIN_FABSF (x); } - inline double abs (double x) { return __builtin_fabs (x); } - inline long double abs (long double x) { return __BUILTIN_FABSL (x); } - - inline float fabs (float x) { return __BUILTIN_FABSF (x); } - inline double fabs (double x) { return __BUILTIN_FABS (x); } - inline long double fabs (long double x) { return __BUILTIN_FABSL (x); } - - inline float fmod (float x, float y) { return __BUILTIN_FMODF (x, y); } - inline double fmod (double x, double y) { return __BUILTIN_FMOD (x, y); } - inline long double fmod (long double x, long double y) { return __BUILTIN_FMODL (x, y); } - - inline float modf (float x, float* p) { return __BUILTIN_MODFF (x, p); } - inline double modf (double x, double* p) { return __BUILTIN_MODF (x, p); } - inline long double modf (long double x, long double* p) { return __BUILTIN_MODFL (x, p); } - - inline float floor(float x) { return __BUILTIN_FLOORF(x); } - inline double floor(double x) { return __BUILTIN_FLOOR (x); } - inline long double floor(long double x) { return __BUILTIN_FLOORL(x); } - - inline float ceil (float x) { return __BUILTIN_CEILF (x); } - inline double ceil (double x) { return __BUILTIN_CEIL (x); } - inline long double ceil (long double x) { return __BUILTIN_CEILL (x); } - - inline float frexp(float x, int* p) { return __BUILTIN_FREXPF(x, p); } - inline double frexp(double x, int* p) { return __BUILTIN_FREXP (x, p); } - inline long double frexp(long double x, int* p) { return __BUILTIN_FREXPL(x, p); } - - inline float ldexp(float x, int p) { return __BUILTIN_LDEXPF(x, p); } - inline double ldexp(double x, int p) { return __BUILTIN_LDEXP (x, p); } - inline long double ldexp(long double x, int p) { return __BUILTIN_LDEXPL(x, p); } - - inline float sqrt (float x) { return __BUILTIN_SQRTF (x); } - inline double sqrt (double x) { return __BUILTIN_SQRT (x); } - inline long double sqrt (long double x) { return __BUILTIN_SQRTL (x); } - - inline float sin (float x) { return __BUILTIN_SINF (x); } - inline double sin (double x) { return __BUILTIN_SIN (x); } - inline long double sin (long double x) { return __BUILTIN_SINL (x); } - - inline float cos (float x) { return __BUILTIN_COSF (x); } - inline double cos (double x) { return __BUILTIN_COS (x); } - inline long double cos (long double x) { return __BUILTIN_COSL (x); } - - inline float tan (float x) { return __BUILTIN_TANF (x); } - inline double tan (double x) { return __BUILTIN_TAN (x); } - inline long double tan (long double x) { return __BUILTIN_TANL (x); } - - inline float asin (float x) { return __BUILTIN_ASINF (x); } - inline double asin (double x) { return __BUILTIN_ASIN (x); } - inline long double asin (long double x) { return __BUILTIN_ASINL (x); } - - inline float acos (float x) { return __BUILTIN_ACOSF (x); } - inline double acos (double x) { return __BUILTIN_ACOS (x); } - inline long double acos (long double x) { return __BUILTIN_ACOSL (x); } - - inline float atan (float x) { return __BUILTIN_ATANF (x); } - inline double atan (double x) { return __BUILTIN_ATAN (x); } - inline long double atan (long double x) { return __BUILTIN_ATANL (x); } - - inline float atan2(float y, float x) { return __BUILTIN_ATAN2F(y, x); } - inline double atan2(double y, double x) { return __BUILTIN_ATAN2 (y, x); } - inline long double atan2(long double y, long double x) { return __BUILTIN_ATAN2L(y, x); } - - inline float exp (float x) { return __BUILTIN_EXPF (x); } - inline double exp (double x) { return __BUILTIN_EXPF (x); } - inline long double exp (long double x) { return __BUILTIN_EXPL (x); } - - inline float pow (float x, float a) { return __BUILTIN_POWF (x, a); } - inline double pow (double x, double a) { return __BUILTIN_POW (x, a); } - inline long double pow (long double x, long double a) { return __BUILTIN_POWL (x, a); } - - inline float log (float x) { return __BUILTIN_LOGF (x); } - inline double log (double x) { return __BUILTIN_LOG (x); } - inline long double log (long double x) { return __BUILTIN_LOGL (x); } - - inline float log10(float x) { return __BUILTIN_LOG10F(x); } - inline double log10(double x) { return __BUILTIN_LOG10 (x); } - inline long double log10(long double x) { return __BUILTIN_LOG10L(x); } - - inline float sinh (float x) { return __BUILTIN_SINHF (x); } - inline double sinh (double x) { return __BUILTIN_SINH (x); } - inline long double sinh (long double x) { return __BUILTIN_SINHL (x); } - - inline float cosh (float x) { return __BUILTIN_COSHF (x); } - inline double cosh (double x) { return __BUILTIN_COSH (x); } - inline long double cosh (long double x) { return __BUILTIN_COSHL (x); } - - inline float tanh (float x) { return __BUILTIN_TANHF (x); } - inline double tanh (double x) { return __BUILTIN_TANH (x); } - inline long double tanh (long double x) { return __BUILTIN_TANHL (x); } - } // namespace std + // Implement most of for compilers that do not yet support it. + #if defined(__GNUC__) && defined(__AVR__) + #include + + #ifndef _HUGE_ENUF + #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow + #endif + + #if !defined(INFINITY) + #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) + #endif + #define HUGE_VAL ((double)INFINITY) + #define HUGE_VALF ((float)INFINITY) + #define HUGE_VALL ((long double)INFINITY) + #if !defined(NAN) + #define NAN (-(float)(INFINITY * 0.0F)) + #endif + + #define _DENORM (-2) + #define _FINITE (-1) + #define _INFCODE 1 + #define _NANCODE 2 + + #define FP_INFINITE _INFCODE + #define FP_NAN _NANCODE + #define FP_NORMAL _FINITE + #define FP_SUBNORMAL _DENORM + #define FP_ZERO 0 + + #define _C2 1 // 0 if not 2's complement + #define FP_ILOGB0 (-0x7fffffff - _C2) + #define FP_ILOGBNAN 0x7fffffff + + static_assert(__SIZEOF_LONG_DOUBLE__ >= __SIZEOF_DOUBLE__, + "Error: Configuration error regarding 64-bit double/long-double for AVR"); + + #if(__SIZEOF_DOUBLE__ == 4) + #define __BUILTIN_ISNANF __builtin_isnan + #define __BUILTIN_ISNAN __builtin_isnan + #define __BUILTIN_ISNANL __builtin_isnanl + #define __BUILTIN_FABSF __builtin_fabs + #define __BUILTIN_FABS __builtin_fabs + #define __BUILTIN_FABSL __builtin_fabsl + #define __BUILTIN_FMODF __builtin_fmod + #define __BUILTIN_FMOD __builtin_fmod + #define __BUILTIN_FMODL __builtin_fmodl + #define __BUILTIN_MODFF __builtin_modff + #define __BUILTIN_MODF __builtin_modf + #define __BUILTIN_MODFL __builtin_modfl + #define __BUILTIN_FLOORF __builtin_floor + #define __BUILTIN_FLOOR __builtin_floor + #define __BUILTIN_FLOORL __builtin_floorl + #define __BUILTIN_CEILF __builtin_ceil + #define __BUILTIN_CEIL __builtin_ceil + #define __BUILTIN_CEILL __builtin_ceill + #define __BUILTIN_FREXPF __builtin_frexp + #define __BUILTIN_FREXP __builtin_frexp + #define __BUILTIN_FREXPL __builtin_frexpl + #define __BUILTIN_LDEXPF __builtin_ldexp + #define __BUILTIN_LDEXP __builtin_ldexp + #define __BUILTIN_LDEXPL __builtin_ldexpl + #define __BUILTIN_LROUNDF __builtin_lround + #define __BUILTIN_LROUND __builtin_lround + #define __BUILTIN_LROUNDL __builtin_lroundl + #define __BUILTIN_SQRTF __builtin_sqrt + #define __BUILTIN_SQRT __builtin_sqrt + #define __BUILTIN_SQRTL __builtin_sqrtl + #define __BUILTIN_CBRTF __builtin_cbrt + #define __BUILTIN_CBRT __builtin_cbrt + #define __BUILTIN_CBRTL __builtin_cbrtl + #define __BUILTIN_SINF __builtin_sin + #define __BUILTIN_SIN __builtin_sin + #define __BUILTIN_SINL __builtin_sinl + #define __BUILTIN_COSF __builtin_cos + #define __BUILTIN_COS __builtin_cos + #define __BUILTIN_COSL __builtin_cosl + #define __BUILTIN_TANF __builtin_tan + #define __BUILTIN_TAN __builtin_tan + #define __BUILTIN_TANL __builtin_tanl + #define __BUILTIN_ASINF __builtin_asin + #define __BUILTIN_ASIN __builtin_asin + #define __BUILTIN_ASINL __builtin_asinl + #define __BUILTIN_ACOSF __builtin_acos + #define __BUILTIN_ACOS __builtin_acos + #define __BUILTIN_ACOSL __builtin_acosl + #define __BUILTIN_ATANF __builtin_atan + #define __BUILTIN_ATAN __builtin_atan + #define __BUILTIN_ATANL __builtin_atanl + #define __BUILTIN_ATAN2F __builtin_atan2 + #define __BUILTIN_ATAN2 __builtin_atan2 + #define __BUILTIN_ATAN2L __builtin_atan2l + #define __BUILTIN_EXPF __builtin_exp + #define __BUILTIN_EXP __builtin_exp + #define __BUILTIN_EXPL __builtin_expl + #define __BUILTIN_POWF __builtin_pow + #define __BUILTIN_POW __builtin_pow + #define __BUILTIN_POWL __builtin_powl + #define __BUILTIN_LOGF __builtin_log + #define __BUILTIN_LOG __builtin_log + #define __BUILTIN_LOGL __builtin_logl + #define __BUILTIN_LOG10F __builtin_log10 + #define __BUILTIN_LOG10 __builtin_log10 + #define __BUILTIN_LOG10L __builtin_log10l + #define __BUILTIN_SINHF __builtin_sinh + #define __BUILTIN_SINH __builtin_sinh + #define __BUILTIN_SINHL __builtin_sinhl + #define __BUILTIN_COSHF __builtin_cosh + #define __BUILTIN_COSH __builtin_cosh + #define __BUILTIN_COSHL __builtin_coshl + #define __BUILTIN_TANHF __builtin_tanh + #define __BUILTIN_TANH __builtin_tanh + #define __BUILTIN_TANHL __builtin_tanhl + #elif(__SIZEOF_DOUBLE__ == 8) + #define __BUILTIN_ISNANF __builtin_isnanf + #define __BUILTIN_ISNAN __builtin_isnanl + #define __BUILTIN_ISNANL __builtin_isnanl + #define __BUILTIN_FABSF __builtin_fabsf + #define __BUILTIN_FABS __builtin_fabsl + #define __BUILTIN_FABSL __builtin_fabsl + #define __BUILTIN_FMODF __builtin_fmodf + #define __BUILTIN_FMOD __builtin_fmodl + #define __BUILTIN_FMODL __builtin_fmodl + #define __BUILTIN_MODFF __builtin_modff + #define __BUILTIN_MODF __builtin_modf + #define __BUILTIN_MODFL __builtin_modfl + #define __BUILTIN_FLOORF __builtin_floorf + #define __BUILTIN_FLOOR __builtin_floorl + #define __BUILTIN_FLOORL __builtin_floorl + #define __BUILTIN_CEILF __builtin_ceilf + #define __BUILTIN_CEIL __builtin_ceill + #define __BUILTIN_CEILL __builtin_ceill + #define __BUILTIN_FREXPF __builtin_frexpf + #define __BUILTIN_FREXP __builtin_frexpl + #define __BUILTIN_FREXPL __builtin_frexpl + #define __BUILTIN_LDEXPF __builtin_ldexpf + #define __BUILTIN_LDEXP __builtin_ldexpl + #define __BUILTIN_LDEXPL __builtin_ldexpl + #define __BUILTIN_LROUNDF __builtin_lroundf + #define __BUILTIN_LROUND __builtin_lroundl + #define __BUILTIN_LROUNDL __builtin_lroundl + #define __BUILTIN_SQRTF __builtin_sqrtf + #define __BUILTIN_SQRT __builtin_sqrtl + #define __BUILTIN_SQRTL __builtin_sqrtl + #define __BUILTIN_CBRTF __builtin_cbrtf + #define __BUILTIN_CBRT __builtin_cbrtl + #define __BUILTIN_CBRTL __builtin_cbrtl + #define __BUILTIN_SINF __builtin_sinf + #define __BUILTIN_SIN __builtin_sinl + #define __BUILTIN_SINL __builtin_sinl + #define __BUILTIN_COSF __builtin_cosf + #define __BUILTIN_COS __builtin_cosl + #define __BUILTIN_COSL __builtin_cosl + #define __BUILTIN_TANF __builtin_tanf + #define __BUILTIN_TAN __builtin_tanl + #define __BUILTIN_TANL __builtin_tanl + #define __BUILTIN_ASINF __builtin_asinf + #define __BUILTIN_ASIN __builtin_asinl + #define __BUILTIN_ASINL __builtin_asinl + #define __BUILTIN_ACOSF __builtin_acosf + #define __BUILTIN_ACOS __builtin_acosl + #define __BUILTIN_ACOSL __builtin_acosl + #define __BUILTIN_ATANF __builtin_atanf + #define __BUILTIN_ATAN __builtin_atanl + #define __BUILTIN_ATANL __builtin_atanl + #define __BUILTIN_ATAN2F __builtin_atan2f + #define __BUILTIN_ATAN2 __builtin_atan2l + #define __BUILTIN_ATAN2L __builtin_atan2l + #define __BUILTIN_EXPF __builtin_expf + #define __BUILTIN_EXP __builtin_expl + #define __BUILTIN_EXPL __builtin_expl + #define __BUILTIN_POWF __builtin_powf + #define __BUILTIN_POW __builtin_powl + #define __BUILTIN_POWL __builtin_powl + #define __BUILTIN_LOGF __builtin_logf + #define __BUILTIN_LOG __builtin_logl + #define __BUILTIN_LOGL __builtin_logl + #define __BUILTIN_LOG10F __builtin_log10f + #define __BUILTIN_LOG10 __builtin_log10l + #define __BUILTIN_LOG10L __builtin_log10l + #define __BUILTIN_SINHF __builtin_sinhf + #define __BUILTIN_SINH __builtin_sinhl + #define __BUILTIN_SINHL __builtin_sinhl + #define __BUILTIN_COSHF __builtin_coshf + #define __BUILTIN_COSH __builtin_coshl + #define __BUILTIN_COSHL __builtin_coshl + #define __BUILTIN_TANHF __builtin_tanhf + #define __BUILTIN_TANH __builtin_tanhl + #define __BUILTIN_TANHL __builtin_tanhl #else + #error Error: sizeof(double) is unknown or not standard for AVR. + #endif - #include - - namespace std - { - inline float abs(float x) { return ::fabsf(x); } - inline double abs(double x) { return ::fabs (x); } - inline long double abs(long double x) { return ::fabsl(x); } - - using ::fabs; - using ::fmod; - using ::modf; - using ::floor; - using ::ceil; - using ::frexp; - using ::ldexp; - using ::sqrt; - using ::sin; - using ::cos; - using ::tan; - using ::asin; - using ::acos; - using ::atan; - using ::atan2; - using ::exp; - using ::pow; - using ::log; - using ::log10; - using ::sinh; - using ::cosh; - using ::tanh; - } - - #endif // __GNUC__ or not __GNUC__ stuff + extern "C" + { + //int isfinitef(float x); + int isfinitel(long double x); + int ilogbf(float x); + int ilogb (double x); + int ilogbl(long double x); + + float asinhf(float x); + double asinh (double x); + long double asinhl(long double x); + + float acoshf(float x); + double acosh (double x); + long double acoshl(long double x); + + float atanhf(float x); + double atanh (double x); + long double atanhl(long double x); + + float tgammaf(float x); + double tgamma (double x); + long double tgammal(long double x); + + float lgammaf(float x); + double lgamma (double x); + long double lgammal(long double x); + } namespace std { - // Provide certain functions that are often missing from . - // Here, we patch some of these in an exemplary fashion for the - // proposed std::float32_t. - float32_t asinh (std::float32_t x); - float32_t acosh (std::float32_t x); - float32_t atanh (std::float32_t x); - float32_t tgamma(std::float32_t x); + inline bool isfinite(float x) { return ::isfinitef(x) == 1; } + inline bool isfinite(double x) { return ::isfinite (x) == 1; } + inline bool isfinite(long double x) { return ::isfinitel(x) == 1; } + inline int ilogb (float x) { return ::ilogbf (x); } + inline int ilogb (double x) { return ::ilogb (x); } + inline int ilogb (long double x) { return ::ilogbl (x); } + inline bool isnan (float x) { return __BUILTIN_ISNANF (x) == 1; } + inline bool isnan (double x) { return __BUILTIN_ISNAN (x) == 1; } + inline bool isnan (long double x) { return __BUILTIN_ISNANL (x) == 1; } + inline float fabs (float x) { return __BUILTIN_FABSF (x); } + inline double fabs (double x) { return __BUILTIN_FABS (x); } + inline long double fabs (long double x) { return __BUILTIN_FABSL (x); } + inline float fmod (float x, float y) { return __BUILTIN_FMODF (x, y); } + inline double fmod (double x, double y) { return __BUILTIN_FMOD (x, y); } + inline long double fmod (long double x, long double y) { return __BUILTIN_FMODL (x, y); } + inline float modf (float x, float* intptr) { return __BUILTIN_MODFF (x, intptr); } + inline double modf (double x, double* intptr) { return __BUILTIN_MODF (x, intptr); } + inline long double modf (long double x, long double* intptr) { return __BUILTIN_MODFL (x, intptr); } + inline float floor (float x) { return __BUILTIN_FLOORF(x); } + inline double floor (double x) { return __BUILTIN_FLOOR (x); } + inline long double floor (long double x) { return __BUILTIN_FLOORL(x); } + inline float ceil (float x) { return __BUILTIN_CEILF (x); } + inline double ceil (double x) { return __BUILTIN_CEIL (x); } + inline long double ceil (long double x) { return __BUILTIN_CEILL (x); } + inline float frexp (float x, int* p) { return __BUILTIN_FREXPF(x, p); } + inline double frexp (double x, int* p) { return __BUILTIN_FREXP (x, p); } + inline long double frexp (long double x, int* p) { return __BUILTIN_FREXPL(x, p); } + inline float ldexp (float x, int p) { return __BUILTIN_LDEXPF(x, p); } + inline double ldexp (double x, int p) { return __BUILTIN_LDEXP (x, p); } + inline long double ldexp (long double x, int p) { return __BUILTIN_LDEXPL(x, p); } + inline long lround (float x) { return __BUILTIN_LROUNDF(x); } + inline long lround (double x) { return __BUILTIN_LROUND (x); } + inline long lround (long double x) { return __BUILTIN_LROUNDL(x); } + inline float sqrt (float x) { return __BUILTIN_SQRTF (x); } + inline double sqrt (double x) { return __BUILTIN_SQRT (x); } + inline long double sqrt (long double x) { return __BUILTIN_SQRTL (x); } + inline float cbrt (float x) { return __BUILTIN_CBRTF (x); } + inline double cbrt (double x) { return __BUILTIN_CBRT (x); } + inline long double cbrt (long double x) { return __BUILTIN_CBRTL (x); } + inline float sin (float x) { return __BUILTIN_SINF (x); } + inline double sin (double x) { return __BUILTIN_SIN (x); } + inline long double sin (long double x) { return __BUILTIN_SINL (x); } + inline float cos (float x) { return __BUILTIN_COSF (x); } + inline double cos (double x) { return __BUILTIN_COS (x); } + inline long double cos (long double x) { return __BUILTIN_COSL (x); } + inline float tan (float x) { return __BUILTIN_TANF (x); } + inline double tan (double x) { return __BUILTIN_TAN (x); } + inline long double tan (long double x) { return __BUILTIN_TANL (x); } + inline float asin (float x) { return __BUILTIN_ASINF (x); } + inline double asin (double x) { return __BUILTIN_ASIN (x); } + inline long double asin (long double x) { return __BUILTIN_ASINL (x); } + inline float acos (float x) { return __BUILTIN_ACOSF (x); } + inline double acos (double x) { return __BUILTIN_ACOS (x); } + inline long double acos (long double x) { return __BUILTIN_ACOSL (x); } + inline float atan (float x) { return __BUILTIN_ATANF (x); } + inline double atan (double x) { return __BUILTIN_ATAN (x); } + inline long double atan (long double x) { return __BUILTIN_ATANL (x); } + inline float atan2 (float y, float x) { return __BUILTIN_ATAN2F(y, x); } + inline double atan2 (double y, double x) { return __BUILTIN_ATAN2 (y, x); } + inline long double atan2 (long double y, long double x) { return __BUILTIN_ATAN2L(y, x); } + inline float expf (float x) { return __BUILTIN_EXPF (x); } + inline double exp (double x) { return __BUILTIN_EXP (x); } + inline long double exp (long double x) { return __BUILTIN_EXPL (x); } + inline float pow (float x, float a) { return __BUILTIN_POWF (x, a); } + inline double pow (double x, double a) { return __BUILTIN_POW (x, a); } + inline long double pow (long double x, long double a) { return __BUILTIN_POWL (x, a); } + inline float log (float x) { return __BUILTIN_LOGF (x); } + inline double log (double x) { return __BUILTIN_LOG (x); } + inline long double log (long double x) { return __BUILTIN_LOGL (x); } + inline float log10 (float x) { return __BUILTIN_LOG10F(x); } + inline double log10 (double x) { return __BUILTIN_LOG10 (x); } + inline long double log10 (long double x) { return __BUILTIN_LOG10L(x); } + inline float sinh (float x) { return __BUILTIN_SINHF (x); } + inline double sinh (double x) { return __BUILTIN_SINH (x); } + inline long double sinh (long double x) { return __BUILTIN_SINHL (x); } + inline float cosh (float x) { return __BUILTIN_COSHF (x); } + inline double cosh (double x) { return __BUILTIN_COSH (x); } + inline long double cosh (long double x) { return __BUILTIN_COSHL (x); } + inline float tanh (float x) { return __BUILTIN_TANHF (x); } + inline double tanh (double x) { return __BUILTIN_TANH (x); } + inline long double tanh (long double x) { return __BUILTIN_TANHL (x); } + inline float asinh (float x) { return ::asinhf(x); } + inline double asinh (double x) { return ::asinh (x); } + inline long double asinh (long double x) { return ::asinhl(x); } + inline float acosh (float x) { return ::acoshf(x); } + inline double acosh (double x) { return ::acosh (x); } + inline long double acosh (long double x) { return ::acoshl(x); } + inline float atanh (float x) { return ::asinhf(x); } + inline double atanh (double x) { return ::asinh (x); } + inline long double atanh (long double x) { return ::asinhl(x); } + inline float tgamma (float x) { return ::tgammaf(x); } + inline double tgamma (double x) { return ::tgamma (x); } + inline long double tgamma (long double x) { return ::tgammal(x); } + inline float lgamma (float x) { return ::lgammaf(x); } + inline double lgamma (double x) { return ::lgamma (x); } + inline long double lgamma (long double x) { return ::lgammal(x); } } + #else + + #if defined(__cplusplus) + extern "C" + { + #endif + // These are (most of) the functions from having C-linkage. + int isfinitef(float); + int isfinitel(long double); + int ilogbf (float); + int ilogbl (long double); + int isnanf (float); + int isnanl (long double); + float fabsf (float x); + long double fabsl (long double x); + float fmodf (float x, float y); + long double fmodl (long double x, long double y); + float modff (float x, float* intptr); + long double modfl (long double x, long double* intptr); + float floorf (float x); + long double floorl (long double x); + float ceilf (float x); + long double ceill (long double x); + float frexpf (float x, int* p); + long double frexpl (long double x, int* p); + float ldexpf (float x, int p); + long double ldexpl (long double x, int p); + long lroundf (float x); + long lroundl (long double x); + float sqrtf (float x); + long double sqrtl (long double x); + float cbrtf (float x); + long double cbrtl (long double x); + float sinf (float x); + long double sinl (long double x); + float cosf (float x); + long double cosl (long double x); + float tanf (float x); + long double tanl (long double x); + float asinf (float x); + long double asinl (long double x); + float acosf (float x); + long double acosl (long double x); + float atanf (float x); + long double atanl (long double x); + float atan2f (float y, float x); + long double atan2l (long double y, long double x); + float expf (float x); + long double expl (long double x); + float powf (float x, float a); + long double powl (long double x, long double a); + float logf (float x); + long double logl (long double x); + float log10f (float x); + long double log10l (long double x); + float sinhf (float x); + long double sinhl (long double x); + float coshf (float x); + long double coshl (long double x); + float tanhf (float x); + long double tanhl (long double x); + float asinhf (float x); + long double asinhl (long double x); + float acoshf (float x); + long double acoshl (long double x); + float atanhf (float x); + long double atanhl (long double x); + float tgammaf (float x); + long double tgammal (long double x); + float lgammaf (float x); + long double lgammal (long double x); + #if defined(__cplusplus) + } + #endif + + #if defined(__cplusplus) + extern "C++" + { + #endif + inline bool isfinite(float x) { return (::isfinitef(x) == 1); } + inline bool isfinite(double x) { return (::isfinite (x) == 1); } + inline bool isfinite(long double x) { return (::isfinitel(x) == 1); } + inline int ilogb (float x) { return ::ilogbf(x); } + inline int ilogb (double x) { return ::ilogb (x); } + inline int ilogb (long double x) { return ::ilogbl(x); } + #if defined(__GNUC__) + inline bool isnan (float x) { return __builtin_isnanf(x); } + inline bool isnan (double x) { return __builtin_isnan (x); } + inline bool isnan (long double x) { return __builtin_isnanl(x); } + inline float abs (float x) { return __builtin_fabsf (x); } + inline double abs (double x) { return __builtin_fabs (x); } + inline long double abs (long double x) { return __builtin_fabsl (x); } + inline float fabs (float x) { return __builtin_fabsf (x); } + inline double fabs (double x) { return __builtin_fabs (x); } + inline long double fabs (long double x) { return __builtin_fabsl (x); } + inline float fmod (float x, float y) { return __builtin_fmodf (x, y); } + inline double fmod (double x, double y) { return __builtin_fmod (x, y); } + inline long double fmod (long double x, long double y) { return __builtin_fmodl (x, y); } + inline float modf (float x, float* p) { return __builtin_modff (x, p); } + inline double modf (double x, double* p) { return __builtin_modf (x, p); } + inline long double modf (long double x, long double* p) { return __builtin_modfl (x, p); } + inline float floor (float x) { return __builtin_floorf(x); } + inline double floor (double x) { return __builtin_floor (x); } + inline long double floor (long double x) { return __builtin_floorl(x); } + inline float ceil (float x) { return __builtin_ceilf (x); } + inline double ceil (double x) { return __builtin_ceil (x); } + inline long double ceil (long double x) { return __builtin_ceill (x); } + inline float frexp (float x, int* p) { return __builtin_frexpf(x, p); } + inline double frexp (double x, int* p) { return __builtin_frexp (x, p); } + inline long double frexp (long double x, int* p) { return __builtin_frexpl(x, p); } + inline float ldexp (float x, int p) { return __builtin_ldexpf(x, p); } + inline double ldexp (double x, int p) { return __builtin_ldexp (x, p); } + inline long double ldexp (long double x, int p) { return __builtin_ldexpl(x, p); } + inline long lround (float x) { return __builtin_lroundf(x); } + inline long lround (double x) { return __builtin_lround (x); } + inline long lround (long double x) { return __builtin_lroundl(x); } + inline float sqrt (float x) { return __builtin_sqrtf (x); } + inline double sqrt (double x) { return __builtin_sqrt (x); } + inline long double sqrt (long double x) { return __builtin_sqrtl (x); } + inline float cbrt (float x) { return __builtin_cbrtf (x); } + inline double cbrt (double x) { return __builtin_cbrt (x); } + inline long double cbrt (long double x) { return __builtin_cbrtl (x); } + inline float sin (float x) { return __builtin_sinf (x); } + inline double sin (double x) { return __builtin_sin (x); } + inline long double sin (long double x) { return __builtin_sinl (x); } + inline float cos (float x) { return __builtin_cosf (x); } + inline double cos (double x) { return __builtin_cos (x); } + inline long double cos (long double x) { return __builtin_cosl (x); } + inline float tan (float x) { return __builtin_tanf (x); } + inline double tan (double x) { return __builtin_tan (x); } + inline long double tan (long double x) { return __builtin_tanl (x); } + inline float asin (float x) { return __builtin_asinf (x); } + inline double asin (double x) { return __builtin_asin (x); } + inline long double asin (long double x) { return __builtin_asinl (x); } + inline float acos (float x) { return __builtin_acosf (x); } + inline double acos (double x) { return __builtin_acos (x); } + inline long double acos (long double x) { return __builtin_acosl (x); } + inline float atan (float x) { return __builtin_atanf (x); } + inline double atan (double x) { return __builtin_atan (x); } + inline long double atan (long double x) { return __builtin_atanl (x); } + inline float atan2 (float y, float x) { return __builtin_atan2f(y, x); } + inline double atan2 (double y, double x) { return __builtin_atan2 (y, x); } + inline long double atan2 (long double y, long double x) { return __builtin_atan2l(y, x); } + inline float exp (float x) { return __builtin_expf (x); } + inline double exp (double x) { return __builtin_exp (x); } + inline long double exp (long double x) { return __builtin_expl (x); } + inline float pow (float x, float a) { return __builtin_powf (x, a); } + inline double pow (double x, double a) { return __builtin_pow (x, a); } + inline long double pow (long double x, long double a) { return __builtin_powl (x, a); } + inline float log (float x) { return __builtin_logf (x); } + inline double log (double x) { return __builtin_log (x); } + inline long double log (long double x) { return __builtin_logl (x); } + inline float log10 (float x) { return __builtin_log10f(x); } + inline double log10 (double x) { return __builtin_log10 (x); } + inline long double log10 (long double x) { return __builtin_log10l(x); } + inline float sinh (float x) { return __builtin_sinhf (x); } + inline double sinh (double x) { return __builtin_sinh (x); } + inline long double sinh (long double x) { return __builtin_sinhl (x); } + inline float cosh (float x) { return __builtin_coshf (x); } + inline double cosh (double x) { return __builtin_cosh (x); } + inline long double cosh (long double x) { return __builtin_coshl (x); } + inline float tanh (float x) { return __builtin_tanhf (x); } + inline double tanh (double x) { return __builtin_tanh (x); } + inline long double tanh (long double x) { return __builtin_tanhl (x); } + #else + inline bool isnan (float x) { return ::isnanf(x); } + bool isnan (double x); + inline bool isnan (long double x) { return ::isnanl(x); } + inline float abs (float x) { return ::fabsf (x); } + extern "C" + double abs (double x); + inline long double abs (long double x) { return ::fabsl (x); } + inline float fabs (float x) { return ::fabsf (x); } + extern "C" + double fabs (double x); + inline long double fabs (long double x) { return ::fabsl (x); } + inline float fmod (float x, float y) { return ::fmodf(x, y); } + extern "C" + double fmod (double x, double y); + inline long double fmod (long double x, long double y) { return ::fmodl(x, y); } + inline float modf (float x, float* p) { return ::modff (x, p); } + extern "C" + double modf (double x, double* p); + inline long double modf (long double x, long double* p) { return ::modfl (x, p); } + inline float floor (float x) { return ::floorf(x); } + extern "C" + double floor (double x); + inline long double floor (long double x) { return ::floorl(x); } + inline float ceil (float x) { return ::ceilf (x); } + extern "C" + double ceil (double x); + inline long double ceil (long double x) { return ::ceill (x); } + inline float frexp (float x, int* p) { return ::frexpf(x, p); } + extern "C" + double frexp (double x, int* p); + inline long double frexp (long double x, int* p) { return ::frexpl(x, p); } + inline float ldexp (float x, int p) { return ::ldexpf(x, p); } + extern "C" + double ldexp (double x, int p); + inline long double ldexp (long double x, int p) { return ::ldexpl (x, p); } + inline long lround (float x) { return ::lroundf(x); } + extern "C" + long lround (double x); + inline long lround (long double x) { return ::lroundl(x); } + inline float sqrt (float x) { return ::sqrtf (x); } + extern "C" + double sqrt (double x); + inline long double sqrt (long double x) { return ::sqrtl (x); } + inline float cbrt (float x) { return ::cbrtf (x); } + extern "C" + double cbrt (double x); + inline long double cbrt (long double x) { return ::cbrtl (x); } + inline float sin (float x) { return ::sinf (x); } + extern "C" + double sin (double x); + inline long double sin (long double x) { return ::sinl (x); } + inline float cos (float x) { return ::cosf (x); } + extern "C" + double cos (double x); + inline long double cos (long double x) { return ::cosl (x); } + inline float tan (float x) { return ::tanf (x); } + extern "C" + double tan (double x); + inline long double tan (long double x) { return ::tanl (x); } + inline float asin (float x) { return ::asinf (x); } + extern "C" + double asin (double x); + inline long double asin (long double x) { return ::asinl (x); } + inline float acos (float x) { return ::acosf (x); } + extern "C" + double acos (double x); + inline long double acos (long double x) { return ::acosl (x); } + inline float atan (float x) { return ::atanf (x); } + extern "C" + double atan (double x); + inline long double atan (long double x) { return ::atanl (x); } + inline float atan2 (float y, float x) { return ::atan2f(y, x); } + extern "C" + double atan2 (double y, double x); + inline long double atan2 (long double y, long double x) { return ::atan2l(y, x); } + inline float exp (float x) { return ::expf (x); } + extern "C" + double exp (double x); + inline long double exp (long double x) { return ::expl (x); } + inline float pow (float x, float a) { return ::powf (x, a); } + extern "C" + double pow (double x, double a); + inline long double pow (long double x, long double a) { return ::powl (x, a); } + inline float log (float x) { return ::logf (x); } + extern "C" + double log (double x); + inline long double log (long double x) { return ::logl (x); } + inline float log10 (float x) { return ::log10f(x); } + extern "C" + double log10 (double x); + inline long double log10 (long double x) { return ::log10l(x); } + inline float sinh (float x) { return ::sinhf (x); } + extern "C" + double sinh (double x); + inline long double sinh (long double x) { return ::sinhl (x); } + inline float cosh (float x) { return ::coshf (x); } + extern "C" + double cosh (double x); + inline long double cosh (long double x) { return ::coshl (x); } + inline float tanh (float x) { return ::tanhf (x); } + extern "C" + double tanh (double x); + inline long double tanh (long double x) { return ::tanhl (x); } + #endif + inline float asinh (float x) { return ::asinhf(x); } + extern "C" + double asinh (double x); + inline long double asinh (long double x) { return ::asinhl(x); } + inline float acosh (float x) { return ::acoshf(x); } + extern "C" + double acosh (double x); + inline long double acosh (long double x) { return ::acoshl(x); } + inline float atanh (float x) { return ::atanhf(x); } + extern "C" + double atanh (double x); + inline long double atanh (long double x) { return ::atanhl(x); } + inline float tgamma (float x) { return ::tgammaf(x); } + extern "C" + double tgamma (double x); + inline long double tgamma (long double x) { return ::tgammal(x); } + inline float lgamma (float x) { return ::lgammaf(x); } + extern "C" + double lgamma (double x); + inline long double lgamma (long double x) { return ::lgammal(x); } + #if __cplusplus > 201703L + inline float lerp (float a, float b, float t) + { return a + (t * (b - a)); } + inline double lerp (double a, double b, double t) + { return a + (t * (b - a)); } + inline long double lerp (long double a, long double b, long double t) + { return a + (t * (b - a)); } + #endif + #if defined(__cplusplus) + } + #endif + + namespace std + { + using ::isfinite; + using ::ilogb; + using ::isnan; + using ::abs; + using ::fabs; + using ::fmod; + using ::modf; + using ::floor; + using ::ceil; + using ::frexp; + using ::ldexp; + using ::lround; + using ::sqrt; + using ::cbrt; + using ::sin; + using ::cos; + using ::tan; + using ::asin; + using ::acos; + using ::atan; + using ::atan2; + using ::exp; + using ::pow; + using ::log; + using ::log10; + using ::sinh; + using ::cosh; + using ::tanh; + using ::asinh; + using ::acosh; + using ::atanh; + using ::tgamma; + using ::lgamma; + } // namespace std + + #endif + #endif // CMATH_2010_02_23_ diff --git a/examples/chapter04_04/src/util/STL/complex b/examples/chapter04_04/src/util/STL/complex index af71423d8..1e5db0445 100644 --- a/examples/chapter04_04/src/util/STL/complex +++ b/examples/chapter04_04/src/util/STL/complex @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -1287,7 +1287,7 @@ } // namespace std /* - 8-bit microcontroller @ 16MHz + 8-bit microcontroller at 16MHz std::complex x(1.23F, 3.45F); std::complex y(0.77F, 0.22F); diff --git a/examples/chapter04_04/src/util/STL/cstdint b/examples/chapter04_04/src/util/STL/cstdint index 1e030cf28..0e2e8d7ed 100644 --- a/examples/chapter04_04/src/util/STL/cstdint +++ b/examples/chapter04_04/src/util/STL/cstdint @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -49,35 +49,36 @@ namespace std { - using ::int8_t; - using ::int16_t; - using ::int32_t; - using ::int64_t; + using ::int8_t; + using ::int16_t; + using ::int32_t; + using ::int64_t; using ::uint8_t; using ::uint16_t; using ::uint32_t; using ::uint64_t; - using ::int_least8_t; - using ::int_least16_t; - using ::int_least32_t; - using ::int_least64_t; + using ::int_least8_t; + using ::int_least16_t; + using ::int_least32_t; + using ::int_least64_t; using ::uint_least8_t; using ::uint_least16_t; using ::uint_least32_t; using ::uint_least64_t; - using ::int_fast8_t; - using ::int_fast16_t; - using ::int_fast32_t; - using ::int_fast64_t; + using ::int_fast8_t; + using ::int_fast16_t; + using ::int_fast32_t; + using ::int_fast64_t; using ::uint_fast8_t; using ::uint_fast16_t; using ::uint_fast32_t; using ::uint_fast64_t; - using ::intmax_t; + using ::intmax_t; using ::uintmax_t; + using ::intptr_t; using ::uintptr_t; } diff --git a/examples/chapter04_04/src/util/STL/cstdlib b/examples/chapter04_04/src/util/STL/cstdlib index 83e04fe69..0055579ac 100644 --- a/examples/chapter04_04/src/util/STL/cstdlib +++ b/examples/chapter04_04/src/util/STL/cstdlib @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2017. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,15 +29,31 @@ #define EXIT_FAILURE -1 #endif - void exit(int) __attribute__((noreturn)); + extern "C" + { + void abort (void); + int atexit(void(*)(void)) noexcept; + void exit (int); + float strtof(const char* str, char** str_end); + double strtod(const char* str, char** str_end); + long double strtold(const char* str, char** str_end); + } namespace std { inline int abs(int a) { return ((a < 0) ? -a : a); } + //inline long abs(long a) { return ((a < 0) ? -a : a); } + //inline long long abs(long long a) { return ((a < 0) ? -a : a); } inline long labs(long a) { return ((a < 0) ? -a : a); } inline long long llabs(long long a) { return ((a < 0) ? -a : a); } - inline void exit(int exit_code) { ::exit(exit_code); } + using ::abort; + using ::atexit; + using ::exit; + + using ::strtof; + using ::strtod; + using ::strtold; struct div_t { int quot; int rem; }; struct ldiv_t { long quot; long rem; }; diff --git a/examples/chapter04_04/src/util/STL/cstring b/examples/chapter04_04/src/util/STL/cstring index e2b079384..3a899f75e 100644 --- a/examples/chapter04_04/src/util/STL/cstring +++ b/examples/chapter04_04/src/util/STL/cstring @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,15 +10,20 @@ #include - extern "C" void* memset(void*, int, size_t); - extern "C" size_t strlen(const char*); - extern "C" char* strcpy(char*, const char*); + extern "C" void* memcpy (void*, const void*, size_t); + extern "C" void* memmove(void*, const void*, size_t); + extern "C" void* memset (void*, int, size_t); + + extern "C" char* strcpy (char*, const char*); + extern "C" size_t strlen (const char*); namespace std { - inline void* memset(void* dst, int c, size_t n) { return ::memset(dst, c, n); } - inline ::size_t strlen(const char* str) { return ::strlen(str); } - inline char* strcpy(char* p_dst, const char* p_src) { return ::strcpy(p_dst, p_src); } + using ::memcpy; + using ::memmove; + using ::memset; + using ::strlen; + using ::strcpy; } #endif // CSTRING_2018_10_04_ diff --git a/examples/chapter04_04/src/util/STL/functional b/examples/chapter04_04/src/util/STL/functional index 4d04b4e38..0302e7dc9 100644 --- a/examples/chapter04_04/src/util/STL/functional +++ b/examples/chapter04_04/src/util/STL/functional @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -14,6 +14,16 @@ namespace std { + template + struct hash + { + // Since the underlying type is a std::uint64_t we will rely on its hash function from the STL + auto operator()(const T&) const noexcept -> std::size_t + { + return std::size_t { }; + } + }; + namespace xfunctional_impl { template constexpr T& func_ref_or_moveref(T& t) noexcept { return t; } @@ -56,7 +66,7 @@ template struct identity { - typedef T type; + using type = T; }; template. + +#ifndef ALLOC_TRAITS_2021_01_26_H_ + #define ALLOC_TRAITS_2021_01_26_H_ + + #include + + namespace std + { + template + class allocator; + + template + using __void_t = void; + + struct __allocator_traits_base + { + template + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template + struct __rebind<_Tp, _Up, __void_t::other>> + { + using type = typename _Tp::template rebind<_Up>::other; + }; + + protected: + template + using __pointer = typename _Tp::pointer; + + template + using __c_pointer = typename _Tp::const_pointer; + + template + using __v_pointer = typename _Tp::void_pointer; + + template + using __cv_pointer = typename _Tp::const_void_pointer; + + template + using __pocca = typename _Tp::propagate_on_container_copy_assignment; + + template + using __pocma = typename _Tp::propagate_on_container_move_assignment; + + template + using __pocs = typename _Tp::propagate_on_container_swap; + + template + using __equal = typename _Tp::is_always_equal; + }; + + template + using __alloc_rebind = typename __allocator_traits_base::template __rebind::type; + + template + struct allocator_traits : __allocator_traits_base + { + public: + typedef AllocatorType allocator_type; + typedef typename AllocatorType::value_type value_type; + + using pointer = __detected_or_t; + + private: + template class _Func, typename _Tp, typename = void> + struct _Ptr + { + using type = typename pointer_traits::template rebind<_Tp>; + }; + + template class _Func, typename _Tp> + struct _Ptr<_Func, _Tp, __void_t<_Func>> + { + using type = _Func; + }; + + template + struct _Diff + { + using type = typename pointer_traits<_PtrT>::difference_type; + }; + + template + struct _Diff<_A2, _PtrT, __void_t> + { + using type = typename _A2::difference_type; + }; + + template + struct _Size + { + using type = size_t; + }; + + template + struct _Size<_A2, _DiffT, __void_t> + { + using type = typename _A2::size_type; + }; + + public: + using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; + using void_pointer = typename _Ptr<__v_pointer, void>::type; + using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; + using difference_type = typename _Diff::type; + using size_type = typename _Size::type; + + using propagate_on_container_swap = __detected_or_t; + + template + using rebind_alloc = __alloc_rebind; + + template + using rebind_traits = allocator_traits>; + + private: + template + static auto _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) -> decltype(__a.allocate(__n, __hint)) + { + return __a.allocate(__n, __hint); + } + + template + static pointer _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) + { + return __a.allocate(__n); + } + + template + struct __construct_helper + { + template()->construct( + std::declval<_Tp*>(), std::declval<_Args>()...))> + static true_type __test(int); + + template + static false_type __test(...); + + using type = decltype(__test(0)); + }; + + template + using __has_construct = typename __construct_helper<_Tp, _Args...>::type; + + template + static void _S_construct(AllocatorType& __a, _Tp* __p, _Args&&... __args) + { + __a.construct(__p, std::forward<_Args>(__args)...); + } + + template + static void _S_destroy(_Alloc2& __a, _Tp* __p, int) + { + __a.destroy(__p); + } + + template + static void _S_destroy(_Alloc2&, _Tp* __p, ...) + { + __p->~_Tp(); + } + + template + static size_type _S_max_size(_Alloc2& __a, int) + { + return __a.max_size(); + } + + template + static size_type _S_max_size(_Alloc2&, ...) + { + return (size_type) (0xFFFFFFFFFFFFFFFFULL / sizeof(value_type)); + } + + template + static auto _S_select(_Alloc2& __a, int) -> decltype(__a.select_on_container_copy_construction()) + { + return __a.select_on_container_copy_construction(); + } + + template + static _Alloc2 _S_select(_Alloc2& __a, ...) + { + return __a; + } + + public: + static pointer allocate(AllocatorType& __a, size_type __n) + { + return __a.allocate(__n); + } + + static pointer allocate(AllocatorType& __a, size_type __n, const_void_pointer __hint) + { + return _S_allocate(__a, __n, __hint, 0); + } + + static void deallocate(AllocatorType& __a, pointer __p, size_type __n) + { + __a.deallocate(__p, __n); + } + + template + static auto construct(AllocatorType& __a, _Tp* __p, _Args&&... __args) -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) + { + _S_construct(__a, __p, std::forward<_Args>(__args)...); + } + + template + static void destroy(AllocatorType& __a, _Tp* __p) + { + _S_destroy(__a, __p, 0); + } + + static size_type max_size(const AllocatorType& __a) noexcept + { return _S_max_size(__a, 0); } + + static AllocatorType + select_on_container_copy_construction(const AllocatorType& __rhs) + { return _S_select(__rhs, 0); } + }; + + template + struct allocator_traits> + { + // Partial specialization for std::allocator. + using allocator_type = allocator<_Tp>; + using value_type = _Tp; + using pointer = _Tp*; + using const_pointer = const _Tp*; + using void_pointer = void*; + using const_void_pointer = const void*; + using difference_type = std::ptrdiff_t; + using size_type = std::size_t; + using propagate_on_container_copy_assignment = false_type; + using propagate_on_container_move_assignment = true_type; + using propagate_on_container_swap = false_type; + using is_always_equal = true_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + static pointer allocate(allocator_type& __a, size_type __n) + { return __a.allocate(__n); } + + static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) + { return __a.allocate(__n, __hint); } + + static void deallocate(allocator_type& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + template + static void construct(allocator_type& __a, _Up* __p, _Args&&... __args) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + template + static void destroy(allocator_type& __a, _Up* __p) noexcept(noexcept(__a.destroy(__p))) + { __a.destroy(__p); } + + static size_type max_size(const allocator_type& __a) noexcept + { return __a.max_size(); } + + static allocator_type select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; + } + +#endif // ALLOC_TRAITS_2021_01_26_H_ diff --git a/examples/chapter04_04/src/util/STL/impl/avr/avr_atomic.h b/examples/chapter04_04/src/util/STL/impl/avr/avr_atomic.h index ba02a690e..7179cc287 100644 --- a/examples/chapter04_04/src/util/STL/impl/avr/avr_atomic.h +++ b/examples/chapter04_04/src/util/STL/impl/avr/avr_atomic.h @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/STL/impl/avr/avr_float_limits.cpp b/examples/chapter04_04/src/util/STL/impl/avr/avr_float_limits.cpp deleted file mode 100644 index 5a7597274..000000000 --- a/examples/chapter04_04/src/util/STL/impl/avr/avr_float_limits.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. -// Distributed under the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include - -#include - -namespace std -{ - namespace xfloat_impl - { - // Use some GCC internal stuff here. - STL_LOCAL_CONSTEXPR float avr_nan_flt = static_cast(__builtin_nan("")); - STL_LOCAL_CONSTEXPR float avr_inf_flt = static_cast(__builtin_inf()); - STL_LOCAL_CONSTEXPR double avr_nan_dbl = __builtin_nan(""); - STL_LOCAL_CONSTEXPR double avr_inf_dbl = __builtin_inf(); - STL_LOCAL_CONSTEXPR long double avr_nan_ldbl = static_cast(__builtin_nan("")); - STL_LOCAL_CONSTEXPR long double avr_inf_ldbl = static_cast(__builtin_inf()); - } - - float numeric_limits_details::my_value_that_needs_to_be_provided_flt_quiet_NaN() - { - return std::xfloat_impl::avr_nan_flt; - } - - float numeric_limits_details::my_value_that_needs_to_be_provided_flt_signaling_NaN() - { - return 0.0F; - } - - float numeric_limits_details::my_value_that_needs_to_be_provided_flt_infinity() - { - return std::xfloat_impl::avr_inf_flt; - } - - double numeric_limits_details::my_value_that_needs_to_be_provided_dbl_quiet_NaN() - { - return std::xfloat_impl::avr_nan_dbl; - } - - double numeric_limits_details::my_value_that_needs_to_be_provided_dbl_signaling_NaN() - { - return 0.0; - } - - double numeric_limits_details::my_value_that_needs_to_be_provided_dbl_infinity() - { - return std::xfloat_impl::avr_inf_dbl; - } - - long double numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_quiet_NaN() - { - return std::xfloat_impl::avr_nan_ldbl; - } - - long double numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_signaling_NaN() - { - return 0.0L; - } - - long double numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_infinity() - { - return std::xfloat_impl::avr_inf_ldbl; - } -} diff --git a/examples/chapter04_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp b/examples/chapter04_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp new file mode 100644 index 000000000..85ce935df --- /dev/null +++ b/examples/chapter04_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#include +#include +#include +#include + +auto my_hardware_random_device_generator(void) -> unsigned int +{ + using timer_type = util::timer; + + const auto t_now = timer_type::get_mark(); + + const auto pseudo_random1 = + math::checksums::crc::crc32_mpeg2 + ( + reinterpret_cast(&t_now), + reinterpret_cast(&t_now) + sizeof(std::uint32_t) + ); + + const auto pseudo_random2 = + math::checksums::crc::crc32_mpeg2 + ( + reinterpret_cast(&t_now) + sizeof(std::uint32_t), + reinterpret_cast(&t_now) + sizeof(std::uint64_t) + ); + + return static_cast(util::make_long(pseudo_random1, pseudo_random2)); +} + +extern "C" unsigned char my_hardware_random_device_entropy(void) +{ + return 1U; +} diff --git a/examples/chapter04_04/src/util/STL/impl/cmath_impl_gamma.cpp b/examples/chapter04_04/src/util/STL/impl/cmath_impl_gamma.cpp deleted file mode 100644 index 8edd85ef5..000000000 --- a/examples/chapter04_04/src/util/STL/impl/cmath_impl_gamma.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. -// Distributed under the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include -#include -#include "xcmath_impl.h" - -// Here, we compute the tgamma function for std::float32_t. -// This provides an example of a portable special function -// calculation using floating-point type definitions having -// specified widths from the proposed . - -namespace std -{ - namespace xcmath_impl - { - std::float32_t tgamma_inverse_taylor_series (std::float32_t); - std::float32_t tgamma_polynomial_approximation(std::float32_t); - - std::float32_t tgamma_inverse_taylor_series(std::float32_t x) - { - // Implement a small-argument Taylor series for 1 / tgamma(x). - const std::float32_t inverse_series_value - = ((((((( + FLOAT32_C(0.0072189432) - * x - FLOAT32_C(0.0096219715)) - * x - FLOAT32_C(0.0421977346)) - * x + FLOAT32_C(0.1665386114)) - * x - FLOAT32_C(0.0420026350)) - * x - FLOAT32_C(0.6558780715)) - * x + FLOAT32_C(0.5772156649)) - * x + FLOAT32_C(1.0)) - * x; - - return FLOAT32_C(1.0) / inverse_series_value; - } - - std::float32_t tgamma_polynomial_approximation(std::float32_t x) - { - // Implement an order-9 polynomial fit for gamma(1 + x). - const std::float32_t polynomial_approximation_value - = (((((((( - FLOAT32_C(0.0235850272) - * x + FLOAT32_C(0.1405004023)) - * x - FLOAT32_C(0.3860871683)) - * x + FLOAT32_C(0.6721315341)) - * x - FLOAT32_C(0.8649108124)) - * x + FLOAT32_C(0.9539074630)) - * x - FLOAT32_C(0.9035083713)) - * x + FLOAT32_C(0.9887589417)) - * x - FLOAT32_C(0.5772069549)) - * x + FLOAT32_C(0.9999999703); - - // Return the polynomial fit for gamma(x). - // One downward recursion is used here. - return (polynomial_approximation_value / x); - } - } - - std::float32_t tgamma(std::float32_t); -} - -std::float32_t std::tgamma(std::float32_t x) -{ - // Use a positive argument for the Gamma calculation. - const bool b_neg = (x < 0); - - x = ((!b_neg) ? x : -x); - - // Check if the argument is pure zero or indistinguishably close to zero. - if(x < (std::numeric_limits::min)()) - { - return std::numeric_limits::quiet_NaN(); - } - - // Check if the argument is smaller than epsilon(). - if(x < std::numeric_limits::epsilon()) - { - using std::xcmath_impl::euler; - - return ((!b_neg) ? (FLOAT32_C(+1.0) / x) - euler() - : (FLOAT32_C(-1.0) / x) - euler()); - } - - // Check for overflow. - if(x > FLOAT32_C(35.04)) - { - return std::numeric_limits::infinity(); - } - - // Check if the argument is very close to +1 or +2? - if(b_neg == false) - { - using std::xcmath_impl::near_integer; - - const bool is_near_one = near_integer(x, static_cast(1U)); - const bool is_near_two = near_integer(x, static_cast(2U)); - - if(is_near_one || is_near_two) - { - return FLOAT32_C(1.0); - } - } - - // Evaluate the number of recursions needed in order to reach - // the range 0 < x < 1, and scale the argument accordingly. - const std::uint_least8_t n_recur = static_cast(std::floor(x)); - - x -= n_recur; - - // Obtain an approximation of tgamma(x), where x has - // perhaps been negated and/or scaled to a lower value. - std::float32_t gamma_value = ((x < FLOAT32_C(0.1)) ? std::xcmath_impl::tgamma_inverse_taylor_series(x) - : std::xcmath_impl::tgamma_polynomial_approximation(x)); - - // Scale up the result via recursion if necessary. - for(std::uint_least8_t k = static_cast(0U); k < n_recur; ++k) - { - gamma_value *= x; - - ++x; - } - - // Return (and possibly reflect) the result. - if(false == b_neg) - { - return gamma_value; - } - else - { - using std::xcmath_impl::pi; - - const std::float32_t sin_pi_x = std::sin(pi() * x); - - return -pi() / ((x * gamma_value) * sin_pi_x); - } -} diff --git a/examples/chapter04_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp b/examples/chapter04_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp deleted file mode 100644 index 463879188..000000000 --- a/examples/chapter04_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014. -// Distributed under the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include -#include -#include "xcmath_impl.h" - -// Here, we implement naive computations of the inverse hyperbolic -// trigonometric functions asinh, acosh, and atanh for std::float32_t. -// The inverse hyperbolic trigonometric functions are represented -// in terms of logarithmic functions. - -// These provide examples of portable calculations of some common -// elementary transcendental functions using floating-point typedefs -// having specified widths. - -namespace std -{ - std::float32_t asinh(std::float32_t); - std::float32_t acosh(std::float32_t); - std::float32_t atanh(std::float32_t); -} - -std::float32_t std::asinh(std::float32_t x) -{ - // Implement a naive hyperbolic arc-sine function. - return std::log(x + std::sqrt((x * x) + FLOAT32_C(1.0))); -} - -std::float32_t std::acosh(std::float32_t x) -{ - const std::float32_t x_minus_one = x - FLOAT32_C(1.0); - - if(x_minus_one < -std::numeric_limits::epsilon()) - { - return std::numeric_limits::quiet_NaN(); - } - else if(x_minus_one < std::numeric_limits::epsilon()) - { - return FLOAT32_C(1.0); - } - else - { - // Implement a naive hyperbolic arc-cosine function. - const std::float32_t xp = (x + FLOAT32_C(1.0)); - const std::float32_t xm = (x - FLOAT32_C(1.0)); - - return std::log(x + std::sqrt(xm * xp)); - } -} - -std::float32_t std::atanh(std::float32_t x) -{ - const bool is_neg = (x < FLOAT32_C(0.0)); - - const std::float32_t xx = ((!is_neg) ? x : -x); - - if(xx > FLOAT32_C(1.0)) - { - return std::numeric_limits::quiet_NaN(); - } - - std::float32_t result; - - if(xx < FLOAT32_C(1.0)) - { - // Implement a naive hyperbolic arc-tangent function. - const std::float32_t xp = (xx + FLOAT32_C(1.0)); - const std::float32_t xm = (FLOAT32_C(1.0) - xx); - - result = (std::log(xp) - std::log(xm)) / FLOAT32_C(2.0); - } - else - { - result = std::numeric_limits::infinity(); - } - - return ((!is_neg) ? result : -result); -} diff --git a/examples/chapter04_04/src/util/STL/impl/ptr_traits.h b/examples/chapter04_04/src/util/STL/impl/ptr_traits.h new file mode 100644 index 000000000..eeac46613 --- /dev/null +++ b/examples/chapter04_04/src/util/STL/impl/ptr_traits.h @@ -0,0 +1,183 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021 - 2022. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Pointer Traits -*- C++ -*- + +// Copyright (C) 2011-2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#ifndef PTR_TRAITS_2021_01_26_H_ + #define PTR_TRAITS_2021_01_26_H_ + + namespace std + { + template + using __void_t = void; + + // Implementation of the detection idiom (negative case). + template class _Op, typename... _Args> + struct __detector + { + using value_t = false_type; + using type = _Default; + }; + + // Implementation of the detection idiom (positive case). + template class _Op, + typename... _Args> + struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> + { + using value_t = true_type; + using type = _Op<_Args...>; + }; + + // Detect whether _Op<_Args...> is a valid type, use _Default if not. + template class _Op, typename... _Args> + using __detected_or = __detector<_Default, void, _Op, _Args...>; + + // _Op<_Args...> if that is a valid type, otherwise _Default. + template class _Op, typename... _Args> + using __detected_or_t = typename __detected_or<_Default, _Op, _Args...>::type; + + class __undefined; + + // Given Template return T, otherwise invalid. + template + struct __get_first_arg + { using type = __undefined; }; + + template class _Template, + typename _Tp, + typename... _Types> + struct __get_first_arg<_Template<_Tp, _Types...>> + { using type = _Tp; }; + + template + using __get_first_arg_t = typename __get_first_arg<_Tp>::type; + + // Given Template and U return Template, otherwise invalid. + template + struct __replace_first_arg { }; + + template class _Template, + typename _Up, + typename _Tp, typename... _Types> + struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> + { using type = _Template<_Up, _Types...>; }; + + template + using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type; + + template + using __make_not_void = typename conditional::value, __undefined, _Tp>::type; + + template + struct pointer_traits + { + private: + template + using __element_type = typename _Tp::element_type; + + template + using __difference_type = typename _Tp::difference_type; + + template + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template + struct __rebind<_Tp, _Up, __void_t>> + { using type = typename _Tp::template rebind<_Up>; }; + + public: + using pointer = _Ptr; + using element_type = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; + using difference_type = __detected_or_t; + + template + using rebind = typename __rebind<_Ptr, _Up>::type; + + static _Ptr pointer_to(__make_not_void& __e) + { return _Ptr::pointer_to(__e); } + + static_assert(!is_same::value, + "pointer type defines element_type or is like SomePointer"); + }; + + template + struct pointer_traits<_Tp*> + { + typedef _Tp* pointer; + typedef _Tp element_type; + typedef ptrdiff_t difference_type; + + template + using rebind = _Up*; + + static constexpr pointer pointer_to(__make_not_void& __r) + { return std::addressof(__r); } + }; + + // Convenience alias for rebinding pointers. + template + using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; + + template + constexpr _Tp* __to_address(_Tp* __ptr) + { + return __ptr; + } + + #if __cplusplus <= 201703L + template + constexpr typename std::pointer_traits<_Ptr>::element_type* __to_address(const _Ptr& __ptr) + { return std::__to_address(__ptr.operator->()); } + #else + template + constexpr auto __to_address(const _Ptr& __ptr) -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) + { return std::pointer_traits<_Ptr>::to_address(__ptr); } + + template + constexpr auto __to_address(const _Ptr& __ptr, _None...) + { + return std::__to_address(__ptr.operator->()); + } + + template + constexpr _Tp* + to_address(_Tp* __ptr) + { return std::__to_address(__ptr); } + + template + constexpr auto + to_address(const _Ptr& __ptr) + { return std::__to_address(__ptr); } + + #endif // C++2a + } + +#endif // PTR_TRAITS_2021_01_26_H_ diff --git a/examples/chapter04_04/src/util/STL/impl/stl_local_constexpr.h b/examples/chapter04_04/src/util/STL/impl/stl_local_constexpr.h index ec4112078..b010f2cfa 100644 --- a/examples/chapter04_04/src/util/STL/impl/stl_local_constexpr.h +++ b/examples/chapter04_04/src/util/STL/impl/stl_local_constexpr.h @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2014 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,7 +8,27 @@ #ifndef STL_LOCAL_CONSTEXPR_2014_12_04_H_ #define STL_LOCAL_CONSTEXPR_2014_12_04_H_ - #if defined(__GNUC__) + #if (defined(__cplusplus) && (__cplusplus >= 201402L)) + #if defined(__AVR__) && (!defined(__GNUC__) || (defined(__GNUC__) && (__GNUC__ > 7))) + #define STL_LOCAL_CONSTEXPR_ALGORITHMS constexpr + #elif (defined(__cpp_lib_constexpr_algorithms) && (__cpp_lib_constexpr_algorithms>=201806)) + #if defined(__clang__) + #if (__clang_major__ > 9) + #define STL_LOCAL_CONSTEXPR_ALGORITHMS constexpr + #else + #define STL_LOCAL_CONSTEXPR_ALGORITHMS + #endif + #else + #define STL_LOCAL_CONSTEXPR_ALGORITHMS constexpr + #endif + #else + #define STL_LOCAL_CONSTEXPR_ALGORITHMS + #endif + #else + #define STL_LOCAL_CONSTEXPR_ALGORITHMS + #endif + + #if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__) #define STL_LOCAL_CONSTEXPR constexpr #else #define STL_LOCAL_CONSTEXPR const diff --git a/examples/chapter04_04/src/util/STL/impl/stl_local_noexcept.h b/examples/chapter04_04/src/util/STL/impl/stl_local_noexcept.h index 2f2c95fd2..6ea9125da 100644 --- a/examples/chapter04_04/src/util/STL/impl/stl_local_noexcept.h +++ b/examples/chapter04_04/src/util/STL/impl/stl_local_noexcept.h @@ -10,6 +10,8 @@ #if defined(_MSC_VER) #define STL_LOCAL_NOEXCEPT throw() + #elif defined(__IAR_SYSTEMS_ICC__) + #define STL_LOCAL_NOEXCEPT #else #define STL_LOCAL_NOEXCEPT noexcept #endif diff --git a/examples/chapter04_04/src/util/STL/impl/xcmath_impl.h b/examples/chapter04_04/src/util/STL/impl/xcmath_impl.h index f0d9b4f73..1120d94ff 100644 --- a/examples/chapter04_04/src/util/STL/impl/xcmath_impl.h +++ b/examples/chapter04_04/src/util/STL/impl/xcmath_impl.h @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,7 +12,7 @@ #include #include - namespace std { namespace xcmath_impl { + namespace xcmath_impl { template bool near_integer(const float_type& x, const std::uint_least8_t n) @@ -27,22 +27,23 @@ } template - const float_type pi() + constexpr float_type pi() { - return static_cast(FLOATMAX_C(3.1415926535897932384626433832795028841972)); + return static_cast(3.1415926535897932384626433832795028841972L); } template - const float_type ln_two() + constexpr float_type ln_two() { - return static_cast(FLOATMAX_C(0.6931471805599453094172321214581765680755)); + return static_cast(0.6931471805599453094172321214581765680755L); } - template - const float_type euler() - { - return static_cast(FLOATMAX_C(0.5772156649015328606065120900824024310422)); - } - } } // namespace std::xcmath_impl + template + constexpr float_type euler() + { + return static_cast(0.5772156649015328606065120900824024310422L); + } + + } // namespace xcmath_impl #endif // XCMATH_IMPL_2014_01_11_H_ diff --git a/examples/chapter04_04/src/util/STL/iterator b/examples/chapter04_04/src/util/STL/iterator index 7d65caff8..b21b81899 100644 --- a/examples/chapter04_04/src/util/STL/iterator +++ b/examples/chapter04_04/src/util/STL/iterator @@ -8,6 +8,8 @@ #ifndef ITERATOR_2010_02_23_ #define ITERATOR_2010_02_23_ + #include + #include // Implement some of for compilers that do not yet support it. @@ -52,10 +54,7 @@ typedef const value_type& reference; typedef random_access_iterator_tag iterator_category; }; - } - namespace std - { template @@ -86,56 +85,57 @@ typedef typename iterator_traits::reference reference; typedef typename iterator_traits::iterator_category iterator_category; - reverse_iterator() { } + constexpr reverse_iterator() = default; - explicit reverse_iterator(iterator_type x) : current(x) { } + explicit constexpr reverse_iterator(iterator_type x) : current(x) { } template - reverse_iterator(const reverse_iterator& u) : current(u.current) { } + constexpr reverse_iterator(const reverse_iterator& u) : current(u.current) { } - iterator_type base() const { return current; } + constexpr iterator_type base() const { return current; } - reference operator*() const { iterator_type tmp = current; return *--tmp; } - pointer operator->() const { return &(operator*()); } + STL_LOCAL_CONSTEXPR_ALGORITHMS reference operator* () const { iterator_type tmp = current; return *--tmp; } + constexpr pointer operator->() const { return &(operator*()); } - reverse_iterator& operator++() { --current; return *this; } - reverse_iterator& operator--() { ++current; return *this; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator& operator++() { --current; return *this; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator& operator--() { ++current; return *this; } - reverse_iterator operator++(int) { reverse_iterator tmp = *this; --current; return tmp; } - reverse_iterator operator--(int) { reverse_iterator tmp = *this; ++current; return tmp; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator operator++(int) { reverse_iterator tmp = *this; --current; return tmp; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator operator--(int) { reverse_iterator tmp = *this; ++current; return tmp; } - reverse_iterator operator+(typename reverse_iterator::difference_type n) const { return reverse_iterator(current - n); } - reverse_iterator operator-(typename reverse_iterator::difference_type n) const { return reverse_iterator(current + n); } + constexpr reverse_iterator operator+(typename reverse_iterator::difference_type n) const { return reverse_iterator(current - n); } + constexpr reverse_iterator operator-(typename reverse_iterator::difference_type n) const { return reverse_iterator(current + n); } - reverse_iterator& operator+=(typename reverse_iterator::difference_type n) { current -= n; return *this; } - reverse_iterator& operator-=(typename reverse_iterator::difference_type n) { current += n; return *this; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator& operator+=(typename reverse_iterator::difference_type n) { current -= n; return *this; } + STL_LOCAL_CONSTEXPR_ALGORITHMS reverse_iterator& operator-=(typename reverse_iterator::difference_type n) { current += n; return *this; } - reference operator[](typename reverse_iterator::difference_type n) const { return current[-n - 1]; } + constexpr reference operator[](typename reverse_iterator::difference_type n) const { return current[-n - 1]; } private: iterator_type current; - friend inline bool operator< (const reverse_iterator& x, const reverse_iterator& y) { return (x.current > y.current); } - friend inline bool operator<=(const reverse_iterator& x, const reverse_iterator& y) { return (x.current >= y.current); } - friend inline bool operator==(const reverse_iterator& x, const reverse_iterator& y) { return (x.current == y.current); } - friend inline bool operator!=(const reverse_iterator& x, const reverse_iterator& y) { return (x.current != y.current); } - friend inline bool operator>=(const reverse_iterator& x, const reverse_iterator& y) { return (x.current <= y.current); } - friend inline bool operator> (const reverse_iterator& x, const reverse_iterator& y) { return (x.current < y.current); } + friend inline constexpr bool operator< (const reverse_iterator& x, const reverse_iterator& y) { return (x.current > y.current); } + friend inline constexpr bool operator<=(const reverse_iterator& x, const reverse_iterator& y) { return (x.current >= y.current); } + friend inline constexpr bool operator==(const reverse_iterator& x, const reverse_iterator& y) { return (x.current == y.current); } + friend inline constexpr bool operator!=(const reverse_iterator& x, const reverse_iterator& y) { return (x.current != y.current); } + friend inline constexpr bool operator>=(const reverse_iterator& x, const reverse_iterator& y) { return (x.current <= y.current); } + friend inline constexpr bool operator> (const reverse_iterator& x, const reverse_iterator& y) { return (x.current < y.current); } - friend inline typename reverse_iterator::difference_type operator-(const reverse_iterator& x, - const reverse_iterator& y) + friend inline constexpr typename reverse_iterator::difference_type operator-(const reverse_iterator& x, + const reverse_iterator& y) { return (y.current - x.current); } - friend inline reverse_iterator operator+(typename reverse_iterator::difference_type n, - const reverse_iterator& x) + friend inline constexpr reverse_iterator operator+(typename reverse_iterator::difference_type n, + const reverse_iterator& x) { return reverse_iterator(x.current - n); } }; template + STL_LOCAL_CONSTEXPR_ALGORITHMS typename iterator_traits::difference_type distance(input_iterator first, input_iterator last) { @@ -155,6 +155,7 @@ template + STL_LOCAL_CONSTEXPR_ALGORITHMS void advance(input_iterator& it, distance_type n) { for(distance_type i = distance_type(0); i != n; ++i, ++it) @@ -164,31 +165,31 @@ } // See ISO/IEC 14882:2011, near the end of Section 24.3. - template inline auto begin( container_type& c) -> decltype(c.begin()) { return c.begin(); } - template inline auto begin(const container_type& c) -> decltype(c.begin()) { return c.begin(); } - template inline auto cbegin(const container_type& c) -> decltype(c.cbegin()) { return c.cbegin(); } - template inline auto end ( container_type& c) -> decltype(c.end()) { return c.end(); } - template inline auto end (const container_type& c) -> decltype(c.end()) { return c.end(); } - template inline auto cend (const container_type& c) -> decltype(c.cend()) { return c.cend(); } - - template inline auto rbegin( container_type& c) -> decltype(c.rbegin()) { return c.rbegin(); } - template inline auto rbegin(const container_type& c) -> decltype(c.rbegin()) { return c.rbegin(); } - template inline auto crbegin(const container_type& c) -> decltype(c.crbegin()) { return c.crbegin(); } - template inline auto rend ( container_type& c) -> decltype(c.rend()) { return c.rend(); } - template inline auto rend (const container_type& c) -> decltype(c.rend()) { return c.rend(); } - template inline auto crend (const container_type& c) -> decltype(c.crend()) { return c.crend(); } - - template inline value_type* begin (value_type(&c_array)[N]) { return &c_array[0U]; } - template inline value_type* end (value_type(&c_array)[N]) { return &c_array[N]; } - - template inline const value_type* cbegin (value_type(&c_array)[N]) { return &c_array[0U]; } - template inline const value_type* cend (value_type(&c_array)[N]) { return &c_array[N]; } - - template inline value_type* rbegin (value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[N]); } - template inline value_type* rend (value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[0U]); } - - template inline const value_type* crbegin(value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[N]); } - template inline const value_type* crend (value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[0U]); } + template inline constexpr auto begin( container_type& c) -> decltype(c.begin()) { return c.begin(); } + template inline constexpr auto begin(const container_type& c) -> decltype(c.begin()) { return c.begin(); } + template inline constexpr auto cbegin(const container_type& c) -> decltype(c.cbegin()) { return c.cbegin(); } + template inline constexpr auto end ( container_type& c) -> decltype(c.end()) { return c.end(); } + template inline constexpr auto end (const container_type& c) -> decltype(c.end()) { return c.end(); } + template inline constexpr auto cend (const container_type& c) -> decltype(c.cend()) { return c.cend(); } + + template inline constexpr auto rbegin( container_type& c) -> decltype(c.rbegin()) { return c.rbegin(); } + template inline constexpr auto rbegin(const container_type& c) -> decltype(c.rbegin()) { return c.rbegin(); } + template inline constexpr auto crbegin(const container_type& c) -> decltype(c.crbegin()) { return c.crbegin(); } + template inline constexpr auto rend ( container_type& c) -> decltype(c.rend()) { return c.rend(); } + template inline constexpr auto rend (const container_type& c) -> decltype(c.rend()) { return c.rend(); } + template inline constexpr auto crend (const container_type& c) -> decltype(c.crend()) { return c.crend(); } + + template inline constexpr value_type* begin (value_type(&c_array)[N]) { return &c_array[0U]; } + template inline constexpr value_type* end (value_type(&c_array)[N]) { return &c_array[N]; } + + template inline const constexpr value_type* cbegin (value_type(&c_array)[N]) { return &c_array[0U]; } + template inline const constexpr value_type* cend (value_type(&c_array)[N]) { return &c_array[N]; } + + template inline constexpr value_type* rbegin (value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[N]); } + template inline constexpr value_type* rend (value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[0U]); } + + template inline const constexpr value_type* crbegin(value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[N]); } + template inline const constexpr value_type* crend (value_type(&c_array)[N]) { return std::reverse_iterator(&c_array[0U]); } } #endif // ITERATOR_2010_02_23_ diff --git a/examples/chapter04_04/src/util/STL/limits b/examples/chapter04_04/src/util/STL/limits index 367a2fb1e..15bf177a3 100644 --- a/examples/chapter04_04/src/util/STL/limits +++ b/examples/chapter04_04/src/util/STL/limits @@ -19,6 +19,9 @@ // The implementation was partly inspired by some concepts in GCC's // implementation of . + #if defined(__GNUC__) && defined(__XTENSA__) + extern "C++" { + #endif namespace std { #define CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS true @@ -52,25 +55,52 @@ class numeric_limits_details { private: - static const long long my_long_long_max = 0x7FFFFFFFFFFFFFFFLL; + static constexpr long long my_long_long_max = 0x7FFFFFFFFFFFFFFFLL; // The following values for float, double, and long double are provided // in a separate file that is dependent on the AVR architecture. - static float my_value_that_needs_to_be_provided_flt_infinity(); - static float my_value_that_needs_to_be_provided_flt_quiet_NaN(); - static float my_value_that_needs_to_be_provided_flt_signaling_NaN(); - static float my_value_that_needs_to_be_provided_flt_denorm_min(); - - static double my_value_that_needs_to_be_provided_dbl_infinity(); - static double my_value_that_needs_to_be_provided_dbl_quiet_NaN(); - static double my_value_that_needs_to_be_provided_dbl_signaling_NaN(); - static double my_value_that_needs_to_be_provided_dbl_denorm_min(); - - static long double my_value_that_needs_to_be_provided_ldbl_infinity(); - static long double my_value_that_needs_to_be_provided_ldbl_quiet_NaN(); - static long double my_value_that_needs_to_be_provided_ldbl_signaling_NaN(); - static long double my_value_that_needs_to_be_provided_ldbl_denorm_min(); + #if defined(__GNUC__) + static constexpr float my_value_that_needs_to_be_provided_flt_infinity() { return __builtin_inff(); } + static constexpr float my_value_that_needs_to_be_provided_flt_quiet_NaN() { return __builtin_nanf(""); } + static constexpr float my_value_that_needs_to_be_provided_flt_signaling_NaN() { return __builtin_nanf(""); } + #endif + #if defined(__IAR_SYSTEMS_ICC__) + static constexpr float my_value_that_needs_to_be_provided_flt_infinity() { return 0.Infinity; } + static constexpr float my_value_that_needs_to_be_provided_flt_quiet_NaN() { return 0.NaN; } + static constexpr float my_value_that_needs_to_be_provided_flt_signaling_NaN() { return 0.NaN; } + #endif + static constexpr float my_value_that_needs_to_be_provided_flt_denorm_min() { return FLT_MIN; } + + #if defined(__GNUC__) + #if defined(__AVR__) && (__SIZEOF_DOUBLE__ == 8) + static constexpr double my_value_that_needs_to_be_provided_dbl_infinity() { return __builtin_infl(); } + static constexpr double my_value_that_needs_to_be_provided_dbl_quiet_NaN() { return __builtin_nanl(""); } + static constexpr double my_value_that_needs_to_be_provided_dbl_signaling_NaN() { return __builtin_nanl(""); } + #else + static constexpr double my_value_that_needs_to_be_provided_dbl_infinity() { return __builtin_inf(); } + static constexpr double my_value_that_needs_to_be_provided_dbl_quiet_NaN() { return __builtin_nan(""); } + static constexpr double my_value_that_needs_to_be_provided_dbl_signaling_NaN() { return __builtin_nan(""); } + #endif + #endif + #if defined(__IAR_SYSTEMS_ICC__) + static constexpr double my_value_that_needs_to_be_provided_dbl_infinity() { return 0.Infinity; } + static constexpr double my_value_that_needs_to_be_provided_dbl_quiet_NaN() { return 0.NaN; } + static constexpr double my_value_that_needs_to_be_provided_dbl_signaling_NaN() { return 0.NaN; } + #endif + static constexpr double my_value_that_needs_to_be_provided_dbl_denorm_min() { return DBL_MIN; } + + #if defined(__GNUC__) + static constexpr long double my_value_that_needs_to_be_provided_ldbl_infinity() { return __builtin_infl(); } + static constexpr long double my_value_that_needs_to_be_provided_ldbl_quiet_NaN() { return __builtin_nanl(""); } + static constexpr long double my_value_that_needs_to_be_provided_ldbl_signaling_NaN() { return __builtin_nanl(""); } + #endif + #if defined(__IAR_SYSTEMS_ICC__) + static constexpr long double my_value_that_needs_to_be_provided_ldbl_infinity() { return 0.Infinity; } + static constexpr long double my_value_that_needs_to_be_provided_ldbl_quiet_NaN() { return 0.NaN; } + static constexpr long double my_value_that_needs_to_be_provided_ldbl_signaling_NaN() { return 0.NaN; } + #endif + static constexpr long double my_value_that_needs_to_be_provided_ldbl_denorm_min() { return LDBL_MIN; } template friend class numeric_limits; @@ -80,39 +110,39 @@ class numeric_limits { public: - static const bool is_specialized = false; - static const int digits = 0; - static const int digits10 = 0; - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = false; - static const bool is_exact = false; - static const int radix = 0; - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - static const bool is_iec559 = false; - static const bool is_bounded = false; - static const bool is_modulo = false; - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; - - static T (min)() throw() { return static_cast(0); } - static T (max)() throw() { return static_cast(0); } - static T lowest() throw() { return static_cast(0); } - static T epsilon() throw() { return static_cast(0); } - static T round_error() throw() { return static_cast(0); } - static T infinity() throw() { return static_cast(0); } - static T quiet_NaN() throw() { return static_cast(0); } - static T signaling_NaN() throw() { return static_cast(0); } - static T denorm_min() throw() { return static_cast(0); } + static constexpr bool is_specialized = false; + static constexpr int digits = 0; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr int radix = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = false; + static constexpr bool is_modulo = false; + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + + static constexpr T (min)() throw() { return static_cast(0); } + static constexpr T (max)() throw() { return static_cast(0); } + static constexpr T lowest() throw() { return static_cast(0); } + static constexpr T epsilon() throw() { return static_cast(0); } + static constexpr T round_error() throw() { return static_cast(0); } + static constexpr T infinity() throw() { return static_cast(0); } + static constexpr T quiet_NaN() throw() { return static_cast(0); } + static constexpr T signaling_NaN() throw() { return static_cast(0); } + static constexpr T denorm_min() throw() { return static_cast(0); } }; // Specialization for bool. @@ -120,46 +150,46 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static bool (min)() throw() { return false; } - static bool (max)() throw() { return true; } - static bool lowest() throw() { return (min)(); } - - static const int digits = 1; - static const int digits10 = 0; - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static bool epsilon() throw() { return false; } - static bool round_error() throw() { return false; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static bool infinity() throw() { return false; } - static bool quiet_NaN() throw() { return false; } - static bool signaling_NaN() throw() { return false; } - static bool denorm_min() throw() { return false; } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = false; - - static const bool traps = true; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr bool (min)() throw() { return false; } + static constexpr bool (max)() throw() { return true; } + static constexpr bool lowest() throw() { return (min)(); } + + static constexpr int digits = 1; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr bool epsilon() throw() { return false; } + static constexpr bool round_error() throw() { return false; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr bool infinity() throw() { return false; } + static constexpr bool quiet_NaN() throw() { return false; } + static constexpr bool signaling_NaN() throw() { return false; } + static constexpr bool denorm_min() throw() { return false; } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for char. @@ -167,44 +197,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static char (min)() throw() { return CHAR_MIN; } - static char (max)() throw() { return CHAR_MAX; } - static char lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(char); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(char); - static const int max_digits10 = 0; - static const bool is_signed = CONCEPT_FROM_GLIBCXX_IS_SIGNED(char); - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static char epsilon() throw() { return 0; } - static char round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static char infinity() throw() { return char(); } - static char quiet_NaN() throw() { return char(); } - static char signaling_NaN() throw() { return char(); } - static char denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr char (min)() throw() { return CHAR_MIN; } + static constexpr char (max)() throw() { return CHAR_MAX; } + static constexpr char lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(char); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(char); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = CONCEPT_FROM_GLIBCXX_IS_SIGNED(char); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char epsilon() throw() { return 0; } + static constexpr char round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char infinity() throw() { return char(); } + static constexpr char quiet_NaN() throw() { return char(); } + static constexpr char signaling_NaN() throw() { return char(); } + static constexpr char denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for signed char. @@ -212,45 +242,45 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static signed char (min)() throw() { return -SCHAR_MAX - 1; } - static signed char (max)() throw() { return SCHAR_MAX; } - static signed char lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(signed char); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(signed char); - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static signed char epsilon() throw() { return 0; } - static signed char round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static signed char infinity() throw() { return static_cast(0); } - static signed char quiet_NaN() throw() { return static_cast(0); } - static signed char signaling_NaN() throw() { return static_cast(0); } - static signed char denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr signed char (min)() throw() { return -SCHAR_MAX - 1; } + static constexpr signed char (max)() throw() { return SCHAR_MAX; } + static constexpr signed char lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(signed char); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(signed char); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr signed char epsilon() throw() { return 0; } + static constexpr signed char round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr signed char infinity() throw() { return static_cast(0); } + static constexpr signed char quiet_NaN() throw() { return static_cast(0); } + static constexpr signed char signaling_NaN() throw() { return static_cast(0); } + static constexpr signed char denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for unsigned char. @@ -258,46 +288,46 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static unsigned char (min)() throw() { return 0; } - static unsigned char (max)() throw() { return (SCHAR_MAX * 2U) + 1; } - static unsigned char lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned char); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned char); - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static unsigned char epsilon() throw() { return 0; } - static unsigned char round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static unsigned char infinity() throw() { return static_cast(0); } - static unsigned char quiet_NaN() throw() { return static_cast(0); } - static unsigned char signaling_NaN() throw() { return static_cast(0); } - static unsigned char denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr unsigned char (min)() throw() { return 0; } + static constexpr unsigned char (max)() throw() { return (SCHAR_MAX * 2U) + 1; } + static constexpr unsigned char lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned char); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned char); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr unsigned char epsilon() throw() { return 0; } + static constexpr unsigned char round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr unsigned char infinity() throw() { return static_cast(0); } + static constexpr unsigned char quiet_NaN() throw() { return static_cast(0); } + static constexpr unsigned char signaling_NaN() throw() { return static_cast(0); } + static constexpr unsigned char denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; @@ -306,45 +336,45 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static short (min)() throw() { return -SHRT_MAX - 1; } - static short (max)() throw() { return SHRT_MAX; } - static short lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(short); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(short); - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static short epsilon() throw() { return 0; } - static short round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static short infinity() throw() { return short(); } - static short quiet_NaN() throw() { return short(); } - static short signaling_NaN() throw() { return short(); } - static short denorm_min() throw() { return short(); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr short (min)() throw() { return -SHRT_MAX - 1; } + static constexpr short (max)() throw() { return SHRT_MAX; } + static constexpr short lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(short); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(short); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr short epsilon() throw() { return 0; } + static constexpr short round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr short infinity() throw() { return short(); } + static constexpr short quiet_NaN() throw() { return short(); } + static constexpr short signaling_NaN() throw() { return short(); } + static constexpr short denorm_min() throw() { return short(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for unsigned short. @@ -352,44 +382,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static unsigned short (min)() throw() { return 0; } - static unsigned short (max)() throw() { return (SHRT_MAX * 2U) + 1; } - static unsigned short lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned short); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned short); - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static unsigned short epsilon() throw() { return 0; } - static unsigned short round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static unsigned short infinity() throw() { return static_cast(0); } - static unsigned short quiet_NaN() throw() { return static_cast(0); } - static unsigned short signaling_NaN() throw() { return static_cast(0); } - static unsigned short denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr unsigned short (min)() throw() { return 0; } + static constexpr unsigned short (max)() throw() { return (SHRT_MAX * 2U) + 1; } + static constexpr unsigned short lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned short); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned short); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr unsigned short epsilon() throw() { return 0; } + static constexpr unsigned short round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr unsigned short infinity() throw() { return static_cast(0); } + static constexpr unsigned short quiet_NaN() throw() { return static_cast(0); } + static constexpr unsigned short signaling_NaN() throw() { return static_cast(0); } + static constexpr unsigned short denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for int. @@ -397,44 +427,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static int (min)() throw() { return -INT_MAX - 1; } - static int (max)() throw() { return INT_MAX; } - static int lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(int); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(int); - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static int epsilon() throw() { return 0; } - static int round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static int infinity() throw() { return static_cast(0); } - static int quiet_NaN() throw() { return static_cast(0); } - static int signaling_NaN() throw() { return static_cast(0); } - static int denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr int (min)() throw() { return -INT_MAX - 1; } + static constexpr int (max)() throw() { return INT_MAX; } + static constexpr int lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(int); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(int); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr int epsilon() throw() { return 0; } + static constexpr int round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr int infinity() throw() { return static_cast(0); } + static constexpr int quiet_NaN() throw() { return static_cast(0); } + static constexpr int signaling_NaN() throw() { return static_cast(0); } + static constexpr int denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for unsigned int. @@ -442,45 +472,45 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static unsigned int (min)() throw() { return 0; } - static unsigned int (max)() throw() { return (INT_MAX * 2U) + 1; } - static unsigned int lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned int); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned int); - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static unsigned int epsilon() throw() { return 0; } - static unsigned int round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static unsigned int infinity() throw() { return static_cast(0); } - static unsigned int quiet_NaN() throw() { return static_cast(0); } - static unsigned int signaling_NaN() throw() { return static_cast(0); } - static unsigned int denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr unsigned int (min)() throw() { return 0; } + static constexpr unsigned int (max)() throw() { return (INT_MAX * 2U) + 1; } + static constexpr unsigned int lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned int); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned int); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr unsigned int epsilon() throw() { return 0; } + static constexpr unsigned int round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr unsigned int infinity() throw() { return static_cast(0); } + static constexpr unsigned int quiet_NaN() throw() { return static_cast(0); } + static constexpr unsigned int signaling_NaN() throw() { return static_cast(0); } + static constexpr unsigned int denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for long. @@ -488,44 +518,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static long (min)() throw() { return -LONG_MAX - 1; } - static long (max)() throw() { return LONG_MAX; } - static long lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(long); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(long); - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static long epsilon() throw() { return 0; } - static long round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static long infinity() throw() { return static_cast(0); } - static long quiet_NaN() throw() { return static_cast(0); } - static long signaling_NaN() throw() { return static_cast(0); } - static long denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr long (min)() throw() { return -LONG_MAX - 1; } + static constexpr long (max)() throw() { return LONG_MAX; } + static constexpr long lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(long); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(long); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr long epsilon() throw() { return 0; } + static constexpr long round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr long infinity() throw() { return static_cast(0); } + static constexpr long quiet_NaN() throw() { return static_cast(0); } + static constexpr long signaling_NaN() throw() { return static_cast(0); } + static constexpr long denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for unsigned long. @@ -533,44 +563,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static unsigned long (min)() throw() { return 0; } - static unsigned long (max)() throw() { return (LONG_MAX * 2UL) + 1; } - static unsigned long lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned long); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned long); - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static unsigned long epsilon() throw() { return 0; } - static unsigned long round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static unsigned long infinity() throw() { return static_cast(0); } - static unsigned long quiet_NaN() throw() { return static_cast(0); } - static unsigned long signaling_NaN() throw() { return static_cast(0); } - static unsigned long denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr unsigned long (min)() throw() { return 0; } + static constexpr unsigned long (max)() throw() { return (LONG_MAX * 2UL) + 1; } + static constexpr unsigned long lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned long); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned long); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr unsigned long epsilon() throw() { return 0; } + static constexpr unsigned long round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr unsigned long infinity() throw() { return static_cast(0); } + static constexpr unsigned long quiet_NaN() throw() { return static_cast(0); } + static constexpr unsigned long signaling_NaN() throw() { return static_cast(0); } + static constexpr unsigned long denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for long long. @@ -578,44 +608,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static long long (min)() throw() { return -numeric_limits_details::my_long_long_max - 1; } - static long long (max)() throw() { return numeric_limits_details::my_long_long_max; } - static long long lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(long long); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(long long); - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static long long epsilon() throw() { return 0; } - static long long round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static long long infinity() throw() { return static_cast(0); } - static long long quiet_NaN() throw() { return static_cast(0); } - static long long signaling_NaN() throw() { return static_cast(0); } - static long long denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr long long (min)() throw() { return -numeric_limits_details::my_long_long_max - 1; } + static constexpr long long (max)() throw() { return numeric_limits_details::my_long_long_max; } + static constexpr long long lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(long long); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(long long); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr long long epsilon() throw() { return 0; } + static constexpr long long round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr long long infinity() throw() { return static_cast(0); } + static constexpr long long quiet_NaN() throw() { return static_cast(0); } + static constexpr long long signaling_NaN() throw() { return static_cast(0); } + static constexpr long long denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for unsigned long long. @@ -623,44 +653,44 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static unsigned long long (min)() throw() { return 0; } - static unsigned long long (max)() throw() { return (numeric_limits_details::my_long_long_max * 2ULL) + 1; } - static unsigned long long lowest() throw() { return (min)(); } - - static const int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned long long); - static const int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned long long); - static const int max_digits10 = 0; - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - - static unsigned long long epsilon() throw() { return 0; } - static unsigned long long round_error() throw() { return 0; } - - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - - static unsigned long long infinity() throw() { return static_cast(0); } - static unsigned long long quiet_NaN() throw() { return static_cast(0); } - static unsigned long long signaling_NaN() throw() { return static_cast(0); } - static unsigned long long denorm_min() throw() { return static_cast(0); } - - static const bool is_iec559 = false; - static const bool is_bounded = true; - static const bool is_modulo = true; - static const bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; + static constexpr bool is_specialized = true; + + static constexpr unsigned long long (min)() throw() { return 0; } + static constexpr unsigned long long (max)() throw() { return (numeric_limits_details::my_long_long_max * 2ULL) + 1; } + static constexpr unsigned long long lowest() throw() { return (min)(); } + + static constexpr int digits = CONCEPT_FROM_GLIBCXX_DIGITS(unsigned long long); + static constexpr int digits10 = CONCEPT_FROM_GLIBCXX_DIGITS10(unsigned long long); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr unsigned long long epsilon() throw() { return 0; } + static constexpr unsigned long long round_error() throw() { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr unsigned long long infinity() throw() { return static_cast(0); } + static constexpr unsigned long long quiet_NaN() throw() { return static_cast(0); } + static constexpr unsigned long long signaling_NaN() throw() { return static_cast(0); } + static constexpr unsigned long long denorm_min() throw() { return static_cast(0); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = CONCEPT_FROM_GLIBCXX_INTEGRAL_TRAPS; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; }; // Specialization for float. @@ -668,46 +698,46 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static float (min)() throw() { return FLT_MIN; } - static float (max)() throw() { return FLT_MAX; } - static float lowest() throw() { return -FLT_MAX; } - - static const int digits = FLT_MANT_DIG; - static const int digits10 = FLT_DIG; - static const int max_digits10 = CONCEPT_FROM_GLIBCXX_MAX_DIGITS10(FLT_MANT_DIG); - static const bool is_signed = true; - static const bool is_integer = false; - static const bool is_exact = false; - static const int radix = FLT_RADIX; - - static float epsilon() throw() { return FLT_EPSILON; } - static float round_error() throw() { return 0.5F; } - - static const int min_exponent = FLT_MIN_EXP; - static const int min_exponent10 = FLT_MIN_10_EXP; - static const int max_exponent = FLT_MAX_EXP; - static const int max_exponent10 = FLT_MAX_10_EXP; - - static const bool has_infinity = true; - static const bool has_quiet_NaN = true; - static const bool has_signaling_NaN = false; - static const bool has_denorm = true; - static const bool has_denorm_loss = false; - - static float infinity() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_infinity(); } - static float quiet_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_quiet_NaN(); } - static float signaling_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_signaling_NaN(); } - static float denorm_min() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_denorm_min(); } - - static const bool is_iec559 = true; - static const bool is_bounded = true; - static const bool is_modulo = false; - - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_to_nearest; + static constexpr bool is_specialized = true; + + static constexpr float (min)() throw() { return FLT_MIN; } + static constexpr float (max)() throw() { return FLT_MAX; } + static constexpr float lowest() throw() { return -FLT_MAX; } + + static constexpr int digits = FLT_MANT_DIG; + static constexpr int digits10 = FLT_DIG; + static constexpr int max_digits10 = CONCEPT_FROM_GLIBCXX_MAX_DIGITS10(FLT_MANT_DIG); + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr int radix = FLT_RADIX; + + static constexpr float epsilon() throw() { return FLT_EPSILON; } + static constexpr float round_error() throw() { return 0.5F; } + + static constexpr int min_exponent = FLT_MIN_EXP; + static constexpr int min_exponent10 = FLT_MIN_10_EXP; + static constexpr int max_exponent = FLT_MAX_EXP; + static constexpr int max_exponent10 = FLT_MAX_10_EXP; + + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm = true; + static constexpr bool has_denorm_loss = false; + + static constexpr float infinity() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_infinity(); } + static constexpr float quiet_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_quiet_NaN(); } + static constexpr float signaling_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_signaling_NaN(); } + static constexpr float denorm_min() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_flt_denorm_min(); } + + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_to_nearest; }; // Specialization for double. @@ -715,46 +745,46 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static double (min)() throw() { return DBL_MIN; } - static double (max)() throw() { return DBL_MAX; } - static double lowest() throw() { return -DBL_MAX; } - - static const int digits = DBL_MANT_DIG; - static const int digits10 = DBL_DIG; - static const int max_digits10 = CONCEPT_FROM_GLIBCXX_MAX_DIGITS10(DBL_MANT_DIG); - static const bool is_signed = true; - static const bool is_integer = false; - static const bool is_exact = false; - static const int radix = 2; // DBL_RADIX; - - static double epsilon() throw() { return DBL_EPSILON; } - static double round_error() throw() { return 0.5; } - - static const int min_exponent = DBL_MIN_EXP; - static const int min_exponent10 = DBL_MIN_10_EXP; - static const int max_exponent = DBL_MAX_EXP; - static const int max_exponent10 = DBL_MAX_10_EXP; - - static const bool has_infinity = true; - static const bool has_quiet_NaN = true; - static const bool has_signaling_NaN = false; - static const bool has_denorm = true; - static const bool has_denorm_loss = false; - - static double infinity() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_infinity(); } - static double quiet_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_quiet_NaN(); } - static double signaling_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_signaling_NaN(); } - static double denorm_min() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_denorm_min(); } - - static const bool is_iec559 = true; - static const bool is_bounded = true; - static const bool is_modulo = false; - - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_to_nearest; + static constexpr bool is_specialized = true; + + static constexpr double (min)() throw() { return DBL_MIN; } + static constexpr double (max)() throw() { return DBL_MAX; } + static constexpr double lowest() throw() { return -DBL_MAX; } + + static constexpr int digits = DBL_MANT_DIG; + static constexpr int digits10 = DBL_DIG; + static constexpr int max_digits10 = CONCEPT_FROM_GLIBCXX_MAX_DIGITS10(DBL_MANT_DIG); + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr int radix = 2; // DBL_RADIX; + + static constexpr double epsilon() throw() { return DBL_EPSILON; } + static constexpr double round_error() throw() { return 0.5; } + + static constexpr int min_exponent = DBL_MIN_EXP; + static constexpr int min_exponent10 = DBL_MIN_10_EXP; + static constexpr int max_exponent = DBL_MAX_EXP; + static constexpr int max_exponent10 = DBL_MAX_10_EXP; + + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm = true; + static constexpr bool has_denorm_loss = false; + + static constexpr double infinity() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_infinity(); } + static constexpr double quiet_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_quiet_NaN(); } + static constexpr double signaling_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_signaling_NaN(); } + static constexpr double denorm_min() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_dbl_denorm_min(); } + + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_to_nearest; }; // Specialization for long double. @@ -762,47 +792,50 @@ class numeric_limits { public: - static const bool is_specialized = true; - - static long double (min)() throw() { return LDBL_MIN; } - static long double (max)() throw() { return LDBL_MAX; } - static long double lowest() throw() { return -LDBL_MAX; } - - static const int digits = LDBL_MANT_DIG; - static const int digits10 = LDBL_DIG; - static const int max_digits10 = CONCEPT_FROM_GLIBCXX_MAX_DIGITS10(LDBL_MANT_DIG); - static const bool is_signed = true; - static const bool is_integer = false; - static const bool is_exact = false; - static const int radix = 2; // DBL_RADIX; - - static long double epsilon() throw() { return LDBL_EPSILON; } - static long double round_error() throw() { return 0.5; } - - static const int min_exponent = LDBL_MIN_EXP; - static const int min_exponent10 = LDBL_MIN_10_EXP; - static const int max_exponent = LDBL_MAX_EXP; - static const int max_exponent10 = LDBL_MAX_10_EXP; - - static const bool has_infinity = true; - static const bool has_quiet_NaN = true; - static const bool has_signaling_NaN = false; - static const bool has_denorm = true; - static const bool has_denorm_loss = false; - - static long double infinity() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_infinity(); } - static long double quiet_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_quiet_NaN(); } - static long double signaling_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_signaling_NaN(); } - static long double denorm_min() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_denorm_min(); } - - static const bool is_iec559 = true; - static const bool is_bounded = true; - static const bool is_modulo = false; - - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_to_nearest; + static constexpr bool is_specialized = true; + + static constexpr long double (min)() throw() { return LDBL_MIN; } + static constexpr long double (max)() throw() { return LDBL_MAX; } + static constexpr long double lowest() throw() { return -LDBL_MAX; } + + static constexpr int digits = LDBL_MANT_DIG; + static constexpr int digits10 = LDBL_DIG; + static constexpr int max_digits10 = CONCEPT_FROM_GLIBCXX_MAX_DIGITS10(LDBL_MANT_DIG); + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr int radix = 2; // DBL_RADIX; + + static constexpr long double epsilon() throw() { return LDBL_EPSILON; } + static constexpr long double round_error() throw() { return 0.5; } + + static constexpr int min_exponent = LDBL_MIN_EXP; + static constexpr int min_exponent10 = LDBL_MIN_10_EXP; + static constexpr int max_exponent = LDBL_MAX_EXP; + static constexpr int max_exponent10 = LDBL_MAX_10_EXP; + + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm = true; + static constexpr bool has_denorm_loss = false; + + static constexpr long double infinity() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_infinity(); } + static constexpr long double quiet_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_quiet_NaN(); } + static constexpr long double signaling_NaN() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_signaling_NaN(); } + static constexpr long double denorm_min() throw() { return numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_denorm_min(); } + + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_to_nearest; }; } + #if defined(__GNUC__) && defined(__XTENSA__) + } + #endif #endif // LIMITS_2010_02_23_ diff --git a/examples/chapter04_04/src/util/STL/memory b/examples/chapter04_04/src/util/STL/memory index 9167b70b9..92bf3cb6f 100644 --- a/examples/chapter04_04/src/util/STL/memory +++ b/examples/chapter04_04/src/util/STL/memory @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,21 +8,12 @@ #ifndef MEMORY_2010_02_23_ #define MEMORY_2010_02_23_ - #include - #include - #include #include - #if defined(_MSC_VER) - #define STL_LOCAL_ALIGNAS(n) - #else - #define STL_LOCAL_ALIGNAS(n) alignas(n) - #endif - // Provide the default placement versions of operator new. - inline void* operator new (size_t, void* my_p) STL_LOCAL_NOEXCEPT { return my_p; } - inline void* operator new[](size_t, void* my_p) STL_LOCAL_NOEXCEPT { return my_p; } + inline void* operator new (size_t, void* my_p) noexcept { return my_p; } + inline void* operator new[](size_t, void* my_p) noexcept { return my_p; } // Implement the standard allocator (std::allocator). namespace std @@ -41,7 +32,7 @@ allocator_base(const allocator_base&) throw() { } // The allocator's default buffer size. - static STL_LOCAL_CONSTEXPR size_type buffer_size = 64U; + static constexpr size_type buffer_size = 64U; // The allocator's buffer type. struct buffer_type @@ -50,10 +41,9 @@ }; // The allocator's memory allocation. - template static void* do_allocate(const size_type size) { - STL_LOCAL_ALIGNAS(8) static buffer_type buffer; + alignas(8) static buffer_type buffer; static std::uint8_t* get_ptr = buffer.data; @@ -62,8 +52,7 @@ // Increment the get-pointer for the next allocation. // Be sure to handle the inner-buffer alignment. - const std::uint_fast8_t align_increment = inner_buffer_alignment - std::uint_fast8_t(size % inner_buffer_alignment); - const size_type buffer_increment = size + align_increment; + const size_type buffer_increment = size; get_ptr += buffer_increment; @@ -118,12 +107,11 @@ return false; } - template + template class allocator; - template - class allocator : public allocator_base + template<> + class allocator : public allocator_base { public: typedef void value_type; @@ -131,20 +119,16 @@ typedef const value_type* const_pointer; template - struct rebind { typedef allocator other; }; + struct rebind { typedef allocator other; }; }; - template + template class allocator : public allocator_base { public: static_assert(sizeof(T) <= buffer_size, "The size of the allocation object can not exceed the buffer size."); - static_assert(inner_buffer_alignment <= buffer_size, - "The granularity of the inner-buffer alignment can not exceed the buffer size."); - typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; @@ -156,10 +140,10 @@ allocator(const allocator&) throw() : allocator_base(allocator()) { } template - allocator(const allocator&) throw() { } + allocator(const allocator&) throw() { } template - struct rebind { typedef allocator other; }; + struct rebind { typedef allocator other; }; size_type max_size() const throw() { @@ -170,11 +154,11 @@ const_pointer address(const_reference x) const { return &x; } pointer allocate(size_type count, - typename allocator::const_pointer = nullptr) + typename allocator::const_pointer = nullptr) { const size_type chunk_size = count * sizeof(value_type); - void* p = do_allocate(chunk_size); + void* p = do_allocate(chunk_size); return static_cast(p); } @@ -227,6 +211,69 @@ { return detail::addressof_impl::f(detail::addr_impl_ref(v), 0); } + + #if 0 + template + struct allocator_traits + { + public: + using allocator_type = AllocatorType; + using value_type = typename AllocatorType::value_type; + using pointer = value_type*; + using const_pointer = const value_type*; + using void_pointer = void*; + using const_void_pointer = const void*; + using difference_type = std::ptrdiff_t; + using size_type = std::size_t; + + template + struct rebind_alloc + { + using type = typename allocator_type::template rebind::other; + }; + + //struct rebind_alloc + //{ + // using type = value_type; + //}; + + static pointer allocate(allocator_type& a, size_type n) + { + return a.allocate(n); + } + + static pointer allocate(allocator_type& a, size_type n, const_void_pointer hint) + { + return my_allocate(a, n, hint, 0); + } + + template + static void construct(allocator_type& a, OtherValueType* p, const OtherValueType& x) + { + a.construct(p, x); + } + + template + static void destroy(allocator_type& a, OtherValueType* p) + { + a.destroy(p); + } + + static void deallocate(allocator_type& a, pointer p, size_type n) + { + a.deallocate(p, n); + } + + private: + template + static typename OtherAllocatorType::pointer my_allocate(OtherAllocatorType& a, size_type n, const_void_pointer hint, int) + { + return a.allocate(n, hint); + } + }; + #endif } + #include + #endif // MEMORY_2010_02_23_ diff --git a/examples/chapter04_04/src/util/STL/random b/examples/chapter04_04/src/util/STL/random index a47cfc6b6..2c370b07e 100644 --- a/examples/chapter04_04/src/util/STL/random +++ b/examples/chapter04_04/src/util/STL/random @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2018 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -11,162 +11,1709 @@ #include #include #include - #include - #include + #include + #include + #include - /* - Portions of . The following portions will be included: + // Implement some of for compilers that do not yet support it. - linear_congruential_engine - mersenne_twister_engine - subtract_with_carry_engine - discard_block_engine - independent_bits_engine - shuffle_order_engine - [rand.predef] - uniform_int_distribution - */ + extern "C" unsigned int my_hardware_random_device_generator(void); + extern "C" unsigned char my_hardware_random_device_entropy (void); - namespace std + namespace std { + + namespace rnd__detail { + + template(std::numeric_limits::digits)> + struct rnd__shift + { + static const UnsignedIntegralType rnd__value = 0U; + }; + + template + struct rnd__shift + { + static const UnsignedIntegralType rnd__value = UnsignedIntegralType(1ULL << rnd__word_size); + }; + + template + struct rnd__select_uint_least_t + { + static_assert(rnd__which < 0, "Error: would be too much trouble for a slow result"); + }; + + template + struct rnd__select_uint_least_t + { + typedef unsigned int type; + }; + + template + struct rnd__select_uint_least_t { - class seed_seq + typedef unsigned long type; + }; + + template + struct rnd__select_uint_least_t + { + typedef unsigned long long type; + }; + + // Assume a != 0, a < m, c < m, x < m. + template= ParamM - 1), + bool rnd__schrage_ok = ParamM % ParamA < ParamM / ParamA> + struct rnd__inner_mod + { + typedef T _Tp2; + static T + + rnd__calc(T rnd__x) { - public: - using result_type = uint_least32_t; + return static_cast((_Tp2(ParamA) * rnd__x + ParamC) % ParamM); + } + }; - seed_seq() : internal_sequence() { } + // Schrage. + template + struct rnd__inner_mod + { + // General case for x = (ax + c) mod m -- use Schrage's algorithm + // to avoid integer overflow. + // + // Preconditions: a > 0, m > 0. + // + // Note: only works correctly for ParamM % ParamA < ParamM / ParamA. + static T rnd__calc(T rnd__x) + { + if (ParamA == 1) + { + rnd__x %= ParamM; + } + else + { + constexpr T rnd__seed_sequence = ParamM / ParamA; + constexpr T rnd__long_lag_r = ParamM % ParamA; - template - seed_seq(const std::initializer_list& init_list) - : internal_sequence(init_list.begin(), init_list.end()) { } + T rnd__t1 = ParamA * (rnd__x % rnd__seed_sequence); + T rnd__t2 = rnd__long_lag_r * (rnd__x / rnd__seed_sequence); - template - seed_seq(input_iterator_type first, input_iterator_type last) - : internal_sequence(first, last) { } + if (rnd__t1 >= rnd__t2) + { + rnd__x = rnd__t1 - rnd__t2; + } + else + { + rnd__x = ParamM - rnd__t2 + rnd__t1; + } + } - template - void generate(random_iterator_type first, random_iterator_type last) const + if(ParamC != 0) { - typedef typename std::iterator_traits::value_type value_type; + const T rnd__value_d = ParamM - rnd__x; - std::fill(first, last, static_cast(0x8B8B8B8BU)); + if (rnd__value_d > ParamC) + { + rnd__x += ParamC; + } + else + { + rnd__x = ParamC - rnd__value_d; + } + } - std::size_t s = internal_sequence.size(); + return rnd__x; + } + }; - std::size_t n = last - first; + // Special cases: + // - for m == 2^n or m == 0, unsigned integer overflow is safe. + // - a * (m - 1) + c fits in T, there is no overflow. + template + struct rnd__inner_mod + { + static T rnd__calc(T rnd__x) + { + T rnd__res = ParamA * rnd__x + ParamC; - std::size_t t = (n >= 623) ? 11 : - (n >= 68) ? 7 : - (n >= 39) ? 5 : - (n >= 7) ? 3 : - (n - 1)/2; + if (ParamM) + { + rnd__res %= ParamM; + } - std::size_t p = (n - t) / 2; - std::size_t q = p + t; - std::size_t m = (std::max)(s + 1, n); + return rnd__res; + } + }; - value_type mask = 0xFFFFFFFFU; - for(std::size_t k = 0; k < m; ++k) - { - value_type r1(*(first + (k % n)) ^ *(first + ((k + p) % n)) ^ *(first + (((k + n) - 1) % n))); + template + inline T rnd__mod(T rnd__x) + { + return rnd__inner_mod::rnd__calc(rnd__x); + } + + template + OutputIterator rnd__normalize(InputIterator rnd__first, + InputIterator rnd__last, + OutputIterator rnd__result, + const T& rnd__factor) + { + for( ; rnd__first != rnd__last; ++rnd__first, ++rnd__result) + { + *rnd__result = *rnd__first / rnd__factor; + } - r1 = r1 ^ (r1 >> 27); - r1 = (r1 * 1664525U) & mask; + return rnd__result; + } - value_type r2(r1 + ((k == 0) ? s : - (k <= s) ? k % n + internal_sequence[k - 1] : - (k % n))); + } } // namespace std::rnd__detail - *(first + ((k + p) % n)) = (*(first + ((k + p) % n)) + r1) & mask; - *(first + ((k + q) % n)) = (*(first + ((k + q) % n)) + r2) & mask; - *(first + (k % n)) = r2; - } + namespace std { - for(std::size_t k = m; k < m + n; ++k) - { - value_type r3((*(first + (k % n)) + *(first + ((k + p) % n)) + *(first + (k+n-1)%n)) & mask); + // These classes define objects which provide random + // or pseudorandom numbers, either from a discrete or + // a continuous interval. + + // Generate pseudorandom numbers via linear function + // x_{i+1} -> (ax_{i} + c) % m + // + // The template parameter UnsignedIntegralType must be an unsigned + // integral type large enough to store values up to (ParamM-1). + // If the template parameter ParamM is 0, the modulus ParamM used is + // std::numeric_limits::max() + 1. Otherwise, + // the template parameters ParamA and ParamC must be less than ParamM. - r3 = r3 ^ (r3 >> 27); - r3 = (r3 * 1566083941U) & mask; + template + class linear_congruential_engine + { + private: + static_assert(std::is_unsigned::value, + "Error: result_type must be an unsigned integral type"); - value_type r4 = static_cast(r3 - (k % n)); + static_assert(ParamM == 0u || (ParamA < ParamM && ParamC < ParamM), + "Error: template argument substituting ParamM out of bounds"); - *(first + ((k + p) % n)) ^= r3; - *(first + ((k + q) % n)) ^= r4; - *(first + (k % n)) = r4; - } + public: + typedef UnsignedIntegralType result_type; + + static const result_type multiplier = ParamA; + static const result_type increment = ParamC; + static const result_type modulus = ParamM; + static const result_type default_seed = 1U; + + explicit linear_congruential_engine(result_type rnd__seed = default_seed) + { + seed(rnd__seed); + } + + template::value>::type> + explicit linear_congruential_engine(_Sseq& rnd__seed_sequence) + { + seed(rnd__seed_sequence); + } + + void seed(result_type rnd__seed = default_seed); + + static constexpr result_type min() + { + return ParamC == 0u ? 1u : 0u; + } + + static constexpr result_type max() + { + return ParamM - 1u; + } + + void discard(unsigned long long rnd__z) + { + for( ; rnd__z != 0ULL; --rnd__z) + { + (*this)(); + } + } + + result_type operator()() + { + my_elems = rnd__detail::rnd__mod(my_elems); + + return my_elems; + } + + friend bool operator==(const linear_congruential_engine& left, + const linear_congruential_engine& right) + { + return (left.my_elems == right.my_elems); + } + + private: + UnsignedIntegralType my_elems; + }; + + template + inline bool operator!=(const std::linear_congruential_engine& left, + const std::linear_congruential_engine& right) + { + return !(left == right); + } + + // A generalized feedback shift register discrete random number generator. + // + // This algorithm avoids multiplication and division and is designed to be + // friendly to a pipelined architecture. If the parameters are chosen + // correctly, this generator will produce numbers with a very long period and + // fairly good apparent entropy, although still not cryptographically strong. + // + // The best way to use this generator is with the predefined mt19937 class. + // + // This algorithm was originally invented by Makoto Matsumoto and + // Takuji Nishimura. + // + // rnd__word_size Word size, the number of bits in each element of + // the state vector. + // ParamN The degree of recursion. + // ParamM The period parameter. + // rnd__long_lag_r The separation point bit index. + // ParamA The last row of the twist matrix. + // ParamU The first right-shift tempering matrix parameter. + // rnd__value_d The first right-shift tempering matrix mask. + // rnd__seed The first left-shift tempering matrix parameter. + // rnd__value_b The first left-shift tempering matrix mask. + // ParamT The second left-shift tempering matrix parameter. + // ParamC The second left-shift tempering matrix mask. + // ParamL The second right-shift tempering matrix parameter. + // rnd__value_f Initialization multiplier. + + template + class mersenne_twister_engine + { + private: + static_assert(std::is_unsigned::value, + "result_type must be an unsigned integral type"); + + static_assert(1u <= ParamM && ParamM <= ParamN, + "template argument substituting ParamM out of bounds"); + + static_assert(rnd__long_lag_r <= rnd__word_size, "template argument substituting rnd__long_lag_r out of bound"); + static_assert(ParamU <= rnd__word_size, "template argument substituting ParamU out of bound"); + static_assert(rnd__seed <= rnd__word_size, "template argument substituting rnd__seed out of bound"); + static_assert(ParamT <= rnd__word_size, "template argument substituting ParamT out of bound"); + static_assert(ParamL <= rnd__word_size, "template argument substituting ParamL out of bound"); + static_assert(rnd__word_size <= std::numeric_limits::digits, + "template argument substituting rnd__word_size out of bound"); + static_assert(ParamA <= (rnd__detail::rnd__shift::rnd__value - 1), + "template argument substituting ParamA out of bound"); + static_assert(rnd__value_b <= (rnd__detail::rnd__shift::rnd__value - 1), + "template argument substituting rnd__value_b out of bound"); + static_assert(ParamC <= (rnd__detail::rnd__shift::rnd__value - 1), + "template argument substituting ParamC out of bound"); + static_assert(rnd__value_d <= (rnd__detail::rnd__shift::rnd__value - 1), + "template argument substituting rnd__value_d out of bound"); + static_assert(rnd__value_f <= (rnd__detail::rnd__shift::rnd__value - 1), + "template argument substituting rnd__value_f out of bound"); + + public: + typedef UnsignedIntegralType result_type; + + static const size_t word_size = rnd__word_size; + static const size_t state_size = ParamN; + static const size_t shift_size = ParamM; + static const size_t mask_bits = rnd__long_lag_r; + static const result_type xor_mask = ParamA; + static const size_t tempering_u = ParamU; + static const result_type tempering_d = rnd__value_d; + static const size_t tempering_s = rnd__seed; + static const result_type tempering_b = rnd__value_b; + static const size_t tempering_t = ParamT; + static const result_type tempering_c = ParamC; + static const size_t tempering_l = ParamL; + static const result_type initialization_multiplier = rnd__value_f; + static const result_type default_seed = 5489u; + + // constructors and member function + explicit mersenne_twister_engine(result_type rnd__s = default_seed) + { + seed(rnd__s); + } + + template::value>::type> + explicit mersenne_twister_engine(_Sseq& rnd__seed_sequence) + { + seed(rnd__seed_sequence); + } + + void seed(result_type __sd = default_seed); + + static constexpr result_type min() + { + return 0; + } + + static constexpr result_type max() + { + return rnd__detail::rnd__shift::rnd__value - 1; + } + + void discard(unsigned long long rnd__z); + + result_type operator()(); + + friend bool operator==(const mersenne_twister_engine& left, + const mersenne_twister_engine& right) + { + return ( std::equal(left.my_elems, left.my_elems + state_size, right.my_elems) + && left.my_p == right.my_p); + } + + private: + UnsignedIntegralType my_elems[state_size]; + size_t my_p; + + void rnd__m_gen_rand(); + }; + + template + inline bool operator!=(const std::mersenne_twister_engine& left, + const std::mersenne_twister_engine& right) + { + return !(left == right); + } + + // Marsaglia-Zaman generator. + // + // This is a model of a Generalized Fibonacci discrete random number + // generator, sometimes referred to as the SWC generator. + // + // A discrete random number generator that produces pseudorandom + // numbers using: + // x_{i} -> (x_{i - s} - x_{i - r} - carry_{i-1}) % m + // + + template + class subtract_with_carry_engine + { + private: + static_assert(std::is_unsigned::value, + "result_type must be an unsigned integral type"); + + static_assert(0u < rnd__seed && rnd__seed < rnd__long_lag_r, "0 < s < r"); + + static_assert(0u < rnd__word_size && rnd__word_size <= std::numeric_limits::digits, + "template argument substituting rnd__word_size out of bounds"); + + public: + typedef UnsignedIntegralType result_type; + + // parameter values + static const size_t word_size = rnd__word_size; + static const size_t short_lag = rnd__seed; + static const size_t long_lag = rnd__long_lag_r; + static const result_type default_seed = (result_type) 19780503ULL; + + explicit subtract_with_carry_engine(result_type __sd = default_seed) + { + seed(__sd); + } + + template::value>::type> + explicit subtract_with_carry_engine(_Sseq& rnd__seed_sequence) + { + seed(rnd__seed_sequence); + } + + void seed(result_type rnd__s = default_seed); + + static constexpr result_type min() { return 0; } + + static constexpr result_type max() + { + return rnd__detail::rnd__shift::rnd__value - 1; + } + + result_type operator()() + { + // Derive short lag index from current index. + std::int32_t rnd__ps = (std::int32_t) my_p - (std::int32_t) short_lag; + + if(rnd__ps < 0) + { + rnd__ps += (std::int32_t) long_lag; + } + + // Calculate new x(i) without overflow or division. + // NB: Thanks to the requirements for UnsignedIntegralType, rnd__elems[rnd__m_p] + rnd__m_carry + // cannot overflow. + UnsignedIntegralType rnd__xi; + + if(my_elems[rnd__ps] >= my_elems[my_p] + my_carry) + { + rnd__xi = my_elems[rnd__ps] - my_elems[my_p] - my_carry; + + my_carry = 0; + } + else + { + rnd__xi = (rnd__detail::rnd__shift::rnd__value - my_elems[my_p] - my_carry + my_elems[rnd__ps]); + + my_carry = 1; + } + + my_elems[my_p] = rnd__xi; + + // Adjust current index to loop around in ring buffer. + if (++my_p >= long_lag) + { + my_p = 0; } - template - void param(output_iterator_type destination) const + return rnd__xi; + } + + void discard(unsigned long long rnd__z) + { + for (; rnd__z != 0ULL; --rnd__z) { - static_cast(destination); + (*this)(); } + } + + friend inline bool operator==(const subtract_with_carry_engine& left, + const subtract_with_carry_engine& right) + { + return ( std::equal(left.my_elems, left.my_elems + long_lag, right.my_elems) + && left.my_carry == right.my_carry + && left.my_p == right.my_p); + } + + private: + UnsignedIntegralType my_elems[long_lag]; + UnsignedIntegralType my_carry; + size_t my_p; + }; + + template + inline bool operator!=(const std::subtract_with_carry_engine& left, + const std::subtract_with_carry_engine& right) + { + return !(left == right); + } + + + // Produces random numbers from some base engine + // by discarding blocks of data. + + template + class discard_block_engine + { + private: + static_assert(1 <= rnd__long_lag_r && rnd__long_lag_r <= rnd__p, + "template argument substituting rnd__long_lag_r out of bounds"); + + public: + typedef typename _RandomNumberEngine::result_type result_type; + + static const size_t block_size = rnd__p; + static const size_t used_block = rnd__long_lag_r; + + discard_block_engine() : my_b(), my_n(0) { } + + explicit discard_block_engine(const _RandomNumberEngine& rnd__eng) + : my_b(rnd__eng), + my_n(0) { } + + explicit discard_block_engine(_RandomNumberEngine&& rnd__eng) + : my_b(std::move(rnd__eng)), + my_n(0) { } + + explicit discard_block_engine(result_type rnd__seed) + : my_b(rnd__seed), + my_n(0) { } + + template::value + && !std::is_same<_Sseq, _RandomNumberEngine >::value)>::type> + explicit discard_block_engine(_Sseq& rnd__seed_sequence) + : my_b(rnd__seed_sequence), + my_n(0) { } + + void seed() + { + my_b.seed(); + my_n = 0; + } + + void seed(result_type rnd__seed) + { + my_b.seed(rnd__seed); + my_n = 0; + } + + template + void seed(_Sseq& rnd__seed_sequence) + { + my_b.seed(rnd__seed_sequence); + my_n = 0; + } + + const _RandomNumberEngine& base() const noexcept + { + return my_b; + } + + static constexpr result_type min() + { + return _RandomNumberEngine::min(); + } + + static constexpr result_type max() + { + return _RandomNumberEngine::max(); + } - size_t size() const { return internal_sequence.size(); } - - seed_seq(const seed_seq&) = delete; - void operator=(const seed_seq&) = delete; - - private: - std::vector internal_sequence; - }; - - template - class mersenne_twister_engine - { - public: - using result_type = unsigned_integral_type; - - static const result_type default_seed = 0U; - - explicit mersenne_twister_engine(result_type val = default_seed) + void discard(unsigned long long rnd__z) + { + for( ; rnd__z != 0ULL; --rnd__z) { + (*this)(); } + } + + result_type operator()(); + + friend bool operator==(const discard_block_engine& left, + const discard_block_engine& right) + { + return left.my_b == right.my_b + && left.my_n == right.my_n; + } + + private: + _RandomNumberEngine my_b; + size_t my_n; + }; + + template + inline bool operator!=(const std::discard_block_engine<_RandomNumberEngine, + rnd__p, + rnd__long_lag_r>& left, + const std::discard_block_engine<_RandomNumberEngine, + rnd__p, + rnd__long_lag_r>& right) + { + return !(left == right); + } + + + // Produces random numbers by combining random numbers + // from some base engine to produce random numbers + // with a specifies number of bits rnd__k. + + template + class shuffle_order_engine + { + private: + static_assert(1u <= rnd__k, "template argument substituting " + "rnd__k out of bound"); + + public: + typedef typename _RandomNumberEngine::result_type result_type; + + static const size_t table_size = rnd__k; + + shuffle_order_engine() : rnd__m_b() + { + rnd__m_initialize(); + } + + explicit shuffle_order_engine(const _RandomNumberEngine& rnd__eng) + : rnd__m_b(rnd__eng) + { + rnd__m_initialize(); + } + + explicit shuffle_order_engine(_RandomNumberEngine&& rnd__eng) + : rnd__m_b(std::move(rnd__eng)) + { + rnd__m_initialize(); + } + + explicit shuffle_order_engine(result_type rnd__seed) + : rnd__m_b(rnd__seed) + { + rnd__m_initialize(); + } + + template::value + && !std::is_same<_Sseq, _RandomNumberEngine >::value)>::type> + explicit shuffle_order_engine(_Sseq& rnd__seed_sequence) + : rnd__m_b(rnd__seed_sequence) + { + rnd__m_initialize(); + } + + void seed() + { + rnd__m_b.seed(); + + rnd__m_initialize(); + } + + void seed(result_type rnd__seed) + { + rnd__m_b.seed(rnd__seed); + + rnd__m_initialize(); + } + + template + void seed(_Sseq& rnd__seed_sequence) + { + rnd__m_b.seed(rnd__seed_sequence); + + rnd__m_initialize(); + } + + const _RandomNumberEngine& base() const noexcept + { + return rnd__m_b; + } + + static constexpr result_type min() + { + return _RandomNumberEngine::min(); + } + + static constexpr result_type max() + { + return _RandomNumberEngine::max(); + } - template - explicit mersenne_twister_engine(seed_sequence_type& q) + void discard(unsigned long long rnd__z) + { + for(; rnd__z != 0ULL; --rnd__z) { + (*this)(); } + } + + result_type operator()(); - void seed(result_type val = default_seed) + friend bool operator==(const shuffle_order_engine& left, + const shuffle_order_engine& right) + { + return ( left.rnd__m_b == right.rnd__m_b + && std::equal(left.rnd__m_v, left.rnd__m_v + rnd__k, right.rnd__m_v) + && left.rnd__m_y == right.rnd__m_y); + } + + private: + void rnd__m_initialize() + { + for(size_t rnd__i = 0; rnd__i < rnd__k; ++rnd__i) { + rnd__m_v[rnd__i] = rnd__m_b(); } - template - void seed(seed_sequence_type& q) + rnd__m_y = rnd__m_b(); + } + + _RandomNumberEngine rnd__m_b; + result_type rnd__m_v[rnd__k]; + result_type rnd__m_y; + }; + + template + inline bool operator!=(const std::shuffle_order_engine<_RandomNumberEngine, rnd__k>& left, + const std::shuffle_order_engine<_RandomNumberEngine, rnd__k>& right) + { + return !(left == right); + } + + template + const UnsignedIntegralType linear_congruential_engine::multiplier; + + template + const UnsignedIntegralType linear_congruential_engine::increment; + + template + const UnsignedIntegralType linear_congruential_engine::modulus; + + template + const UnsignedIntegralType linear_congruential_engine::default_seed; + + template + void linear_congruential_engine::seed(result_type rnd__seed) + { + if(( (rnd__detail::rnd__mod(ParamC) == 0) + && (rnd__detail::rnd__mod(rnd__seed) == 0))) + { + my_elems = 1; + } + else + { + my_elems = rnd__detail::rnd__mod(rnd__seed); + } + } + + template + const size_t mersenne_twister_engine::word_size; + + template + const size_t mersenne_twister_engine::state_size; + + template + const size_t mersenne_twister_engine::shift_size; + + template + const size_t mersenne_twister_engine::mask_bits; + + template + const UnsignedIntegralType mersenne_twister_engine::xor_mask; + + template + const size_t mersenne_twister_engine::tempering_u; + +template + const UnsignedIntegralType mersenne_twister_engine::tempering_d; + + template + const size_t mersenne_twister_engine::tempering_s; + +template + const UnsignedIntegralType mersenne_twister_engine::tempering_b; + + template + const size_t mersenne_twister_engine::tempering_t; + +template + const UnsignedIntegralType mersenne_twister_engine::tempering_c; + + template + const size_t mersenne_twister_engine::tempering_l; + +template + const UnsignedIntegralType mersenne_twister_engine::initialization_multiplier; + + template + const UnsignedIntegralType mersenne_twister_engine::default_seed; + + template + void mersenne_twister_engine::seed(result_type __sd) + { + my_elems[0] = rnd__detail::rnd__mod::rnd__value>(__sd); + + for (size_t rnd__i = 1; rnd__i < state_size; ++rnd__i) + { + UnsignedIntegralType rnd__x = my_elems[rnd__i - 1]; + + rnd__x ^= rnd__x >> (rnd__word_size - 2); + rnd__x *= rnd__value_f; + rnd__x += rnd__detail::rnd__mod(rnd__i); + + my_elems[rnd__i] = rnd__detail::rnd__mod::rnd__value>(rnd__x); + } + + my_p = state_size; + } + + template + void mersenne_twister_engine::rnd__m_gen_rand(void) + { + const UnsignedIntegralType __upper_mask = (~UnsignedIntegralType()) << rnd__long_lag_r; + const UnsignedIntegralType __lower_mask = ~__upper_mask; + + for(size_t rnd__k = 0; rnd__k < (ParamN - ParamM); ++rnd__k) + { + UnsignedIntegralType rnd__y = ((my_elems[rnd__k] & __upper_mask) | (my_elems[rnd__k + 1] & __lower_mask)); + + my_elems[rnd__k] = (my_elems[rnd__k + ParamM] ^ (rnd__y >> 1) ^ ((rnd__y & 0x01) ? ParamA : 0)); + } + + for (size_t rnd__k = (ParamN - ParamM); rnd__k < (ParamN - 1); ++rnd__k) + { + UnsignedIntegralType rnd__y = ((my_elems[rnd__k] & __upper_mask) | (my_elems[rnd__k + 1] & __lower_mask)); + + my_elems[rnd__k] = (my_elems[rnd__k + (ParamM - ParamN)] ^ (rnd__y >> 1) ^ ((rnd__y & 0x01) ? ParamA : 0)); + } + + UnsignedIntegralType rnd__y = ((my_elems[ParamN - 1] & __upper_mask) | (my_elems[0] & __lower_mask)); + + my_elems[ParamN - 1] = (my_elems[ParamM - 1] ^ (rnd__y >> 1) ^ ((rnd__y & 0x01) ? ParamA : 0)); + + my_p = 0; + } + + template + void mersenne_twister_engine::discard(unsigned long long rnd__z) + { + while(rnd__z > state_size - my_p) + { + rnd__z -= state_size - my_p; + rnd__m_gen_rand(); + } + + my_p += rnd__z; + } + + template + typename mersenne_twister_engine::result_type + mersenne_twister_engine::operator()() + { + if (my_p >= state_size) + { + rnd__m_gen_rand(); + } + + result_type rnd__z = my_elems[my_p++]; + + rnd__z ^= (rnd__z >> ParamU) & rnd__value_d; + rnd__z ^= (rnd__z << rnd__seed) & rnd__value_b; + rnd__z ^= (rnd__z << ParamT) & ParamC; + rnd__z ^= (rnd__z >> ParamL); + + return rnd__z; + } + + template + const size_t subtract_with_carry_engine::word_size; + + template + const size_t subtract_with_carry_engine::short_lag; + + template + const size_t subtract_with_carry_engine::long_lag; + + template + const UnsignedIntegralType subtract_with_carry_engine::default_seed; + + template + void subtract_with_carry_engine::seed(result_type rnd__value) + { + std::linear_congruential_engine + + __lcg(rnd__value == 0u ? default_seed : rnd__value); + + const size_t ParamN = (rnd__word_size + 31) / 32; + + for (size_t rnd__i = 0; rnd__i < long_lag; ++rnd__i) + { + UnsignedIntegralType rnd__sum = 0u; + UnsignedIntegralType rnd__factor = 1u; + + for(size_t rnd__j = 0; rnd__j < ParamN; ++rnd__j) { + rnd__sum += rnd__detail::rnd__mod::rnd__value>(__lcg()) * rnd__factor; + + rnd__factor *= rnd__detail::rnd__shift::rnd__value; } - }; - - typedef mersenne_twister_engine - mt19937; + + my_elems[rnd__i] = + rnd__detail::rnd__mod::rnd__value>(rnd__sum); + } + + my_carry = (my_elems[long_lag - 1] == 0) ? 1 : 0; + my_p = 0; + } + + template + const size_t discard_block_engine<_RandomNumberEngine, + rnd__p, + rnd__long_lag_r>::block_size; + + template + const size_t discard_block_engine<_RandomNumberEngine, + rnd__p, + rnd__long_lag_r>::used_block; + + template + typename discard_block_engine<_RandomNumberEngine, + rnd__p, + rnd__long_lag_r>::result_type + discard_block_engine<_RandomNumberEngine, rnd__p, rnd__long_lag_r>::operator()() + { + if (my_n >= used_block) + { + my_b.discard(block_size - my_n); + my_n = 0; + } + + ++my_n; + + return my_b(); + } + + template + const size_t shuffle_order_engine<_RandomNumberEngine, rnd__k>::table_size; + + template + typename shuffle_order_engine<_RandomNumberEngine, rnd__k>::result_type + shuffle_order_engine<_RandomNumberEngine, rnd__k>::operator()() + { + size_t rnd__j = rnd__k * ((rnd__m_y - rnd__m_b.min()) / (rnd__m_b.max() - rnd__m_b.min() + 1.0L)); + + rnd__m_y = rnd__m_v[rnd__j]; + rnd__m_v[rnd__j] = rnd__m_b(); + + return rnd__m_y; } + // The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. + typedef linear_congruential_engine minstd_rand0; + + // An alternative LCR (Lehmer Generator function). + typedef linear_congruential_engine minstd_rand; + + // The classic Mersenne Twister. + // M. Matsumoto and T. Nishimura, Mersenne Twister: A 623-Dimensionally + // Equidistributed Uniform Pseudo-Random Number Generator, ACM Transactions + // on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. + + typedef mersenne_twister_engine + mt19937; + + // An alternative Mersenne Twister (64-bit). + typedef mersenne_twister_engine + mt19937_64; + + typedef subtract_with_carry_engine ranlux24_base; + typedef subtract_with_carry_engine ranlux48_base; + + typedef discard_block_engine ranlux24; + typedef discard_block_engine ranlux48; + + typedef shuffle_order_engine knuth_b; + + typedef minstd_rand0 default_random_engine; + + class random_device + { + public: + using result_type = unsigned int; + + random_device() { } + + explicit random_device(const char*) { } + + static constexpr result_type(min)() noexcept + { + return static_cast(UINT8_C(0)); + } + + static constexpr result_type(max)() noexcept + { + return static_cast(static_cast(INTMAX_C(-1))); + } + + // Not conformant with the standard return type of double. + float entropy() const noexcept + { + const unsigned char e = my_hardware_random_device_entropy(); + + return ((e > static_cast(UINT8_C(32))) ? 32.0F : float(e)); + } + + result_type operator()() + { + return static_cast(my_hardware_random_device_generator()); + } + + random_device(const random_device&) = delete; + random_device& operator=(const random_device&) = delete; + }; + + } // namespace std + #endif // RANDOM_2018_06_10_ diff --git a/examples/chapter04_04/src/util/STL/ratio b/examples/chapter04_04/src/util/STL/ratio index 9ab68582e..bcfe973a9 100644 --- a/examples/chapter04_04/src/util/STL/ratio +++ b/examples/chapter04_04/src/util/STL/ratio @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -/// \author (c) Marco Paland (info@paland.com) +/// \author (c) Marco Paland (info (AT) paland.com) /// 2011-2012, PALANDesign Hannover, Germany /// /// \license LGPLv3 diff --git a/examples/chapter04_04/src/util/STL/stdexcept b/examples/chapter04_04/src/util/STL/stdexcept new file mode 100644 index 000000000..5e7a8c527 --- /dev/null +++ b/examples/chapter04_04/src/util/STL/stdexcept @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021 - 2022. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef STDEXCEPT_2021_10_22_ + #define STDEXCEPT_2021_10_22_ + + #include + + namespace std + { + class exception + { + public: + exception() noexcept { } + explicit exception(const string&) { } + explicit exception(const char*) { } + + virtual ~exception() { } + + virtual const char* what() const noexcept { static const char pstr[] = "explanatory_string"; return pstr; } + }; + + class logic_error; + class domain_error; + class invalid_argument; + class length_error; + class out_of_range; + class runtime_error; + class range_error; + class overflow_error; + class underflow_error; + + class logic_error : public exception + { + public: + explicit logic_error(const string&) { } + explicit logic_error(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "logic_error"; return pstr; } + }; + + class domain_error : public exception + { + public: + explicit domain_error(const string&) { } + explicit domain_error(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "domain_error"; return pstr; } + }; + + class invalid_argument : public exception + { + public: + explicit invalid_argument(const string&) { } + explicit invalid_argument(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "invalid_argument"; return pstr; } + }; + + class length_error : public exception + { + public: + explicit length_error(const string&) { } + explicit length_error(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "length_error"; return pstr; } + }; + + class out_of_range : public exception + { + public: + explicit out_of_range(const string&) { } + explicit out_of_range(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "out_of_range"; return pstr; } + }; + + class runtime_error : public exception + { + public: + explicit runtime_error(const string&) { } + explicit runtime_error(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "runtime_error"; return pstr; } + }; + + class range_error : public exception + { + public: + explicit range_error(const string&) { } + explicit range_error(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "range_error"; return pstr; } + }; + + class overflow_error : public exception + { + public: + explicit overflow_error(const string&) { } + explicit overflow_error(const char*) { } + + virtual const char* what() const noexcept { static const char pstr[] = "overflow_error"; return pstr; } + }; + } + +#endif // STDEXCEPT_2021_10_22_ diff --git a/examples/chapter04_04/src/util/STL/string b/examples/chapter04_04/src/util/STL/string index 62d7097db..2bda595ba 100644 --- a/examples/chapter04_04/src/util/STL/string +++ b/examples/chapter04_04/src/util/STL/string @@ -19,6 +19,12 @@ { using string = basic_string, allocator>; + // TBD: Implement various forms of to_string (especially for built-in integral types). + inline string to_string(int n) { return std::string(); } + + // TBD: Implement std::string addition. + inline string operator+(const string& a, const string& b) { return std::string(); } + namespace literals { namespace string_literals diff --git a/examples/chapter04_04/src/util/STL/time.h b/examples/chapter04_04/src/util/STL/time.h index 65296a4a2..0bc1d8e84 100644 --- a/examples/chapter04_04/src/util/STL/time.h +++ b/examples/chapter04_04/src/util/STL/time.h @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/STL/tuple b/examples/chapter04_04/src/util/STL/tuple index ee82bf9e8..14798e7be 100644 --- a/examples/chapter04_04/src/util/STL/tuple +++ b/examples/chapter04_04/src/util/STL/tuple @@ -8,14 +8,12 @@ #ifndef TUPLE_2010_02_23_ #define TUPLE_2010_02_23_ - #if defined(__GNUC__) - #pragma GCC system_header - #endif - #include #include - #include + #include + #include #include + #include // Implement some of std::tuple for compilers that do not yet support it. // This implementation of tuple supports up to 11 template parameters. @@ -32,18 +30,20 @@ struct xnothing final { - xnothing() { } - xnothing(const xnothing&) { } - ~xnothing() { } - xnothing& operator=(const xnothing&) { return *this; } + constexpr xnothing() = default; + constexpr xnothing(const xnothing&) = default; + constexpr xnothing(xnothing&&) noexcept = default; + ~xnothing() = default; + constexpr auto operator=(const xnothing&) -> xnothing& = default; + constexpr auto operator=(xnothing&&) noexcept -> xnothing& = default; }; - inline bool operator==(const xnothing&, const xnothing&) { return true; } - inline bool operator!=(const xnothing&, const xnothing&) { return false; } - inline bool operator< (const xnothing&, const xnothing&) { return false; } - inline bool operator<=(const xnothing&, const xnothing&) { return false; } - inline bool operator> (const xnothing&, const xnothing&) { return false; } - inline bool operator>=(const xnothing&, const xnothing&) { return false; } + inline constexpr auto operator==(const xnothing&, const xnothing&) noexcept -> bool { return true; } + inline constexpr auto operator!=(const xnothing&, const xnothing&) noexcept -> bool { return false; } + inline constexpr auto operator< (const xnothing&, const xnothing&) noexcept -> bool { return false; } + inline constexpr auto operator<=(const xnothing&, const xnothing&) noexcept -> bool { return false; } + inline constexpr auto operator> (const xnothing&, const xnothing&) noexcept -> bool { return false; } + inline constexpr auto operator>=(const xnothing&, const xnothing&) noexcept -> bool { return false; } } namespace std @@ -67,6 +67,20 @@ typename T11 = xtuple_helper::xnothing> class tuple { + private: + using type0 = T0; + using type1 = T1; + using type2 = T2; + using type3 = T3; + using type4 = T4; + using type5 = T5; + using type6 = T6; + using type7 = T7; + using type8 = T8; + using type9 = T9; + using type10 = T10; + using type11 = T11; + public: template @@ -75,63 +89,67 @@ template friend class xtuple_helper::xsize; - typedef tuple tuple_type; - - tuple() { } - - explicit tuple(const T0& p0, - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 (), - const T7& p7 = T7 (), - const T8& p8 = T8 (), - const T9& p9 = T9 (), - const T10& p10 = T10(), - const T11& p11 = T11()) : t0 (p0), - t1 (p1), - t2 (p2), - t3 (p3), - t4 (p4), - t5 (p5), - t6 (p6), - t7 (p7), - t8 (p8), - t9 (p9), - t10(p10), - t11(p11){ } - - tuple(const tuple_type& t) : t0 (t.t0), - t1 (t.t1), - t2 (t.t2), - t3 (t.t3), - t4 (t.t4), - t5 (t.t5), - t6 (t.t6), - t7 (t.t7), - t8 (t.t8), - t9 (t.t9), - t10(t.t10), - t11(t.t11){ } + using tuple_type = tuple; + + constexpr tuple() = default; + + constexpr tuple(const T0& p0, + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 (), + const T7& p7 = T7 (), + const T8& p8 = T8 (), + const T9& p9 = T9 (), + const T10& p10 = T10(), + const T11& p11 = T11()) : t0 (p0), + t1 (p1), + t2 (p2), + t3 (p3), + t4 (p4), + t5 (p5), + t6 (p6), + t7 (p7), + t8 (p8), + t9 (p9), + t10(p10), + t11(p11) { } + + constexpr tuple(const tuple_type& t) : t0 (t.t0), + t1 (t.t1), + t2 (t.t2), + t3 (t.t3), + t4 (t.t4), + t5 (t.t5), + t6 (t.t6), + t7 (t.t7), + t8 (t.t8), + t9 (t.t9), + t10(t.t10), + t11(t.t11) { } + + constexpr tuple(tuple_type&& t) noexcept + : t0 (t.t0), + t1 (t.t1), + t2 (t.t2), + t3 (t.t3), + t4 (t.t4), + t5 (t.t5), + t6 (t.t6), + t7 (t.t7), + t8 (t.t8), + t9 (t.t9), + t10(t.t10), + t11(t.t11) { } template - tuple(const std::pair& p) : t0 (p.first), - t1 (p.second), - t2 (T2 ()), - t3 (T3 ()), - t4 (T4 ()), - t5 (T5 ()), - t6 (T6 ()), - t7 (T7 ()), - t8 (T8 ()), - t9 (T9 ()), - t10(T10()), - t11(T11()){ } - - ~tuple() { } + constexpr tuple(const std::pair& p) : t0 (p.first), + t1 (p.second) { } + + ~tuple() = default; template - tuple& operator=(const tuple& t) + constexpr tuple& operator=(const tuple& t) + { + if(this != &t) + { + t0 = T0 (t.t0); + t1 = T1 (t.t1); + t2 = T2 (t.t2); + t3 = T3 (t.t3); + t4 = T4 (t.t4); + t5 = T5 (t.t5); + t6 = T6 (t.t6); + t7 = T7 (t.t7); + t8 = T8 (t.t8); + t9 = T9 (t.t9); + t10 = T10(t.t10); + t11 = T11(t.t11); + } + + return *this; + } + + constexpr tuple& operator=(tuple&& t) noexcept { - t0 = T0 (t.t0); - t1 = T1 (t.t1); - t2 = T2 (t.t2); - t3 = T3 (t.t3); - t4 = T4 (t.t4); - t5 = T5 (t.t5); - t6 = T6 (t.t6); - t7 = T7 (t.t7); - t8 = T8 (t.t8); - t9 = T9 (t.t9); - t10 = T10(t.t10); - t11 = T11(t.t11); + t0 = static_cast(t.t0); + t1 = static_cast(t.t1); + t2 = static_cast(t.t2); + t3 = static_cast(t.t3); + t4 = static_cast(t.t4); + t5 = static_cast(t.t5); + t6 = static_cast(t.t6); + t7 = static_cast(t.t7); + t8 = static_cast(t.t8); + t9 = static_cast(t.t9); + t10 = static_cast(t.t10); + t11 = static_cast(t.t11); return *this; } template - tuple& operator=(const std::pair& p) + constexpr tuple& operator=(const std::pair& p) { t0 = T0 (p.first); t1 = T1 (p.second); @@ -183,51 +222,75 @@ return *this; } - void swap(tuple& other) + constexpr void swap(tuple& other) { if(this != &other) { - const type0 tmp0 (t0 ); t0 = other.t0 ; other.t0 = tmp0 ; - const type1 tmp1 (t1 ); t1 = other.t1 ; other.t1 = tmp1 ; - const type2 tmp2 (t2 ); t2 = other.t2 ; other.t2 = tmp2 ; - const type3 tmp3 (t3 ); t3 = other.t3 ; other.t3 = tmp3 ; - const type4 tmp4 (t4 ); t4 = other.t4 ; other.t4 = tmp4 ; - const type5 tmp5 (t5 ); t5 = other.t5 ; other.t5 = tmp5 ; - const type6 tmp6 (t6 ); t6 = other.t6 ; other.t6 = tmp6 ; - const type7 tmp7 (t7 ); t7 = other.t7 ; other.t7 = tmp7 ; - const type8 tmp8 (t8 ); t8 = other.t8 ; other.t8 = tmp8 ; - const type9 tmp9 (t9 ); t9 = other.t9 ; other.t9 = tmp9 ; - const type10 tmp10(t10); t10 = other.t10; other.t10 = tmp10; - const type11 tmp11(t11); t11 = other.t11; other.t11 = tmp11; + my_swap(t0 , other.t0); + my_swap(t1 , other.t1); + my_swap(t2 , other.t2); + my_swap(t3 , other.t3); + my_swap(t4 , other.t4); + my_swap(t5 , other.t5); + my_swap(t6 , other.t6); + my_swap(t7 , other.t7); + my_swap(t8 , other.t8); + my_swap(t9 , other.t9); + my_swap(t10, other.t10); + my_swap(t11, other.t11); } } + constexpr void swap(tuple&& other) + { + my_swap(static_cast(t0) , static_cast(other.t0)); + my_swap(static_cast(t1) , static_cast(other.t1)); + my_swap(static_cast(t2) , static_cast(other.t2)); + my_swap(static_cast(t3) , static_cast(other.t3)); + my_swap(static_cast(t4) , static_cast(other.t4)); + my_swap(static_cast(t5) , static_cast(other.t5)); + my_swap(static_cast(t6) , static_cast(other.t6)); + my_swap(static_cast(t7) , static_cast(other.t7)); + my_swap(static_cast(t8) , static_cast(other.t8)); + my_swap(static_cast(t9) , static_cast(other.t9)); + my_swap(static_cast(t10), static_cast(other.t10)); + my_swap(static_cast(t11), static_cast(other.t11)); + } + private: - T0 t0; - T1 t1; - T2 t2; - T3 t3; - T4 t4; - T5 t5; - T6 t6; - T7 t7; - T8 t8; - T9 t9; - T10 t10; - T11 t11; - - typedef T0 type0; - typedef T1 type1; - typedef T2 type2; - typedef T3 type3; - typedef T4 type4; - typedef T5 type5; - typedef T6 type6; - typedef T7 type7; - typedef T8 type8; - typedef T9 type9; - typedef T10 type10; - typedef T11 type11; + type0 t0 { }; + type1 t1 { }; + type2 t2 { }; + type3 t3 { }; + type4 t4 { }; + type5 t5 { }; + type6 t6 { }; + type7 t7 { }; + type8 t8 { }; + type9 t9 { }; + type10 t10 { }; + type11 t11 { }; + + template + constexpr void my_swap(swap_type& left, swap_type& right) + { + if(&left != &right) + { + const swap_type tmp(left); + + left = right; + right = tmp; + } + } + + template + constexpr void my_swap(swap_type&& left, swap_type&& right) + { + const swap_type tmp(left); + + left = right; + right = tmp; + } }; } @@ -236,14 +299,14 @@ template class xget { }; - #define MAKE_XTUPLE_GET_HELPER(NUM) \ - template class xget<(NUM), xtuple_type> \ - { \ - public: \ - typedef typename xtuple_type::type##NUM xelem_type; \ - static xelem_type& get ( xtuple_type& t) { return t.t##NUM ; } \ - static const xelem_type& get_const(const xtuple_type& t) { return t.t##NUM ; } \ - } \ + #define MAKE_XTUPLE_GET_HELPER(NUM) \ + template class xget<(NUM), xtuple_type> \ + { \ + public: \ + typedef typename xtuple_type::type##NUM xelem_type; \ + static constexpr xelem_type& get ( xtuple_type& t) { return t.t##NUM ; } \ + static constexpr const xelem_type& get_const(const xtuple_type& t) { return t.t##NUM ; } \ + } MAKE_XTUPLE_GET_HELPER(0); MAKE_XTUPLE_GET_HELPER(1); @@ -265,76 +328,76 @@ class xsize { public: - static STL_LOCAL_CONSTEXPR std::size_t value = xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value - + xtuple_elem_size_helper::value; + static constexpr std::size_t value = xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value + + xtuple_elem_size_helper::value; }; } namespace std { template - typename xtuple_helper::xget >::xelem_type& get(tuple<>& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple<>& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } + constexpr typename xtuple_helper::xget >::xelem_type& get(tuple& t) { return xtuple_helper::xget >::get(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple<>& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple<>& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template - const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template @@ -372,7 +435,7 @@ class tuple_size { public: - static STL_LOCAL_CONSTEXPR std::size_t value = xtuple_helper::xsize::value; + static constexpr std::size_t value = xtuple_helper::xsize::value; }; template @@ -385,31 +448,31 @@ class tuple_size : public std::integral_constant::value> { }; template - tuple make_tuple(const T0& p0 = T0 ()) + constexpr tuple make_tuple(const T0& p0 = T0 ()) { return tuple(p0); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 ()) { return tuple(p0, p1); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 ()) { return tuple(p0, p1, p2); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 ()) { return tuple(p0, p1, p2, p3); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 ()) { return tuple(p0, p1, p2, p3, p4); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 ()) { return tuple(p0, p1, p2, p3, p4, p5); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 ()) { return tuple(p0, p1, p2, p3, p4, p5, p6); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 (), - const T7& p7 = T7 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 (), + const T7& p7 = T7 ()) { return tuple(p0, p1, p2, p3, p4, p5, p6, p7); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 (), - const T7& p7 = T7 (), - const T8& p8 = T8 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 (), + const T7& p7 = T7 (), + const T8& p8 = T8 ()) { return tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 (), - const T7& p7 = T7 (), - const T8& p8 = T8 (), - const T9& p9 = T9 ()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 (), + const T7& p7 = T7 (), + const T8& p8 = T8 (), + const T9& p9 = T9 ()) { return tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 (), - const T7& p7 = T7 (), - const T8& p8 = T8 (), - const T9& p9 = T9 (), - const T10& p10 = T10()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 (), + const T7& p7 = T7 (), + const T8& p8 = T8 (), + const T9& p9 = T9 (), + const T10& p10 = T10()) { return tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } template - tuple make_tuple(const T0& p0 = T0 (), - const T1& p1 = T1 (), - const T2& p2 = T2 (), - const T3& p3 = T3 (), - const T4& p4 = T4 (), - const T5& p5 = T5 (), - const T6& p6 = T6 (), - const T7& p7 = T7 (), - const T8& p8 = T8 (), - const T9& p9 = T9 (), - const T10& p10 = T10(), - const T11& p11 = T11()) + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 (), + const T3& p3 = T3 (), + const T4& p4 = T4 (), + const T5& p5 = T5 (), + const T6& p6 = T6 (), + const T7& p7 = T7 (), + const T8& p8 = T8 (), + const T9& p9 = T9 (), + const T10& p10 = T10(), + const T11& p11 = T11()) { return tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } } + namespace xtuple_helper + { + struct ignore_t + { + template + constexpr ignore_t& operator=(T&&) noexcept { return *this; } + + template + constexpr ignore_t& operator=(ignore_t&&) noexcept { return *this; } + }; + } + + namespace std + { + constexpr xtuple_helper::ignore_t ignore; + + template + constexpr std::tuple tie(Args&... args) noexcept + { + return {args...}; + } + } + #endif // TUPLE_2010_02_23_ diff --git a/examples/chapter04_04/src/util/STL/type_traits b/examples/chapter04_04/src/util/STL/type_traits index 25f0a4147..7c9d8caa4 100644 --- a/examples/chapter04_04/src/util/STL/type_traits +++ b/examples/chapter04_04/src/util/STL/type_traits @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -9,9 +9,7 @@ #define TYPE_TRAITS_2013_09_01_ #include - - #include - #include + #include // Implement some of for compilers that do not yet support it. @@ -23,11 +21,11 @@ { typedef the_value_type value_type; - static STL_LOCAL_CONSTEXPR value_type value = the_value; + static constexpr value_type value = the_value; typedef integral_constant type; - STL_LOCAL_CONSTEXPR operator value_type() const STL_LOCAL_NOEXCEPT + constexpr operator value_type() const { return value; } @@ -93,6 +91,11 @@ typedef false_type type; }; + template + using conditional_t = typename conditional::type; + template struct is_same : false_type { }; @@ -138,6 +141,12 @@ template struct is_array : std::true_type {}; + template struct is_reference : std::false_type { }; + template struct is_reference : std::true_type { }; + template struct is_reference : std::true_type { }; + + template struct is_function : std::integral_constant::value && !std::is_reference::value> { }; + template using remove_cv_t = typename remove_cv::type; template using remove_const_t = typename remove_const::type; template using remove_volatile_t = typename remove_volatile::type; @@ -153,6 +162,39 @@ template using remove_cvref_t = typename remove_cvref::type; + + template + constexpr remove_reference_t&& move(T&& arg) + { + return static_cast&&>(arg); + } + } + + namespace std + { + template + struct make_unsigned + { + using type = typename std::conditional<(sizeof(T) > 4U), std::uint64_t, + typename std::conditional<(sizeof(T) > 2U), std::uint32_t, + typename std::conditional<(sizeof(T) > 1U), std::uint16_t, + std::uint8_t>::type>::type>::type; + }; + + template + struct make_signed + { + using type = typename std::conditional<(sizeof(T) > 4U), std::int64_t, + typename std::conditional<(sizeof(T) > 2U), std::int32_t, + typename std::conditional<(sizeof(T) > 1U), std::int16_t, + std::int8_t>::type>::type>::type; + }; + + template + using make_unsigned_t = typename std::make_unsigned::type; + + template + using make_signed_t = typename std::make_signed::type; } namespace traits_helper @@ -178,20 +220,37 @@ namespace traits_helper { - template + template struct type_identity { using type = T; }; - template + template auto try_add_lvalue_reference(int) -> type_identity; - template + template auto try_add_lvalue_reference(...) -> type_identity; - template + template auto try_add_rvalue_reference(int) -> type_identity; - template + template auto try_add_rvalue_reference(...) -> type_identity; + + template + std::integral_constant test(int T::*); + + template + std::false_type test(...); + + template + std::true_type test_pre_ptr_convertible(const volatile B*); + template + std::false_type test_pre_ptr_convertible(const volatile void*); + + template + auto test_pre_is_base_of(...) -> std::true_type; + template + auto test_pre_is_base_of(int) -> + decltype(test_pre_ptr_convertible(static_cast(nullptr))); } namespace std @@ -204,6 +263,242 @@ template typename std::add_rvalue_reference::type declval(); + + template + struct is_class : decltype(traits_helper::test(nullptr)) { }; + + template + struct is_base_of : std::integral_constant::value && std::is_class::value && + decltype(traits_helper::test_pre_is_base_of(0))::value> { }; + + template + struct remove_extent { typedef T type; }; + + template + struct remove_extent { typedef T type; }; + + template + struct remove_extent { typedef T type; }; + + template< class T > + struct decay + { + private: + typedef typename std::remove_reference::type U; + + public: + typedef typename std::conditional::value, + typename std::remove_extent::type*, + typename std::conditional::value, + typename std::add_pointer::type, + typename std::remove_cv::type>::type>::type type; + }; + + template + using void_t = void; + + // primary template (used for zero types) + template + struct common_type { }; + + // 1 type + template + struct common_type : common_type {}; + + // 2 types + template + using cond_t = decltype(false ? std::declval() : std::declval()); + + template + struct common_type_2_impl {}; + + template + struct common_type_2_impl>> + { + using type = typename std::decay>::type; + }; + + template + struct common_type : common_type_2_impl::type, + typename std::decay::type> { }; + + // 3 or more types + template + struct common_type_multi_impl { }; + + template + struct common_type_multi_impl::type>, T1, T2, R...> + : common_type::type, R...> { }; + + template + struct common_type : common_type_multi_impl {}; + } + + #if(__cplusplus >= 201703L) + // C++17 and later + namespace std + { + template + inline constexpr bool is_same_v = is_same::value; + + template + inline constexpr bool is_integral_v = is_integral::value; + + template + inline constexpr bool is_floating_point_v = is_floating_point::value; + + template< class Base, class Derived > + inline constexpr bool is_base_of_v = is_base_of::value; + } + #endif + + #if(__cplusplus > 202002L) + // C++20 and later + namespace std + { + template + struct type_identity + { + using type = T; + }; + + template + using type_identity_t = typename type_identity::type; + } + #endif + + namespace traits_helper + { + template + auto test_returnable(int) -> + decltype + ( + void(static_cast(nullptr)), std::true_type { } + ); + + template + auto test_returnable(...) -> std::false_type; + + template + auto test_implicitly_convertible(int) -> + decltype + ( + void(std::declval()(std::declval())), std::true_type { } + ); + + template + auto test_implicitly_convertible(...) -> std::false_type; + + typedef char yes_type; + + struct no_type + { + char padding[8]; + }; + + struct is_constructible_imp + { + template()...))> + static traits_helper::yes_type test(int); + template + static traits_helper::no_type test(...); + + template()))> + static traits_helper::yes_type test1(int); + template + static traits_helper::no_type test1(...); + + template + static traits_helper::yes_type ref_test(T); + template + static traits_helper::no_type ref_test(...); + }; + + template + struct ok_tag { double d; char c[N]; }; + + template + ok_tag check_is_complete(int); + + template + char check_is_complete(...); + + struct is_default_constructible_imp + { + template + static traits_helper::yes_type test(int); + + template + static traits_helper::no_type test(...); + }; + + struct is_destructible_imp + { + template().~T())> + static traits_helper::yes_type test(int); + template + static traits_helper::no_type test(...); + }; + } + + namespace std + { + template struct is_complete + : public std::integral_constant::type>::value + || (sizeof(traits_helper::check_is_complete(0)) != sizeof(char))> { }; + + template struct is_destructible + : public std::integral_constant(0)) == sizeof(traits_helper::yes_type)> + { + static_assert(std::is_complete::value, "Arguments to is_destructible must be complete types"); + }; + + template struct is_default_constructible + : public integral_constant(0)) == sizeof(traits_helper::yes_type)> + { + static_assert(std::is_complete::value, "Arguments to is_default_constructible must be complete types"); + }; + + template struct is_default_constructible : public is_default_constructible{}; + template struct is_default_constructible : public is_default_constructible{}; + template struct is_default_constructible : public integral_constant{}; + + template struct is_default_constructible : public integral_constant{}; + + template <> struct is_default_constructible : public integral_constant{}; + template <> struct is_default_constructible : public integral_constant{}; + template <> struct is_default_constructible : public integral_constant{}; + template <> struct is_default_constructible : public integral_constant{}; + + template + struct is_convertible + : std::integral_constant(0))::value + && decltype(traits_helper::test_implicitly_convertible(0))::value) + || (std::is_void::value && std::is_void::value)> { }; + + template struct is_constructible + : public std::integral_constant(0)) == sizeof(traits_helper::yes_type)> + { + static_assert(std::is_complete::value, "The target type must be complete in order to test for constructibility"); + }; + + template struct is_constructible : public integral_constant::value && sizeof(traits_helper::is_constructible_imp::test1(0)) == sizeof(traits_helper::yes_type)> + { + static_assert(std::is_complete::value, "The target type must be complete in order to test for constructibility"); + }; + + template struct is_constructible : public integral_constant (std::declval())) == sizeof(traits_helper::yes_type)> { }; + template struct is_constructible : public integral_constant(std::declval())) == sizeof(traits_helper::yes_type)> { }; + + template <> struct is_constructible : public false_type { }; + template <> struct is_constructible : public false_type { }; + template <> struct is_constructible : public false_type { }; + template <> struct is_constructible : public false_type { }; + + template struct is_constructible : public is_default_constructible { }; } #endif // TYPE_TRAITS_2013_09_01_ diff --git a/examples/chapter04_04/src/util/STL/utility b/examples/chapter04_04/src/util/STL/utility index 55ecf320e..97909e08f 100644 --- a/examples/chapter04_04/src/util/STL/utility +++ b/examples/chapter04_04/src/util/STL/utility @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,6 +10,7 @@ #include #include + #include // Implement some of for compilers that do not yet support it. @@ -18,16 +19,22 @@ // Forward declaration of std::identity, which is implemented in . template struct identity; - } - namespace std - { - template - T&& forward(typename identity::type& param) + template + constexpr T&& forward(remove_reference_t& arg) STL_LOCAL_NOEXCEPT { - return static_cast(param); + return static_cast(arg); } + template + constexpr T&& forward(remove_reference_t&& arg) STL_LOCAL_NOEXCEPT + { + return static_cast(arg); + } + } + + namespace std + { template class pair @@ -47,10 +54,32 @@ pair(const pair& other) : first (other.first), second(other.second) { } + pair(pair&& other) noexcept : first (other.first), + second(other.second) { } + template pair(const pair& p) : first (T1(p.first)), second(T2(p.second)) { } + + pair& operator=(const pair& other) + { + if(*this != &other) + { + first = other.first; + second = other.second; + } + + return *this; + } + + pair& operator=(pair&& other) noexcept + { + first = other.first; + second = other.second; + + return *this; + } }; } diff --git a/examples/chapter04_04/src/util/STL_C++XX_stdfloat/cstdfloat b/examples/chapter04_04/src/util/STL_C++XX_stdfloat/cstdfloat index ece28d13a..9a4164105 100644 --- a/examples/chapter04_04/src/util/STL_C++XX_stdfloat/cstdfloat +++ b/examples/chapter04_04/src/util/STL_C++XX_stdfloat/cstdfloat @@ -14,7 +14,7 @@ #ifndef CSTDFLOAT_2014_01_09_ #define CSTDFLOAT_2014_01_09_ - #include + #include "stdfloat.h" #include // Here, we define floating-point typedefs having specified widths diff --git a/examples/chapter04_04/src/util/memory/util_factory.h b/examples/chapter04_04/src/util/memory/util_factory.h index 1def4c7bf..84b50257b 100644 --- a/examples/chapter04_04/src/util/memory/util_factory.h +++ b/examples/chapter04_04/src/util/memory/util_factory.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2020. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/memory/util_n_slot_array_allocator.h b/examples/chapter04_04/src/util/memory/util_n_slot_array_allocator.h new file mode 100644 index 000000000..37b9b382b --- /dev/null +++ b/examples/chapter04_04/src/util/memory/util_n_slot_array_allocator.h @@ -0,0 +1,195 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2024. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef UTIL_N_SLOT_ARRAY_ALLOCATOR_2020_10_25_H // NOLINT(llvm-header-guard) + #define UTIL_N_SLOT_ARRAY_ALLOCATOR_2020_10_25_H + + #include + #include + #include + #include + + namespace util { + + // Forward declaration of n_slot_array_allocator template. + template + class n_slot_array_allocator; + + // Template partial specialization of n_slot_array_allocator template for void. + template + class n_slot_array_allocator + { + public: + using value_type = void; + using pointer = value_type*; + using const_pointer = const value_type*; + + template + struct rebind + { + using other = n_slot_array_allocator; + }; + }; + + template + class n_slot_array_allocator // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + private: + static constexpr std::uint_fast32_t slot_width = SlotWidth; + static constexpr std::size_t slot_count = SlotCount; + + using slot_array_type = std::array; + using slot_array_memory_type = std::array; + using slot_array_flags_type = std::array; + + public: + using size_type = std::size_t; + using value_type = typename slot_array_type::value_type; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + + constexpr n_slot_array_allocator() = default; // LCOV_EXCL_LINE + + constexpr n_slot_array_allocator(const n_slot_array_allocator&) = default; // LCOV_EXCL_LINE + + template + struct rebind + { + using other = n_slot_array_allocator; + }; + + constexpr auto max_size() const noexcept -> size_type { return slot_count; } + + constexpr auto address( reference x) const -> pointer { return &x; } + constexpr auto address(const_reference x) const -> const_pointer { return &x; } + + auto allocate(size_type count, const_pointer p_hint = nullptr) -> pointer + { + static_cast(count); + static_cast(p_hint); + + pointer p { nullptr }; + + // TBD: There is most likely significant optimization potential + // capable of being unlocked if a storage/lookup mechanism can be + // devised that uses a binary search when finding the next free slot. + + // (TBD) In fact, constant-time allocation probably possible, as shown in: + // SmallObjectAllocator from Modern C++ Design by Andrei Alexandrescu. + + for(auto i = static_cast(UINT8_C(0)); i < slot_count; ++i) + { + using local_flags_value_type = typename slot_array_flags_type::value_type; + + if(slot_flags[i] == static_cast(UINT8_C(0))) // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) + { + slot_flags[i] = static_cast(UINT8_C(1)); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) + + p = static_cast(slot_array_memory[i].data()); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) + + if(i > slot_max_index) + { + slot_max_index = i; + + static_cast(slot_max_index); + } + + break; + } + } + + return p; + } + + auto construct(pointer p, const value_type& x) -> void + { + // The memory in the n-slot allocator already exists + // in an uninitialized form. Construction can safely + // simply set the value in the uninitialized memory. + + *p = x; + } + + auto destroy(pointer p) const -> void { static_cast(p); } // LCOV_EXCL_LINE + + auto deallocate(pointer p_slot, size_type sz) -> void + { + static_cast(sz); + + typename slot_array_memory_type::size_type index { }; + + for(auto& slot_array_memory_entry : slot_array_memory) + { + if(p_slot == static_cast(slot_array_memory_entry.data())) + { + using local_flags_value_type = typename slot_array_flags_type::value_type; + + slot_flags[index] = static_cast(UINT8_C(0)); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) + + break; + } + + ++index; + } + } + + private: + static slot_array_memory_type slot_array_memory; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static slot_array_flags_type slot_flags; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static std::size_t slot_max_index; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + }; + + template + typename n_slot_array_allocator::slot_array_memory_type n_slot_array_allocator::slot_array_memory; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,hicpp-uppercase-literal-suffix,readability-uppercase-literal-suffix) + + template + typename n_slot_array_allocator::slot_array_flags_type n_slot_array_allocator::slot_flags; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,hicpp-uppercase-literal-suffix,readability-uppercase-literal-suffix) + + template + std::size_t n_slot_array_allocator::slot_max_index; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,hicpp-uppercase-literal-suffix,readability-uppercase-literal-suffix) + + // Global comparison operators (required by the standard). + template + auto operator==(const n_slot_array_allocator& left, + const n_slot_array_allocator& right) -> bool + { + static_cast(left.max_size()); + static_cast(right.max_size()); + + return true; + } + + template + auto operator!=(const n_slot_array_allocator& left, + const n_slot_array_allocator& right) -> bool + { + static_cast(left.max_size()); + static_cast(right.max_size()); + + return false; + } + + } // namespace util + +#endif // UTIL_N_SLOT_ARRAY_ALLOCATOR_2020_10_25_H diff --git a/examples/chapter04_04/src/util/memory/util_placed_pointer.h b/examples/chapter04_04/src/util/memory/util_placed_pointer.h index 308889925..bc933ca3b 100644 --- a/examples/chapter04_04/src/util/memory/util_placed_pointer.h +++ b/examples/chapter04_04/src/util/memory/util_placed_pointer.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2020. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/memory/util_ring_allocator.h b/examples/chapter04_04/src/util/memory/util_ring_allocator.h index 8465ac4ed..c824dea3c 100644 --- a/examples/chapter04_04/src/util/memory/util_ring_allocator.h +++ b/examples/chapter04_04/src/util/memory/util_ring_allocator.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2017. +// Copyright Christopher Kormanyos 2007 - 2021. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -32,7 +32,7 @@ // The ring allocator's buffer type. struct buffer_type { - static constexpr size_type size = 16U; + static constexpr size_type size = 64U; std::uint8_t data[size]; diff --git a/examples/chapter04_04/src/util/memory/util_static_allocator.h b/examples/chapter04_04/src/util/memory/util_static_allocator.h index 4ad4ad07a..62b83e148 100644 --- a/examples/chapter04_04/src/util/memory/util_static_allocator.h +++ b/examples/chapter04_04/src/util/memory/util_static_allocator.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2017. +// Copyright Christopher Kormanyos 2007 - 2021. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,7 +31,7 @@ // The static allocator's buffer type. struct buffer_type { - static constexpr size_type size = 16U; + static constexpr size_type size = 640U; std::uint8_t data[size]; diff --git a/examples/chapter04_04/src/util/utility/util_alignas.h b/examples/chapter04_04/src/util/utility/util_alignas.h index 0cd13a5a7..c933895fc 100644 --- a/examples/chapter04_04/src/util/utility/util_alignas.h +++ b/examples/chapter04_04/src/util/utility/util_alignas.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2020. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/utility/util_baselexical_cast.h b/examples/chapter04_04/src/util/utility/util_baselexical_cast.h new file mode 100644 index 000000000..16f64a655 --- /dev/null +++ b/examples/chapter04_04/src/util/utility/util_baselexical_cast.h @@ -0,0 +1,173 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2024. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef UTIL_BASELEXICAL_CAST_2020_06_28_H // NOLINT(llvm-header-guard) + #define UTIL_BASELEXICAL_CAST_2020_06_28_H + + #if ((defined(__cplusplus) && (__cplusplus >= 201703L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) + #if !(defined(__GNUC__) && defined(__AVR__)) + #define UTIL_BASELEXICAL_CAST_HAS_CHARCONV + #endif + #endif + + #if defined(UTIL_BASELEXICAL_CAST_HAS_CHARCONV) + #include + #include + #else + #include + #include + #include + #include + #endif + + namespace util { + + #if defined(UTIL_BASELEXICAL_CAST_HAS_CHARCONV) + + template(UINT8_C(10)), + const bool UpperCase = true> + auto baselexical_cast(const UnsignedIntegerType& u, char* first, char* last) -> const char* + { + constexpr auto my_base = static_cast(BaseRepresentation); + + const auto result = std::to_chars(first, last, u, my_base); + + return result.ptr; + } + + #else + + template + struct baselexical_cast_helper + { + private: + using output_value_type = typename std::iterator_traits::value_type; + + public: + static auto extract(output_value_type) noexcept -> output_value_type = delete; + }; + + template + struct baselexical_cast_helper(UINT8_C(16))> + { + private: + using output_value_type = typename std::iterator_traits::value_type; + + public: + static auto extract(output_value_type c) noexcept -> output_value_type + { + if(c <= static_cast(INT8_C(9))) + { + c = + static_cast + ( + c + static_cast('0') + ); + } + else if((c >= static_cast(0xA)) && (c <= static_cast(INT8_C(0xF)))) // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + { + c = + static_cast + ( + static_cast(UpperCase ? static_cast('A') : static_cast('a')) + + static_cast(c - static_cast(INT8_C(0xA))) + ); + } + + return c; + } + }; + + template + struct baselexical_cast_helper(UINT8_C(10))> + { + private: + using output_value_type = typename std::iterator_traits::value_type; + + public: + static auto extract(output_value_type c) noexcept -> output_value_type + { + if(c <= static_cast(INT8_C(9))) + { + c = + static_cast + ( + c + static_cast('0') + ); + } + + return c; + } + }; + + template(UINT8_C(10)), + const bool UpperCase = true> + auto baselexical_cast(const UnsignedIntegerType& u, OutputIterator out, OutputIterator out_dummy) -> OutputIterator + { + static_cast(out_dummy); + + using unsigned_integer_type = UnsignedIntegerType; + using output_value_type = typename std::iterator_traits::value_type; + + if(u == static_cast(UINT8_C(0))) + { + *out = + static_cast + ( + baselexical_cast_helper::extract(static_cast(UINT8_C(0))) + ); + } + else + { + unsigned_integer_type x(u); + + auto out_first = out; + + while(x != static_cast(UINT8_C(0))) // NOLINT(altera-id-dependent-backward-branch) + { + const auto c = + static_cast + ( + x % static_cast(BaseRepresentation) + ); + + *out = + static_cast + ( + baselexical_cast_helper::extract(c) + ); + + x = + static_cast + ( + x / static_cast(BaseRepresentation) + ); + + if(x != static_cast(UINT8_C(0))) + { + ++out; + } + } + + std::reverse(out_first, out + static_cast(UINT8_C(1))); + } + + return out + static_cast(UINT8_C(1)); + } + + #endif + + } // namespace util + +#endif // UTIL_BASELEXICAL_CAST_2020_06_28_H diff --git a/examples/chapter04_04/src/util/utility/util_communication.h b/examples/chapter04_04/src/util/utility/util_communication.h index 81b21cd1d..b24a6abef 100644 --- a/examples/chapter04_04/src/util/utility/util_communication.h +++ b/examples/chapter04_04/src/util/utility/util_communication.h @@ -1,14 +1,15 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +// Copyright Christopher Kormanyos 2007 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef UTIL_COMMUNICATION_2012_05_31_H_ - #define UTIL_COMMUNICATION_2012_05_31_H_ +#ifndef UTIL_COMMUNICATION_2012_05_31_H + #define UTIL_COMMUNICATION_2012_05_31_H #include + #include #include #include @@ -21,31 +22,29 @@ public: virtual ~communication_base() = default; - virtual bool recv(std::uint8_t& byte_to_recv) = 0; + virtual auto recv(std::uint8_t& byte_to_recv) -> bool = 0; - virtual void select() = 0; - virtual void deselect() = 0; + virtual auto select() -> void = 0; + virtual auto deselect() -> void = 0; - virtual bool select_channel(const std::size_t) { return true; } + virtual auto select_channel(const std::size_t) -> bool { return true; } template - bool send_n(send_iterator_type first, send_iterator_type last) + auto send_n(send_iterator_type first, send_iterator_type last) noexcept -> bool { - bool send_result = true; + auto send_result = true; - while(first != last) + while((first != last) && send_result) { using send_value_type = typename std::iterator_traits::value_type; - send_result &= this->send(std::uint8_t(send_value_type(*first))); - - ++first; + send_result = (this->send(static_cast(send_value_type(*first++))) && send_result); } return send_result; } - virtual bool send(const std::uint8_t byte_to_send) = 0; + virtual auto send(const std::uint8_t byte_to_send) noexcept -> bool = 0; protected: communication_base() = default; @@ -58,17 +57,17 @@ class communication_buffer_depth_one_byte : public communication_base { public: - typedef std::uint8_t buffer_type; + using buffer_type = std::uint8_t; - virtual ~communication_buffer_depth_one_byte() = default; + ~communication_buffer_depth_one_byte() override = default; protected: - communication_buffer_depth_one_byte() : recv_buffer(0U) { } + buffer_type recv_buffer { }; - buffer_type recv_buffer; + communication_buffer_depth_one_byte() = default; private: - virtual bool recv(std::uint8_t& byte_to_recv) + auto recv(std::uint8_t& byte_to_recv) -> bool override { byte_to_recv = recv_buffer; @@ -79,36 +78,28 @@ template class communication_multi_channel : public communication_base { - private: - static_assert(channel_count > 0U, "Error channel_count must be greater than zero."); - public: - communication_multi_channel(communication_base** p_com_channels) - : my_com_channels(), - my_index (0U) + explicit communication_multi_channel(communication_base** p_com_channels) { - for(std::size_t i = 0U; i < channel_count; ++i) - { - my_com_channels[i] = p_com_channels[i]; - } + std::copy(p_com_channels, p_com_channels + channel_count, my_com_channels.begin()); } - ~communication_multi_channel() = default; + ~communication_multi_channel() override = default; - virtual bool send(const std::uint8_t byte_to_send) + auto send(const std::uint8_t byte_to_send) noexcept -> bool override { return my_com_channels[my_index]->send(byte_to_send); } - virtual bool recv(std::uint8_t& byte_to_recv) + auto recv(std::uint8_t& byte_to_recv) -> bool override { return my_com_channels[my_index]->recv(byte_to_recv); } - virtual void select() { my_com_channels[my_index]->select(); } - virtual void deselect() { my_com_channels[my_index]->deselect(); } + auto select() -> void override { my_com_channels[my_index]->select(); } + auto deselect() -> void override { my_com_channels[my_index]->deselect(); } - virtual bool select_channel(const std::size_t index) + auto select_channel(const std::size_t index) -> bool override { const bool select_channel_is_ok = (index < channel_count); @@ -121,11 +112,13 @@ } private: - communication_base* my_com_channels[channel_count]; - std::size_t my_index; + std::array my_com_channels { }; + std::size_t my_index { }; communication_multi_channel() = delete; + + static_assert(channel_count > 0U, "Error channel_count must be greater than zero."); }; } -#endif // UTIL_COMMUNICATION_2012_05_31_H_ +#endif // UTIL_COMMUNICATION_2012_05_31_H diff --git a/examples/chapter04_04/src/util/utility/util_constexpr_algorithm_unsafe.h b/examples/chapter04_04/src/util/utility/util_constexpr_algorithm_unsafe.h new file mode 100644 index 000000000..529664934 --- /dev/null +++ b/examples/chapter04_04/src/util/utility/util_constexpr_algorithm_unsafe.h @@ -0,0 +1,200 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef UTIL_CONSTEXPR_ALGORITHM_UNSAFE_2023_11_23_H // NOLINT(llvm-header-guard) + #define UTIL_CONSTEXPR_ALGORITHM_UNSAFE_2023_11_23_H + + #include + #include + #include + #include + + namespace util { + + // Use a local, constexpr, unsafe implementation of the abs-function. + template + constexpr auto abs_unsafe(ArithmeticType val) -> ArithmeticType + { + return ((val > static_cast(INT8_C(0))) ? val : -val); + } + + // Use a local, constexpr, unsafe implementation of the fill-function. + template + constexpr auto fill_unsafe(DestinationIterator first, DestinationIterator last, ValueType val) -> void + { + while(first != last) + { + using local_destination_value_type = typename std::iterator_traits::value_type; + + *first++ = static_cast(val); + } + } + + // Use a local, constexpr, unsafe implementation of the copy-function. + template + constexpr auto copy_unsafe(InputIterator first, InputIterator last, DestinationIterator dest) -> DestinationIterator + { + while(first != last) + { + using local_destination_value_type = typename std::iterator_traits::value_type; + + #if (defined(__GNUC__) && (__GNUC__ > 9)) + #pragma GCC diagnostic ignored "-Wstringop-overflow" + #endif + *dest++ = static_cast(*first++); + #if (defined(__GNUC__) && (__GNUC__ > 9)) + #pragma GCC diagnostic pop + #endif + } + + return dest; + } + + // Use a local, constexpr, unsafe implementation of the copy-backward-function. + template + constexpr auto copy_backward_unsafe(InputIterator first, InputIterator last, DestinationIterator dest) -> DestinationIterator + { + using local_destination_value_type = typename std::iterator_traits::value_type; + + while(first != last) + { + *(--dest) = static_cast(*(--last)); + } + + return dest; + } + + // Use a local, constexpr, unsafe implementation of the max-function. + template + constexpr auto max_unsafe(const ArithmeticType& left, const ArithmeticType& right) -> ArithmeticType + { + return ((left < right) ? right : left); + } + + // Use a local, constexpr, unsafe implementation of the max-function. + template + constexpr auto min_unsafe(const ArithmeticType& left, const ArithmeticType& right) -> ArithmeticType + { + return ((right < left) ? right : left); + } + + template + constexpr auto lower_bound_unsafe(ForwardIt first, ForwardIt last, const T& value) -> ForwardIt + { + using local_iterator_type = ForwardIt; + + using local_difference_type = typename std::iterator_traits::difference_type; + + local_difference_type step { }; + + auto count = static_cast(last - first); // NOLINT(altera-id-dependent-backward-branch) + + local_iterator_type itr { }; + + while(count > static_cast(INT8_C(0))) // NOLINT(altera-id-dependent-backward-branch) + { + itr = first; + + step = static_cast(count / static_cast(INT8_C(2))); + + itr += step; + + if (*itr < value) + { + first = ++itr; + + count -= static_cast(step + static_cast(INT8_C(1))); + } + else + { + count = step; + } + } + + return first; + } + + template + constexpr auto swap_unsafe(T& left, T& right) -> void + { + auto tmp = static_cast(left); + + left = static_cast(right); + right = static_cast(tmp); + } + + template + constexpr auto swap_unsafe(T&& left, T&& right) -> void + { + auto tmp = static_cast(left); + + left = static_cast(right); + right = static_cast(tmp); + } + + template + constexpr auto find_if_unsafe(InputIt first, InputIt last, UnaryPredicate p) -> InputIt + { + for( ; first != last; ++first) + { + if (p(*first)) + { + return first; + } + } + + return last; + } + + template + constexpr auto find_if_not_unsafe(InputIt first, InputIt last, UnaryPredicate q) -> InputIt + { + for( ; first != last; ++first) + { + if (!q(*first)) + { + return first; + } + } + + return last; + } + + template + constexpr auto all_of_unsafe(InputIt first, InputIt last, UnaryPredicate p) -> bool + { + return (find_if_not_unsafe(first, last, p) == last); + } + + template + constexpr auto iter_swap_unsafe(IteratorType a, IteratorType b) -> void + { + // Non-standard behavior: + // The (dereferenced) left/right value-types are the same. + + using local_value_type = typename std::iterator_traits::value_type; + + swap_unsafe(static_cast(*a), static_cast(*b)); + } + + template + constexpr auto reverse_unsafe(BiDirectionalIterator first, BiDirectionalIterator last) -> void + { + // Ensure that the type of the iterator provided is actually bidirectional. + + for( ; ((first != last) && (first != --last)); ++first) + { + iter_swap_unsafe(first, last); + } + } + + } // namespace util + +#endif // UTIL_CONSTEXPR_ALGORITHM_UNSAFE_2023_11_23_H diff --git a/examples/chapter04_04/src/util/utility/util_constexpr_cmath_unsafe.h b/examples/chapter04_04/src/util/utility/util_constexpr_cmath_unsafe.h new file mode 100644 index 000000000..3223f52f9 --- /dev/null +++ b/examples/chapter04_04/src/util/utility/util_constexpr_cmath_unsafe.h @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef UTIL_CONSTEXPR_CMATH_UNSAFE_2023_11_26_H // NOLINT(llvm-header-guard) + #define UTIL_CONSTEXPR_CMATH_UNSAFE_2023_11_26_H + + #include + + namespace util { + + template + constexpr auto frexp_unsafe(FloatingPointType x, int* expptr) -> FloatingPointType + { + using local_floating_point_type = FloatingPointType; + + local_floating_point_type result { }; + + const auto b_neg = (x < static_cast(0.0L)); + + if((x > static_cast(0.0L)) || b_neg) + { + local_floating_point_type f = (b_neg ? -x : x); // NOLINT(altera-id-dependent-backward-branch) + + auto e2 = static_cast(INT8_C(0)); + + constexpr auto two_pow_plus32 = + static_cast + ( + static_cast(0x10000) + * static_cast(0x10000) + ); + + constexpr auto two_pow_minus32 = static_cast(0.000000000232830643653869628906250000L); + + // TBD: Maybe optimize exponent reduction with a more clever kind of binary searching. + + while(f >= static_cast(two_pow_plus32)) // NOLINT(altera-id-dependent-backward-branch) + { + f = static_cast(f / static_cast(two_pow_plus32)); + e2 += static_cast(INT8_C(32)); + } + + while(f <= static_cast(two_pow_minus32)) // NOLINT(altera-id-dependent-backward-branch) + { + f = static_cast(f * static_cast(two_pow_plus32)); + e2 -= static_cast(INT8_C(32)); + } + + constexpr auto one_ldbl = static_cast(1.0L); + constexpr auto two_ldbl = static_cast(2.0L); + + while(f < static_cast(one_ldbl)) // NOLINT(altera-id-dependent-backward-branch) + { + f = static_cast(f * static_cast(two_ldbl)); + + --e2; + } + + while(f >= static_cast(one_ldbl)) // NOLINT(altera-id-dependent-backward-branch) + { + f = static_cast(f / static_cast(two_ldbl)); + + ++e2; + } + + if(expptr != nullptr) + { + *expptr = e2; + } + + result = ((!b_neg) ? f : -f); + } + else + { + if(expptr != nullptr) + { + *expptr = static_cast(INT8_C(0)); + } + } + + return result; + } + + } // namespace util + +#endif // UTIL_CONSTEXPR_CMATH_UNSAFE_2023_11_26_H diff --git a/examples/chapter04_04/src/util/utility/util_display.h b/examples/chapter04_04/src/util/utility/util_display.h new file mode 100644 index 000000000..9355bad00 --- /dev/null +++ b/examples/chapter04_04/src/util/utility/util_display.h @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2019 - 2023. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef UTIL_DISPLAY_2023_06_09_H + #define UTIL_DISPLAY_2023_06_09_H + + #include + + #include + #include + + namespace util { + + class display_multiline_base : private util::noncopyable + { + public: + virtual ~display_multiline_base() = default; + + virtual auto init() noexcept -> bool = 0; + + virtual auto write(const char* pstr, + const std::uint_fast8_t length, + const std::uint_fast8_t line_index) -> bool = 0; + + protected: + display_multiline_base() noexcept = default; + + virtual auto set_line_index(const std::uint8_t) noexcept -> bool { return true; } + + using timer_type = util::timer; + + static void blocking_delay(const typename timer_type::tick_type blocking_delay_value) + { + timer_type::blocking_delay(blocking_delay_value); + } + }; + + } // namespace util + +#endif // UTIL_DISPLAY_2023_06_09_H diff --git a/examples/chapter04_04/src/util/utility/util_dynamic_array.h b/examples/chapter04_04/src/util/utility/util_dynamic_array.h index 3165f0934..9c9f18b97 100644 --- a/examples/chapter04_04/src/util/utility/util_dynamic_array.h +++ b/examples/chapter04_04/src/util/utility/util_dynamic_array.h @@ -1,294 +1,311 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2012 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef UTIL_DYNAMIC_ARRAY_2012_05_16_H_ - #define UTIL_DYNAMIC_ARRAY_2012_05_16_H_ +#ifndef UTIL_DYNAMIC_ARRAY_2012_05_16_H // NOLINT(llvm-header-guard) + #define UTIL_DYNAMIC_ARRAY_2012_05_16_H #include + #include + #include #include #include #include #include - namespace util + namespace util { + + template, + typename SizeType = std::size_t, + typename DiffType = std::ptrdiff_t> + class dynamic_array; + + template + class dynamic_array { - template> - class dynamic_array + public: + // Type definitions. + using allocator_type = typename std::allocator_traits::template rebind_alloc; + using value_type = typename allocator_type::value_type; + using reference = value_type&; + using const_reference = const value_type&; + using iterator = value_type*; + using const_iterator = const value_type*; + using pointer = value_type*; + using const_pointer = const value_type*; + using size_type = SizeType; + using difference_type = DiffType; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + // Constructors. + explicit constexpr dynamic_array( size_type count = static_cast(UINT8_C(0)), + const_reference v = value_type(), + const allocator_type& a = allocator_type()) + : elem_count(count) { - public: - // Type definitions. - typedef alloc allocator_type; - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* iterator; - typedef const T* const_iterator; - typedef T* pointer; - typedef const T* const_pointer; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - // Constructors. - dynamic_array() : elem_count(0U), - elems (nullptr) { } - - dynamic_array(size_type count) : elem_count(count), - elems (elem_count > 0U ? allocator_type().allocate(elem_count) : nullptr) + if(elem_count > static_cast(UINT8_C(0))) { - for(auto it_self = begin(); it_self != end(); ++it_self) - { - allocator_type().construct(it_self, value_type()); - } - } + allocator_type my_a(a); - dynamic_array(size_type count, - const value_type& v, - const allocator_type& a = allocator_type()) - : elem_count(count), - elems (elem_count > 0U ? allocator_type(a).allocate(elem_count) : nullptr) - { - for(auto it_self = begin(); it_self != end(); ++it_self) - { - allocator_type(a).construct(it_self, v); - } - } + elems = std::allocator_traits::allocate(my_a, elem_count); - dynamic_array(const dynamic_array& other) - : elem_count(other.size()), - elems (elem_count > 0U ? allocator_type().allocate(elem_count) : nullptr) - { - auto it_other = other.cbegin(); + iterator it = begin(); - for(auto it_self = begin(); it_self != end(); ++it_self) + while(it != end()) { - allocator_type().construct(it_self, *it_other++); + std::allocator_traits::construct(my_a, it, v); + + ++it; } } + } - template - dynamic_array(input_iterator first, - input_iterator last, - const allocator_type& a = allocator_type()) - : elem_count(static_cast(std::distance(first, last))), - elems (elem_count > 0U ? allocator_type(a).allocate(elem_count) : nullptr) + constexpr dynamic_array(const dynamic_array& other) + : elem_count(other.size()) + { + allocator_type my_a; + + if(elem_count > static_cast(UINT8_C(0))) { - for(auto it_self = begin(); it_self != end(); ++it_self) - { - allocator_type(a).construct(it_self, *first++); - } + elems = std::allocator_traits::allocate(my_a, elem_count); } - dynamic_array(std::initializer_list lst, - const allocator_type& a = allocator_type()) - : elem_count(lst.size()), - elems (elem_count > 0U ? allocator_type(a).allocate(elem_count) : nullptr) - { - auto it_lst = lst.begin(); + std::copy(other.elems, other.elems + elem_count, elems); + } - for(auto it_self = begin(); it_self != end(); ++it_self) - { - allocator_type(a).construct(it_self, *it_lst++); - } - } + template + constexpr dynamic_array(input_iterator first, + input_iterator last, + const allocator_type& a = allocator_type()) + : elem_count(static_cast(std::distance(first, last))) + { + allocator_type my_a(a); - // Move constructor. - dynamic_array(dynamic_array&& other) : elem_count(other.elem_count), - elems (other.elems) + if(elem_count > static_cast(UINT8_C(0))) { - other.elem_count = 0U; - other.elems = nullptr; + elems = std::allocator_traits::allocate(my_a, elem_count); } - // Destructor. - virtual ~dynamic_array() - { - // Destroy the elements and deallocate the range. - if(elem_count > size_type(0U)) - { - for(pointer p = elems; p != (elems + elem_count); ++p) - { - allocator_type().destroy(p); - } + std::copy(first, last, elems); + } - allocator_type().deallocate(elems, elem_count); - } - } + constexpr dynamic_array(std::initializer_list lst, + const allocator_type& a = allocator_type()) + : elem_count(lst.size()) + { + allocator_type my_a(a); - // Assignment operator. - dynamic_array& operator=(const dynamic_array& other) + if(elem_count > static_cast(UINT8_C(0))) { - if(this != &other) - { - std::copy(other.elems, - other.elems + (std::min)(elem_count, other.elem_count), - elems); - } - - return *this; + elems = std::allocator_traits::allocate(my_a, elem_count); } - // Move assignment operator. - dynamic_array& operator=(dynamic_array&& other) - { - // Destroy the elements and deallocate the range. - if(elem_count > size_type(0U)) - { - for(pointer p = elems; p != (elems + elem_count); ++p) - { - allocator_type().destroy(p); - } + std::copy(lst.begin(), lst.end(), elems); + } - allocator_type().deallocate(elems, elem_count); - } + // Move constructor. + constexpr dynamic_array(dynamic_array&& other) noexcept : elem_count(other.elem_count), + elems (other.elems) + { + other.elem_count = static_cast(UINT8_C(0)); + other.elems = nullptr; + } - elem_count = other.elem_count; - elems = other.elems; + // Destructor. + virtual ~dynamic_array() // LCOV_EXCL_LINE + { + using local_allocator_traits_type = std::allocator_traits; - other.elem_count = 0U; - other.elems = nullptr; + allocator_type my_a; - return *this; - } + // Destroy the elements and deallocate the range. + local_allocator_traits_type::deallocate(my_a, elems, elem_count); + } - // Iterator members: - iterator begin () { return elems; } - iterator end () { return elems + elem_count; } - const_iterator begin () const { return elems; } - const_iterator end () const { return elems + elem_count; } - const_iterator cbegin () const { return elems; } - const_iterator cend () const { return elems + elem_count; } - reverse_iterator rbegin () { return reverse_iterator(elems + elem_count); } - reverse_iterator rend () { return reverse_iterator(elems); } - const_reverse_iterator rbegin () const { return const_reverse_iterator(elems + elem_count); } - const_reverse_iterator rend () const { return const_reverse_iterator(elems); } - const_reverse_iterator crbegin() const { return const_reverse_iterator(elems + elem_count); } - const_reverse_iterator crend () const { return const_reverse_iterator(elems); } - - // Raw pointer access. - pointer data() noexcept + // Assignment operator. + constexpr auto operator=(const dynamic_array& other) -> dynamic_array& + { + if(this != &other) { - return elems; + std::copy(other.elems, + other.elems + (std::min)(elem_count, other.elem_count), + elems); } - // Size and capacity. - size_type size () const { return elem_count; } - size_type max_size() const { return elem_count; } - bool empty () const { return (elem_count == 0U); } - - // Element access members. - reference operator[](const size_type i) { return elems[i]; } - const_reference operator[](const size_type i) const { return elems[i]; } - - reference front() { return elems[0U]; } - const_reference front() const { return elems[0U]; } + return *this; + } - reference back() { return ((elem_count > size_type(0U)) ? elems[elem_count - 1U] : elems[0U]); } - const_reference back() const { return ((elem_count > size_type(0U)) ? elems[elem_count - 1U] : elems[0U]); } + // Move assignment operator. + constexpr auto operator=(dynamic_array&& other) noexcept -> dynamic_array& + { + std::swap(elem_count, other.elem_count); + std::swap(elems, other.elems); - reference at(const size_type i) { return ((i < elem_count) ? elems[i] : elems[0U]); } - const_reference at(const size_type i) const { return ((i < elem_count) ? elems[i] : elems[0U]); } + return *this; + } - // Element manipulation members. - void fill(const value_type& v) { std::fill_n(begin(), elem_count, v); } + // Iterator members: + constexpr auto begin () noexcept -> iterator { return elems; } + constexpr auto end () noexcept -> iterator { return elems + elem_count; } + constexpr auto begin () const noexcept -> const_iterator { return elems; } + constexpr auto end () const noexcept -> const_iterator { return elems + elem_count; } + constexpr auto cbegin () const noexcept -> const_iterator { return elems; } + constexpr auto cend () const noexcept -> const_iterator { return elems + elem_count; } + constexpr auto rbegin () noexcept -> reverse_iterator { return reverse_iterator(elems + elem_count); } + constexpr auto rend () noexcept -> reverse_iterator { return reverse_iterator(elems); } + constexpr auto rbegin () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + constexpr auto rend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } + constexpr auto crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + constexpr auto crend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } + + // Raw pointer access. + constexpr auto data() noexcept -> pointer { return elems; } + constexpr auto data() const noexcept -> const_pointer { return elems; } + + // Size and capacity. + constexpr auto size () const noexcept -> size_type { return elem_count; } + constexpr auto max_size() const noexcept -> size_type { return elem_count; } + constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } + + // Element access members. + constexpr auto operator[](const size_type i) noexcept -> reference { return elems[i]; } + constexpr auto operator[](const size_type i) const noexcept -> const_reference { return elems[i]; } + + constexpr auto front() noexcept -> reference { return elems[static_cast(UINT8_C(0))]; } + constexpr auto front() const noexcept -> const_reference { return elems[static_cast(UINT8_C(0))]; } + + constexpr auto back() noexcept -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + constexpr auto back() const noexcept -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + + constexpr auto at(const size_type i) noexcept -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + constexpr auto at(const size_type i) const noexcept -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + + // Element manipulation members. + constexpr auto fill(const value_type& v) -> void + { + std::fill(begin(), begin() + elem_count, v); + } - void swap(dynamic_array& other) + constexpr auto swap(dynamic_array& other) noexcept -> void + { + if(this != &other) { - const size_type tmp_elem_count = elem_count; - const pointer tmp_elems = elems; + std::swap(elems, other.elems); + std::swap(elem_count, other.elem_count); + } + } - elem_count = other.elem_count; - elems = other.elems; + constexpr auto swap(dynamic_array&& other) noexcept -> void + { + elems = std::move(other.elems); + elem_count = std::move(other.elem_count); + } - other.elem_count = tmp_elem_count; - other.elems = tmp_elems; - } + private: + size_type elem_count; // NOLINT(readability-identifier-naming) + pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) + }; - private: - mutable size_type elem_count; - pointer elems; - }; + template + auto operator==(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + bool left_and_right_are_equal = false; - template - bool operator==(const dynamic_array& lhs, const dynamic_array& rhs) + if(lhs.size() == rhs.size()) { - const bool sizes_are_equal = (lhs.size() == rhs.size()); + using size_type = typename dynamic_array::size_type; - typedef typename dynamic_array::size_type size_type; + const auto size_of_left_is_zero = (lhs.size() == static_cast(UINT8_C(0))); - const bool size_of_left_is_zero = (lhs.size() == size_type(0U)); - - return (sizes_are_equal && (size_of_left_is_zero || std::equal(lhs.begin(), lhs.end(), rhs.begin()))); + left_and_right_are_equal = + (size_of_left_is_zero || std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin())); } - template - bool operator<(const dynamic_array& lhs, const dynamic_array& rhs) - { - typedef typename dynamic_array::size_type size_type; + return left_and_right_are_equal; + } - const bool size_of_left_is_zero = (lhs.size() == size_type(0U)); + template + auto operator<(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + using size_type = typename dynamic_array::size_type; + + const auto size_of_left_is_zero = (lhs.size() == static_cast(UINT8_C(0))); + + bool b_result { }; + if(size_of_left_is_zero) + { + const auto size_of_right_is_zero = (rhs.size() == static_cast(UINT8_C(0))); + + b_result = (!size_of_right_is_zero); + } + else + { if(size_of_left_is_zero) { - const bool size_of_right_is_zero = (rhs.size() == size_type(0U)); + const auto size_of_right_is_zero = (rhs.size() == static_cast(UINT8_C(0))); - return (size_of_right_is_zero ? false : true); + b_result = (!size_of_right_is_zero); } else { - if(size_of_left_is_zero) - { - const bool size_of_right_is_zero = (rhs.size() == size_type(0U)); - - return (size_of_right_is_zero == false); - } - else - { - const size_type count = (std::min)(lhs.size(), rhs.size()); + const size_type count = (std::min)(lhs.size(), rhs.size()); - return std::lexicographical_compare(lhs.begin(), - lhs.begin() + count, - rhs.begin(), - rhs.begin() + count); - } + b_result= std::lexicographical_compare(lhs.cbegin(), + lhs.cbegin() + count, + rhs.cbegin(), + rhs.cbegin() + count); } } - template - bool operator!=(const dynamic_array& lhs, const dynamic_array& rhs) - { - return ((lhs == rhs) == false); - } + return b_result; + } - template - bool operator>(const dynamic_array& lhs, const dynamic_array& rhs) - { - return (rhs < lhs); - } + template + auto operator!=(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (!(lhs == rhs)); + } - template - bool operator>=(const dynamic_array& lhs, const dynamic_array& rhs) - { - return ((lhs < rhs) == false); - } + template + auto operator>(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (rhs < lhs); + } - template - bool operator<=(const dynamic_array& lhs, const dynamic_array& rhs) - { - return ((rhs < lhs) == false); - } + template + auto operator>=(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (!(lhs < rhs)); + } - template - void swap(dynamic_array& x, dynamic_array& y) - { - x.swap(y); - } + template + auto operator<=(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (!(rhs < lhs)); } -#endif // UTIL_DYNAMIC_ARRAY_2012_05_16_H_ + template + auto swap(dynamic_array& x, + dynamic_array& y) noexcept -> void + { + x.swap(y); + } + + } // namespace util + +#endif // UTIL_DYNAMIC_ARRAY_2012_05_16_H diff --git a/examples/chapter04_04/src/util/utility/util_linear_interpolate.h b/examples/chapter04_04/src/util/utility/util_linear_interpolate.h index 93061476b..038571b56 100644 --- a/examples/chapter04_04/src/util/utility/util_linear_interpolate.h +++ b/examples/chapter04_04/src/util/utility/util_linear_interpolate.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2020. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/utility/util_narrow_cast.h b/examples/chapter04_04/src/util/utility/util_narrow_cast.h new file mode 100644 index 000000000..7659d71b5 --- /dev/null +++ b/examples/chapter04_04/src/util/utility/util_narrow_cast.h @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef UTIL_NARROW_CAST_2020_09_24_H_ + #define UTIL_NARROW_CAST_2020_09_24_H_ + + #include + + namespace util + { + template + constexpr T narrow_cast(U&& u) noexcept + { + return static_cast(std::forward(u)); + } + } + +#endif // UTIL_NARROW_CAST_2020_09_24_H_ diff --git a/examples/chapter04_04/src/util/utility/util_noncopyable.h b/examples/chapter04_04/src/util/utility/util_noncopyable.h index 3dabbaa7e..8f45b4e99 100644 --- a/examples/chapter04_04/src/util/utility/util_noncopyable.h +++ b/examples/chapter04_04/src/util/utility/util_noncopyable.h @@ -1,33 +1,37 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef UTIL_NONCOPYABLE_2008_12_16_H_ - #define UTIL_NONCOPYABLE_2008_12_16_H_ +#ifndef UTIL_NONCOPYABLE_2008_12_16_H // NOLINT(llvm-header-guard) + #define UTIL_NONCOPYABLE_2008_12_16_H // Taken (with slight modification) from boost::noncopyable. - namespace util + namespace util { + namespace my_noncopyable_namespace { + + class noncopyable { - namespace my_noncopyable_namespace - { - class noncopyable - { - protected: - noncopyable() = default; - ~noncopyable() = default; - - private: - // Emphasize: The following members are private. - noncopyable(const noncopyable&) = delete; - noncopyable& operator=(const noncopyable&) = delete; - }; - } - - using noncopyable = my_noncopyable_namespace::noncopyable; - } - -#endif // UTIL_NONCOPYABLE_2008_12_16_H_ + protected: + noncopyable() = default; // LCOV_EXCL_LINE + ~noncopyable() = default; // LCOV_EXCL_LINE + + private: + // Emphasize: The following members are private. + noncopyable(const noncopyable&) = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) + noncopyable(noncopyable&&) = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) + + auto operator=(const noncopyable&) -> noncopyable& = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) + auto operator=(noncopyable&&) -> noncopyable& = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete) + }; + + } // namespace my_noncopyable_namespace + + using noncopyable = my_noncopyable_namespace::noncopyable; + + } // namespace util + +#endif // UTIL_NONCOPYABLE_2008_12_16_H diff --git a/examples/chapter04_04/src/util/utility/util_swdm.h b/examples/chapter04_04/src/util/utility/util_swdm.h index bce7da4c1..5fe4f32c5 100644 --- a/examples/chapter04_04/src/util/utility/util_swdm.h +++ b/examples/chapter04_04/src/util/utility/util_swdm.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// \author (c) Marco Paland (info@paland.com) +// \author (c) Marco Paland (info (AT) paland.com) // 2014-2016, PALANDesign Hannover, Germany // // \license The MIT License (MIT) @@ -98,7 +98,7 @@ // void swdm::set_line(bool value) const // { // set the state of the according swdm line/pin to value (true = high/idle, false = low) -// if you don't use an open collector driver, you MUST config the pin as input for high/idle levels +// if you don't use an open collector driver, you MUST configure the pin as input for high/idle levels // and before setting the line to false/low it must be configured as an output. // } // diff --git a/examples/chapter04_04/src/util/utility/util_time.h b/examples/chapter04_04/src/util/utility/util_time.h index 682f97ada..7f9653abb 100644 --- a/examples/chapter04_04/src/util/utility/util_time.h +++ b/examples/chapter04_04/src/util/utility/util_time.h @@ -1,51 +1,53 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef UTIL_TIME_2010_04_10_H_ - #define UTIL_TIME_2010_04_10_H_ +#ifndef UTIL_TIME_2010_04_10_H + #define UTIL_TIME_2010_04_10_H #include #include - #include + #include + #include namespace util { template class timer { + private: + static constexpr auto timer_mask = + static_cast + ( + (UINTMAX_C(1) << (std::numeric_limits::digits - 1)) - UINTMAX_C(1) + ); + public: - typedef unsigned_tick_type tick_type; + using tick_type = unsigned_tick_type; - static_assert(std::numeric_limits::is_signed == false, - "the timer tick_type must be unsigned"); + template static constexpr auto microseconds(other_tick_type value_microseconds) noexcept -> tick_type { return static_cast(value_microseconds); } + template static constexpr auto milliseconds(other_tick_type value_milliseconds) noexcept -> tick_type { return static_cast(1000UL) * microseconds(value_milliseconds); } + template static constexpr auto seconds (other_tick_type value_seconds) noexcept -> tick_type { return static_cast(1000UL) * milliseconds(value_seconds ); } + template static constexpr auto minutes (other_tick_type value_minutes) noexcept -> tick_type { return static_cast( 60UL) * seconds (value_minutes ); } + template static constexpr auto hours (other_tick_type value_hours) noexcept -> tick_type { return static_cast( 60UL) * minutes (value_hours ); } + template static constexpr auto days (other_tick_type value_days) noexcept -> tick_type { return static_cast( 24UL) * hours (value_days ); } + template static constexpr auto weeks (other_tick_type value_weeks) noexcept -> tick_type { return static_cast( 7UL) * days (value_weeks ); } - static_assert(std::numeric_limits::digits <= std::numeric_limits::digits, - "The width of the timer tick_type can not exceed the width of mcal::gpt::value_type"); + constexpr timer() noexcept = default; - private: - static const tick_type timer_mask = static_cast((UINTMAX_C(1) << (std::numeric_limits::digits - 1)) - UINTMAX_C(1)); - - public: - template static constexpr tick_type microseconds(other_tick_type value_microseconds) { return value_microseconds; } - template static constexpr tick_type milliseconds(other_tick_type value_milliseconds) { return static_cast(1000UL) * microseconds(value_milliseconds); } - template static constexpr tick_type seconds (other_tick_type value_seconds ) { return static_cast(1000UL) * milliseconds(value_seconds ); } - template static constexpr tick_type minutes (other_tick_type value_minutes ) { return static_cast( 60UL) * seconds (value_minutes ); } - template static constexpr tick_type hours (other_tick_type value_hours ) { return static_cast( 60UL) * minutes (value_hours ); } - template static constexpr tick_type days (other_tick_type value_days ) { return static_cast( 24UL) * hours (value_days ); } - template static constexpr tick_type weeks (other_tick_type value_weeks ) { return static_cast( 7UL) * days (value_weeks ); } + constexpr timer(tick_type tick_value) noexcept : my_tick(my_now() + tick_value) { } - timer() : my_tick(0U) { } + constexpr timer(const timer& other) noexcept : my_tick(other.my_tick) { } - timer(const tick_type& tick_value) : my_tick(my_now() + tick_value) { } + constexpr timer(timer&& other) noexcept : my_tick(other.my_tick) { } - timer(const timer& other) : my_tick(other.my_tick) { } + ~timer() noexcept = default; - timer& operator=(const timer& other) + auto operator=(const timer& other) noexcept -> timer& { if(this != &other) { @@ -55,62 +57,72 @@ return *this; } - void start_interval(const tick_type& tick_value) + auto operator=(timer&& other) noexcept -> timer& + { + my_tick = other.my_tick; + + return *this; + } + + auto start_interval(const tick_type& tick_value) noexcept -> void { my_tick += tick_value; } - void start_relative(const tick_type& tick_value) + auto start_relative(const tick_type& tick_value) noexcept -> void { my_tick = my_now() + tick_value; } - bool timeout() const + constexpr auto timeout() const noexcept -> bool { - const tick_type delta = my_now() - my_tick; - - return (delta <= timer_mask); + return (static_cast(my_now() - my_tick) <= timer_mask); } - bool timeout_of_specific_timepoint(const tick_type timepoint) const + constexpr auto timeout_of_specific_timepoint(const tick_type timepoint) const noexcept -> bool { - const tick_type delta = timepoint - my_tick; - - return (delta <= timer_mask); + return (static_cast(timepoint - my_tick) <= timer_mask); } - void set_mark() + auto set_mark() noexcept -> void { - my_tick = my_now(); - - return my_tick; + return (my_tick = my_now()); } - static tick_type get_mark() + static constexpr auto get_mark() noexcept -> tick_type { return my_now(); } - tick_type get_ticks_since_mark() const + constexpr auto get_ticks_since_mark() const noexcept -> tick_type { return my_now() - my_tick; } - static void blocking_delay(const tick_type& delay) + static auto blocking_delay(const tick_type& delay) noexcept -> void { const timer t_delay(delay); while(false == t_delay.timeout()) { - mcal::cpu::nop(); + mcal::wdg::secure::trigger(); } } private: - tick_type my_tick; + tick_type my_tick { my_now() }; - static tick_type my_now() { return static_cast(mcal::gpt::secure::get_time_elapsed()); } + constexpr static auto my_now() noexcept -> tick_type + { + return static_cast(mcal::gpt::secure::get_time_elapsed()); + } + + static_assert(std::numeric_limits::is_signed == false, + "the timer tick_type must be unsigned"); + + static_assert(std::numeric_limits::digits <= std::numeric_limits::digits, + "The width of the timer tick_type can not exceed the width of mcal::gpt::value_type"); }; } -#endif // UTIL_TIME_2010_04_10_H_ +#endif // UTIL_TIME_2010_04_10_H diff --git a/examples/chapter04_04/src/util/utility/util_two_part_data_manipulation.h b/examples/chapter04_04/src/util/utility/util_two_part_data_manipulation.h index a27077d74..7375d0cd7 100644 --- a/examples/chapter04_04/src/util/utility/util_two_part_data_manipulation.h +++ b/examples/chapter04_04/src/util/utility/util_two_part_data_manipulation.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2021. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/src/util/utility/util_utype_helper.h b/examples/chapter04_04/src/util/utility/util_utype_helper.h index f009a0ff4..e3f12c792 100644 --- a/examples/chapter04_04/src/util/utility/util_utype_helper.h +++ b/examples/chapter04_04/src/util/utility/util_utype_helper.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2021. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/target.vcxproj b/examples/chapter04_04/target.vcxproj index ef20800a7..8931e28e4 100644 --- a/examples/chapter04_04/target.vcxproj +++ b/examples/chapter04_04/target.vcxproj @@ -10,7 +10,7 @@ {30CE370B-40F3-4BCD-8986-64AAFF8971BD} Target Win32Proj - 10.0.16299.0 + 10.0 @@ -28,7 +28,7 @@ Makefile - v141 + v142 Makefile diff --git a/examples/chapter04_04/target/app/make/app_make.gmk b/examples/chapter04_04/target/app/make/app_make.gmk index c3d6f37bf..4b1a5d08f 100644 --- a/examples/chapter04_04/target/app/make/app_make.gmk +++ b/examples/chapter04_04/target/app/make/app_make.gmk @@ -1,12 +1,12 @@ # -# Copyright Christopher Kormanyos 2007 - 2021. +# Copyright Christopher Kormanyos 2007 - 2023. # Distributed under the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://www.boost.org/LICENSE_1_0.txt) # # ------------------------------------------------------------------------------ -# +# # Makefile # # Build file for the reference application using the GNU tools @@ -15,14 +15,32 @@ # # 07-April-2010 # +# See also a definitive list of GCC command line options +# (for numerous target systems) here: +# https://man7.org/linux/man-pages/man1/gcc.1.html +# +# ------------------------------------------------------------------------------ + + +# ------------------------------------------------------------------------------ +# punctuation # ------------------------------------------------------------------------------ +DQUOTE := \" +$(DQUOTE) := \" + +SEMICOLON := ; +$(SEMICOLON) := ; + +DOLLAR := $$ +$(DOLLAR) := $$ # ------------------------------------------------------------------------------ -# compiler location, build from GCC version and GCC target +# null device # ------------------------------------------------------------------------------ -COMPILER_DIRECTORY = gcc-$(GCC_VERSION)-$(GCC_TARGET) +NULL_DEVICE := NUL +$(NULL_DEVICE) := NUL # ------------------------------------------------------------------------------ # paths @@ -40,29 +58,32 @@ PATH_TGT_MAKE = $(PATH_TGT)/make PATH_BIN = bin PATH_TMP = tmp PATH_OBJ = $(PATH_TMP)/obj -PATH_SRC = $(PATH_TMP)/src +PATH_LST = $(PATH_TMP)/lst PATH_ERR = $(PATH_TMP)/err # ------------------------------------------------------------------------------ -# include files +# standard shell tools # ------------------------------------------------------------------------------ -include $(PATH_APP_MAKE)/app_files.gmk # Application file list -include $(PATH_TGT_MAKE)/$(TGT)_files.gmk # Target filelist -include $(PATH_TGT_MAKE)/$(TGT)_flags.gmk # Target compiler flags + +ECHO = $(PATH_TOOLS_MINGW_BIN)\echo.exe +MAKE = $(PATH_TOOLS_MINGW_BIN)\make.exe +MKDIR = $(PATH_TOOLS_MINGW_BIN)\mkdir.exe +RM = $(PATH_TOOLS_MINGW_BIN)\rm.exe +SED = $(PATH_TOOLS_MINGW_BIN)\sed.exe # ------------------------------------------------------------------------------ # the application # ------------------------------------------------------------------------------ -APP = $(PATH_BIN)/chapter04_04 +APP = $(PATH_BIN)/ref_app -# ------------------------------------------------------------------------------ -# object files -# ------------------------------------------------------------------------------ -FILES_TMP = $(FILES_CPP) $(FILES_TGT) -FILES_O = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .o, $(FILES_TMP)))) +IMAGE_FILE = $(APP).bin + +RULE_SPECIAL_MAKE_IMAGE_FILE = +RULE_SPECIAL_MAKE_FLASH_BATCH = +WARN_FLAGS = # ------------------------------------------------------------------------------ # linker definition file @@ -70,6 +91,21 @@ FILES_O = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .o, $(FILES_TMP)))) LINKER_DEFINITION_FILE = $(PATH_TGT_MAKE)/$(TGT).ld +# ------------------------------------------------------------------------------ +# include the target-specific make files +# ------------------------------------------------------------------------------ +include $(PATH_APP_MAKE)/app_files.gmk # Application file list +include $(PATH_TGT_MAKE)/$(TGT)_files.gmk # Target filelist +include $(PATH_TGT_MAKE)/$(TGT)_flags.gmk # Target compiler flags + + +# ------------------------------------------------------------------------------ +# object files +# ------------------------------------------------------------------------------ +FILES_TMP = $(FILES_CPP) $(FILES_TGT) +FILES_O = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .o, $(FILES_TMP)))) + + # ------------------------------------------------------------------------------ # VPATH definition # @@ -85,22 +121,29 @@ VPATH := $(sort $(dir $(FILES_TMP))) # ------------------------------------------------------------------------------ # Development tools # ------------------------------------------------------------------------------ -AR = $(PATH_TOOLS_CC)\$(GCC_TARGET)-ar.exe -AS = $(PATH_TOOLS_CC)\$(GCC_TARGET)-g++.exe -CC = $(PATH_TOOLS_CC)\$(GCC_TARGET)-g++.exe -CPPFILT = $(PATH_TOOLS_CC)\$(GCC_TARGET)-c++filt.exe -NM = $(PATH_TOOLS_CC)\$(GCC_TARGET)-nm.exe -OBJDUMP = $(PATH_TOOLS_CC)\$(GCC_TARGET)-objdump.exe -OBJCOPY = $(PATH_TOOLS_CC)\$(GCC_TARGET)-objcopy.exe -READELF = $(PATH_TOOLS_CC)\$(GCC_TARGET)-readelf.exe -SIZE = $(PATH_TOOLS_CC)\$(GCC_TARGET)-size.exe - -ECHO = $(PATH_TOOLS_MINGW_BIN)\echo.exe -MAKE = $(PATH_TOOLS_MINGW_BIN)\make.exe -MKDIR = $(PATH_TOOLS_MINGW_BIN)\mkdir.exe -RM = $(PATH_TOOLS_MINGW_BIN)\rm.exe -SED = $(PATH_TOOLS_MINGW_BIN)\sed.exe - +ifeq ($(GCC_PREFIX),) +AR = $(PATH_TOOLS_CC)\ar.exe +AS = $(PATH_TOOLS_CC)\g++.exe +CC = $(PATH_TOOLS_CC)\g++.exe +CPPFILT = $(PATH_TOOLS_CC)\c++filt.exe +NM = $(PATH_TOOLS_CC)\nm.exe +OBJDUMP = $(PATH_TOOLS_CC)\objdump.exe +OBJCOPY = $(PATH_TOOLS_CC)\objcopy.exe +READELF = $(PATH_TOOLS_CC)\readelf.exe +SIZE = $(PATH_TOOLS_CC)\size.exe +else +AR = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-ar.exe +AS = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-g++.exe +CC = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-g++.exe +CPPFILT = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-c++filt.exe +NM = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-nm.exe +OBJDUMP = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-objdump.exe +ifeq ($(OBJCOPY),) +OBJCOPY = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-objcopy.exe +endif +READELF = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-readelf.exe +SIZE = $(PATH_TOOLS_CC)\$(GCC_PREFIX)-size.exe +endif # ------------------------------------------------------------------------------ # Tool parameters @@ -109,47 +152,33 @@ C_INCLUDES = $(TGT_INCLUDES) \ -I$(PATH_APP) \ -I$(PATH_APP)/mcal/$(TGT) -GCCFLAGS = $(TGT_CFLAGS) \ - -g \ - -Wall \ +ifeq ($(WARN_FLAGS),) +WARN_FLAGS = -Wall \ -Wextra \ - -pedantic \ - -Wmain \ - -Wundef \ - -Wsign-conversion \ - -Wunused-parameter \ - -Wuninitialized \ - -Wmissing-declarations \ - -Wshadow \ - -Wunreachable-code \ - -Wswitch-default \ - -Wswitch-enum \ - -Wcast-align \ - -Wmissing-include-dirs \ - -Winit-self \ - -Wfloat-equal \ - -Wdouble-promotion \ + -Wpedantic +endif + +GCCFLAGS = -g \ + $(WARN_FLAGS) \ + -Wno-comment \ -gdwarf-2 \ -fno-exceptions \ -ffunction-sections \ -fdata-sections CFLAGS = $(GCCFLAGS) \ - -Wunsuffixed-float-constants \ - -x c \ - -std=c99 + $(TGT_CFLAGS) \ + -x c -CPPFLAGS = $(GCCFLAGS) \ - $(TGT_CPPFLAGS) \ +CXXFLAGS = $(GCCFLAGS) \ + $(TGT_CXXFLAGS) \ -x c++ \ -fno-rtti \ - -fstrict-enums \ -fno-use-cxa-atexit \ - -fno-use-cxa-get-exception-ptr \ -fno-nonansi-builtins \ -fno-threadsafe-statics \ -fno-enforce-eh-specs \ - -ftemplate-depth=32 \ + -ftemplate-depth=128 \ -Wzero-as-null-pointer-constant AFLAGS = $(GCCFLAGS) \ @@ -157,11 +186,10 @@ AFLAGS = $(GCCFLAGS) \ $(TGT_AFLAGS) \ -x assembler -LDFLAGS = $(GCCFLAGS) \ +LDFLAGS = $(CXXFLAGS) \ $(TGT_LDFLAGS) \ -x none \ - -Wl,--gc-sections \ - -Wl,-Map,$(APP).map + -Wl,--print-memory-usage # ------------------------------------------------------------------------------ # Main-Dependencies (app: all) @@ -186,8 +214,8 @@ clean_prj: @-$(MKDIR) -p $(PATH_BIN) @-$(MKDIR) -p $(PATH_OBJ) @-$(MKDIR) -p $(PATH_ERR) - @-$(MKDIR) -p $(PATH_SRC) - @-$(RM) -r $(PATH_BIN) > NUL 2> NUL + @-$(MKDIR) -p $(PATH_LST) + @-$(RM) -r $(PATH_BIN) 2>$(NULL_DEVICE) @-$(MKDIR) -p $(PATH_BIN) @@ -200,11 +228,11 @@ clean_all: @-$(MKDIR) -p $(PATH_BIN) @-$(MKDIR) -p $(PATH_OBJ) @-$(MKDIR) -p $(PATH_ERR) - @-$(MKDIR) -p $(PATH_SRC) - @-$(RM) -r $(PATH_OBJ) > NUL 2> NUL - @-$(RM) -r $(PATH_ERR) > NUL 2> NUL - @-$(RM) -r $(PATH_SRC) > NUL 2> NUL - @-$(RM) -r $(PATH_BIN) > NUL 2> NUL + @-$(MKDIR) -p $(PATH_LST) + @-$(RM) -r $(PATH_OBJ) 2>$(NULL_DEVICE) + @-$(RM) -r $(PATH_ERR) 2>$(NULL_DEVICE) + @-$(RM) -r $(PATH_LST) 2>$(NULL_DEVICE) + @-$(RM) -r $(PATH_BIN) 2>$(NULL_DEVICE) @-$(MKDIR) -p $(PATH_BIN) @@ -214,6 +242,7 @@ clean_all: .PHONY: version version: # Print the GNU make version and the compiler version + @$(ECHO) @$(ECHO) +++ Print GNUmake version @$(MAKE) --version @$(ECHO) @@ -224,11 +253,14 @@ version: @$(ECHO) $(C_INCLUDES) @$(ECHO) @$(ECHO) +++ Print compiler include paths (for VisualStudio(R) browsing) - @$(ECHO) $(subst /,\, $(subst -I,$$\(SolutionDir\), $(C_INCLUDES))) + @$(ECHO) $(addsuffix $(SEMICOLON),$(subst -I,$$\(ProjectDir\)/, $(C_INCLUDES))) @$(ECHO) @$(ECHO) +++ Print compiler definitions @$(ECHO) $(C_DEFINES) @$(ECHO) + @$(ECHO) +++ Print compiler CXXFLAGS flags + @$(ECHO) $(CXXFLAGS) + @$(ECHO) # ------------------------------------------------------------------------------ @@ -237,8 +269,6 @@ version: $(APP).$(TGT_SUFFIX) : $(LINKER_DEFINITION_FILE) $(FILES_O) @-$(ECHO) +++ linking application to generate: $(APP).$(TGT_SUFFIX) @-$(CC) $(LDFLAGS) $(FILES_O) -o $(APP).$(TGT_SUFFIX) - @-$(ECHO) +++ generating assembly list file: $(APP).lss - @-$(OBJDUMP) -h -S $(APP).$(TGT_SUFFIX) > $(APP).lss # ------------------------------------------------------------------------------ @@ -250,7 +280,11 @@ $(APP)_nm.txt : $(APP).$(TGT_SUFFIX) @-$(ECHO) +++ demangling symbols with c++filt to generate: $(APP)_cppfilt.txt @-$(NM) --numeric-sort --print-size $(APP).$(TGT_SUFFIX) | $(CPPFILT) > $(APP)_cppfilt.txt @-$(ECHO) +++ parsing symbols with readelf to generate: $(APP)_readelf.txt +ifeq ($(TGT_SUFFIX),elf) @-$(READELF) --syms $(APP).$(TGT_SUFFIX) > $(APP)_readelf.txt +else + @-$(ECHO) +++ not available for: $(APP).$(TGT_SUFFIX). +endif @-$(ECHO) +++ creating size summary table with size to generate: $(APP)_size.txt @-$(SIZE) -A -t $(APP).$(TGT_SUFFIX) > $(APP)_size.txt @@ -259,9 +293,29 @@ $(APP)_nm.txt : $(APP).$(TGT_SUFFIX) # create hex mask # ------------------------------------------------------------------------------ $(APP)_flash.hex : $(APP).$(TGT_SUFFIX) + @-$(ECHO) +++ creating hex module: $(APP).$(TGT_SUFFIX) +ifeq ($(TGT_SUFFIX),elf) @-$(ECHO) +++ creating hex module: $(APP).hex. - @-$(OBJCOPY) -O ihex $(APP).$(TGT_SUFFIX) $(APP).hex - @-$(OBJCOPY) -S -O binary $(APP).$(TGT_SUFFIX) $(APP).bin + @-$(OBJCOPY) $(APP).$(TGT_SUFFIX) -O ihex $(APP).hex + @-$(ECHO) +++ creating srec module: $(APP).s19 + @-$(OBJCOPY) $(APP).$(TGT_SUFFIX) -O srec --srec-forceS3 --srec-len=16 $(APP).s19 +else + @-$(ECHO) +++ creating hex module disabled for non-ELF absolute objet file. +endif +ifeq ($(RULE_SPECIAL_MAKE_IMAGE_FILE),) + @-$(ECHO) +++ creating special image file + @-$(ECHO) +++ disabled because there is no special image file +else + @-$(ECHO) +++ creating special image file + @-$(RULE_SPECIAL_MAKE_IMAGE_FILE) +endif +ifeq ($(RULE_SPECIAL_MAKE_FLASH_BATCH),) + @-$(ECHO) +++ creating special flash batch file + @-$(ECHO) +++ disabled because there is no special flash batch file +else + @-$(ECHO) +++ creating special flash batch file + @-$(RULE_SPECIAL_MAKE_FLASH_BATCH) +endif # ------------------------------------------------------------------------------ # Dependencyfile include (build) @@ -270,7 +324,7 @@ $(APP)_flash.hex : $(APP).$(TGT_SUFFIX) # If the files do not exist then the includes will be ignored. # ------------------------------------------------------------------------------ ifneq ($(MAKECMDGOALS),rebuild) --include $(subst .o,.d,$(FILES_O)) # for example tmp/obj/sys_start.d, tmp/obj/mcal_cpu.d, etc +-include $(subst .o,.d,$(FILES_O)) endif diff --git a/examples/chapter04_04/target/app/make/app_rules.gmk b/examples/chapter04_04/target/app/make/app_rules.gmk index 9a0de5e83..4a7bca584 100644 --- a/examples/chapter04_04/target/app/make/app_rules.gmk +++ b/examples/chapter04_04/target/app/make/app_rules.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2018. +# Copyright Christopher Kormanyos 2007 - 2024. # Distributed under the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -11,13 +11,20 @@ # # Generic pattern rules # -# Based on GNU Make 3.81 +# Based on GNU Make 4.2.1 # # 07-April-2010 # # ------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ +# GCC dependency flags. +# ------------------------------------------------------------------------------ + +DEP_FLAGS = -MMD -MF $(PATH_OBJ)/$(basename $(@F)).d + + # ------------------------------------------------------------------------------ # Rule to compile C++ source file (*.cpp) to object file (*.o). # ------------------------------------------------------------------------------ @@ -30,12 +37,29 @@ $(PATH_OBJ)/%.o : %.cpp # ...and create an assembly listing using objdump, # ...and generate a dependency file (using the -MM flag), # ...and be sure to include the path in the dependency file. - @-$(CC) $(CPPFLAGS) $(C_INCLUDES) $< -c -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err - @-$(SED) -e 's|.h:\([0-9]*\),|.h(\1) :|' -e 's|:\([0-9]*\):|(\1) :|' $(PATH_ERR)/$(basename $(@F)).err - @-$(OBJDUMP) -S -C $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_SRC)/$(basename $(@F)).lst - @-$(ECHO) -n $(PATH_OBJ)/ > $(PATH_OBJ)/$(basename $(@F)).d - @-$(CC) $(CPPFLAGS) $< -MM >> $(PATH_OBJ)/$(basename $(@F)).d + @-$(CC) $(CXXFLAGS) $(C_INCLUDES) $(DEP_FLAGS) $< -c -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err + @-$(SED) -e 's|.h:\([0-9]*\),|.h(\1) :|' -e 's|.hpp:\([0-9]*\),|.hpp(\1) :|' -e 's|.cpp:\([0-9]*\),|.cpp(\1) :|' $(PATH_ERR)/$(basename $(@F)).err +ifneq ($(findstr risc,$(GCC_TARGET)),) + @-$(OBJDUMP) -S $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_LST)/$(basename $(@F)).lst +endif + +# ------------------------------------------------------------------------------ +# Rule to compile C++ source file (*.cc) to object file (*.o). +# ------------------------------------------------------------------------------ +$(PATH_OBJ)/%.o : %.cc + @$(ECHO) +++ compile: $< to $@ + # Compile the source file, + # ...and reformat (using sed) any possible error/warning messages + # for the VisualStudio(R) output window, + # ...and create an assembly listing using objdump, + # ...and generate a dependency file (using the -MM flag), + # ...and be sure to include the path in the dependency file. + @-$(CC) $(CXXFLAGS) $(C_INCLUDES) $(DEP_FLAGS) $< -c -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err + @-$(SED) -e 's|.h:\([0-9]*\),|.h(\1) :|' -e 's|.hpp:\([0-9]*\),|.hpp(\1) :|' -e 's|.cc:\([0-9]*\),|.cc(\1) :|' $(PATH_ERR)/$(basename $(@F)).err +ifneq ($(findstr risc,$(GCC_TARGET)),) + @-$(OBJDUMP) -S $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_LST)/$(basename $(@F)).lst +endif # ------------------------------------------------------------------------------ # Rule to compile C source file (*.c) to object file (*.o). @@ -49,11 +73,9 @@ $(PATH_OBJ)/%.o : %.c # ...and create an assembly listing using objdump, # ...and generate a dependency file (using the -MM flag), # ...and be sure to include the path in the dependency file. - @-$(CC) $(CFLAGS) $(C_INCLUDES) $< -c -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err - @-$(SED) -e 's|.h:\([0-9]*\),|.h(\1) :|' -e 's|:\([0-9]*\):|(\1) :|' $(PATH_ERR)/$(basename $(@F)).err - @-$(OBJDUMP) -S $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_SRC)/$(basename $(@F)).lst - @-$(ECHO) -n $(PATH_OBJ)/ > $(PATH_OBJ)/$(basename $(@F)).d - @-$(CC) $(CFLAGS) $< -MM >> $(PATH_OBJ)/$(basename $(@F)).d + @-$(CC) $(CFLAGS) $(C_INCLUDES) $(DEP_FLAGS) $< -c -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err + @-$(SED) -e 's|.h:\([0-9]*\),|.h(\1) :|' -e 's|.c:\([0-9]*\),|.c(\1) :|' $(PATH_ERR)/$(basename $(@F)).err + @-$(OBJDUMP) -S $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_LST)/$(basename $(@F)).lst # ------------------------------------------------------------------------------ @@ -68,4 +90,4 @@ $(PATH_OBJ)/%.o : %.s # ...and create an assembly listing using objdump @-$(CC) $(AFLAGS) $(C_INCLUDES) $< -c -o $(PATH_OBJ)/$(basename $(@F)).o 2> $(PATH_ERR)/$(basename $(@F)).err @-$(SED) -e 's|:\([0-9]*\):|(\1) :|' $(PATH_ERR)/$(basename $(@F)).err - @-$(OBJDUMP) -S $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_SRC)/$(basename $(@F)).lst + @-$(OBJDUMP) -S $(PATH_OBJ)/$(basename $(@F)).o > $(PATH_LST)/$(basename $(@F)).lst diff --git a/examples/chapter04_04/target/build/build.bat b/examples/chapter04_04/target/build/build.bat index 3ca28555d..58fcd36dd 100644 --- a/examples/chapter04_04/target/build/build.bat +++ b/examples/chapter04_04/target/build/build.bat @@ -1,5 +1,5 @@ @rem -@rem Copyright Christopher Kormanyos 2007 - 2018. +@rem Copyright Christopher Kormanyos 2007 - 2024. @rem Distributed under the Boost Software License, @rem Version 1.0. (See accompanying file LICENSE_1_0.txt @rem or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,7 +10,15 @@ @rem Description of the build options used in the build command below. @rem @rem %1: target -@rem avr : ATMEL(R) AVR(R) ATmega328P i.e., Arduino compatible +@rem am335x : BeagleBone with TI(R) AM3359, creates a bare-metal binary file "MLO" +@rem avr : ATMEL(R) AVR(R) ATmega328P i.e., ARDUINO compatible +@rem bcm2835_raspi_b : RaspberryPi Zero, creates a bare-metal binary file "kernel.img" +@rem rl78 : Renesas(R) RL78 +@rem rx63n : Renesas(R) RX600 +@rem stm32f100 : ST Microelectronics STM32F100 ARM(R) Cortex(TM)-M3, STM32VLDISCOVERY board +@rem stm32f407 : ST Microelectronics STM32F407 ARM(R) Cortex(TM)-M4, STM32F4DISCOVERY board +@rem stm32f429 : ST Microelectronics STM32F429 ARM(R) Cortex(TM)-M4, 32F429IDISCOVERY board +@rem stm32f446 : ST Microelectronics STM32F446 ARM(R) Cortex(TM)-M4, 32F446-Nucleo @rem @rem %2: buildtype @rem : None. Build the project. Compile and link outdated files only. @@ -19,7 +27,7 @@ @rem @rem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -@Set build_command=tools\Util\msys64\usr\bin\make.exe -f target/app/make/app_make.gmk %2 TGT=%1 +@set build_command=tools\Util\msys64\usr\bin\make.exe -f target/app/make/app_make.gmk %2 TGT=%1 @echo Executing Command: %build_command% diff --git a/examples/chapter04_04/target/micros/avr/make/avr.ld b/examples/chapter04_04/target/micros/avr/make/avr.ld index 55f96498b..dbc793da7 100644 --- a/examples/chapter04_04/target/micros/avr/make/avr.ld +++ b/examples/chapter04_04/target/micros/avr/make/avr.ld @@ -1,6 +1,5 @@ - /* - Copyright Christopher Kormanyos 2007 - 2018. + Copyright Christopher Kormanyos 2007 - 2023. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -13,22 +12,19 @@ INPUT(libc.a libm.a libgcc.a) OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") OUTPUT_ARCH(avr:5) -/* The beginning and end of the program ROM area. */ -_rom_begin = 0x00000000; -_rom_end = 0x00007FFC; - /* The beginning and end (i.e., top) of the stack */ -/* Set up a stack with a size of (1/2)K */ -_stack_begin = 0x00800600; -_stack_end = 0x00800800; +/* Set up a stack with a size of 0x180=(3/8)K */ +_stack_begin = 0x00800780; +_stack_end = 0x00800900; /* The initial stack pointer (top of stack) is at the top of the 2K RAM */ -__initial_stack_pointer = 0x800800; +__initial_stack_pointer = 0x00800900 - 2; MEMORY { - ROM(rx) : ORIGIN = 0, LENGTH = 32K - 4 - RAM(rw!x) : ORIGIN = 0x00800100, LENGTH = 0x00000600 - 0x00000100 + VEC(rx) : ORIGIN = 0x00000000, LENGTH = 0x00000080 + ROM(rx) : ORIGIN = 0x00000080, LENGTH = 32K - 0x00000080 + RAM(rwx) : ORIGIN = 0x00800100, LENGTH = 0x00000780 - 0x00000100 } SECTIONS @@ -42,7 +38,7 @@ SECTIONS *(.isr_vector) . = ALIGN(0x10); KEEP(*(.isr_vector)) - } > ROM = 0xAAAA + } > VEC = 0x5555 /* Startup code */ .startup : @@ -71,11 +67,6 @@ SECTIONS . = ALIGN(2); } > ROM - .text : - { - . = ALIGN(0x10); - } > ROM = 0xAAAA - . = 0x00800100; . = ALIGN(2); @@ -89,7 +80,7 @@ SECTIONS *(.data*) . = ALIGN(2); KEEP (*(.data*)) - *(.rodata) /* Do *NOT* move this! Include .rodata here if gcc is used with -fdata-sections. */ + *(.rodata) /* Use special handling of rodata (i.e., as part of data since _const_ variables are stored in RAM for AVR arch). */ . = ALIGN(2); KEEP (*(.rodata)) *(.rodata*) diff --git a/examples/chapter04_04/target/micros/avr/make/avr_files.gmk b/examples/chapter04_04/target/micros/avr/make/avr_files.gmk index 126a6ef69..b98667db4 100644 --- a/examples/chapter04_04/target/micros/avr/make/avr_files.gmk +++ b/examples/chapter04_04/target/micros/avr/make/avr_files.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2018. +# Copyright Christopher Kormanyos 2007 - 2024. # Distributed under the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/examples/chapter04_04/target/micros/avr/make/avr_flags.gmk b/examples/chapter04_04/target/micros/avr/make/avr_flags.gmk index 5dd81b6bf..5713636b5 100644 --- a/examples/chapter04_04/target/micros/avr/make/avr_flags.gmk +++ b/examples/chapter04_04/target/micros/avr/make/avr_flags.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2020. +# Copyright Christopher Kormanyos 2007 - 2024. # Distributed under the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -9,27 +9,39 @@ # compiler flags for the target architecture # ------------------------------------------------------------------------------ -# See also: https://blog.zakkemble.net/avr-gcc-builds/ - -GCC_VERSION = 11.2.0 +ifneq ($(MAKE),make) +GCC_VERSION = 13.2.0 +endif GCC_TARGET = avr GCC_PREFIX = avr TGT_SUFFIX = elf -TGT_CFLAGS = -Os \ - -mmcu=atmega328p \ - -fsigned-char \ - -mrelax +TGT_ALLFLAGS = -O2 \ + -mmcu=atmega328p \ + -mrelax \ + -finline-functions \ + -finline-limit=32 \ + -fsigned-char + +ifeq ($(GCC_VERSION),13.2.0) +TGT_ALLFLAGS := $(TGT_ALLFLAGS) \ + -mdouble=32 \ + -mlong-double=64 +endif -TGT_CPPFLAGS = -std=c++11 +TGT_CFLAGS = -std=c99 \ + $(TGT_ALLFLAGS) -TGT_INCLUDES = -I$(PATH_APP)/util/STL_C++XX_stdfloat \ - -I$(PATH_APP)/util/STL +TGT_CXXFLAGS = -std=c++14 \ + $(TGT_ALLFLAGS) + +TGT_INCLUDES = -I$(PATH_APP)/util/STL TGT_AFLAGS = -TGT_LDFLAGS = -nostdlib \ - -nostartfiles \ +TGT_LDFLAGS = -nostdlib \ + -nostartfiles \ + -Wl,--gc-sections \ + -Wl,-Map,$(APP).map \ -T $(LINKER_DEFINITION_FILE) - diff --git a/examples/chapter04_04/target/micros/avr/startup/crt0.cpp b/examples/chapter04_04/target/micros/avr/startup/crt0.cpp index 03c33da6e..832c3f749 100644 --- a/examples/chapter04_04/target/micros/avr/startup/crt0.cpp +++ b/examples/chapter04_04/target/micros/avr/startup/crt0.cpp @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2021. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // // ATMEL(R) AVR(R) startup code. -// Expressed with C++ for AtmegaX by Chris. +// Expressed with C++ for atmega328p by Chris. #include diff --git a/examples/chapter04_04/target/micros/avr/startup/crt0_init_ram.cpp b/examples/chapter04_04/target/micros/avr/startup/crt0_init_ram.cpp index 58238983c..91574fcb1 100644 --- a/examples/chapter04_04/target/micros/avr/startup/crt0_init_ram.cpp +++ b/examples/chapter04_04/target/micros/avr/startup/crt0_init_ram.cpp @@ -27,34 +27,25 @@ namespace crt void crt::init_ram() { - typedef std::uint16_t memory_aligned_type; - // Copy the data segment initializers from rom-to-ram. - // Note that all data segments are aligned by 2. - const std::size_t size_data = - std::size_t( static_cast(static_cast(&_data_end)) - - static_cast(static_cast(&_data_begin))); + mcal_progmem_uintptr_t rom_source = (mcal_progmem_uintptr_t) &_rom_data_begin; - mcal_progmem_uintptr_t rom_source = reinterpret_cast(static_cast(&_rom_data_begin)); + volatile std::uint8_t* first = (volatile std::uint8_t*) &_data_begin; + volatile std::uint8_t* last = (volatile std::uint8_t*) &_data_end; - std::for_each(static_cast(static_cast(&_data_begin)), - static_cast(static_cast(&_data_begin)) + size_data, - [&rom_source](memory_aligned_type& ram_destination) - { - // Note that particular care needs to be taken to read program - // memory with the function mcal::memory::progmem::read(). + for(volatile std::uint8_t* it = first; it != last; ++it) + { + // Note that particular care needs to be taken to read program + // memory with the function mcal::memory::progmem::read(). - // Copy the data from the rom-source to the ram-destination. - ram_destination = - mcal::memory::progmem::read(rom_source); + // Copy the data from the rom-source to the ram-destination. + *it = mcal::memory::progmem::read(rom_source); - // Acquire the next 16-bit address of the rom-source. - rom_source += 2U; - }); + // Acquire the next address of the rom-source. + ++rom_source; + }; // Clear the bss segment. // Note that the bss segment is aligned by 2. - std::fill(static_cast(static_cast(&_bss_begin)), - static_cast(static_cast(&_bss_end)), - static_cast(0U)); + std::fill((std::uint8_t*) &_bss_begin, (std::uint8_t*) &_bss_end, 0U); } diff --git a/examples/chapter04_04/target/micros/avr/startup/crt1.cpp b/examples/chapter04_04/target/micros/avr/startup/crt1.cpp index 13b0b6569..788d2d2db 100644 --- a/examples/chapter04_04/target/micros/avr/startup/crt1.cpp +++ b/examples/chapter04_04/target/micros/avr/startup/crt1.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2022. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,18 +12,18 @@ extern "C" { - struct constructor_function_type + struct ctor_type { - using pointer = void(*)(void); + using function_type = void(*)(void); - using size_type = - util::utype_helper::exact_type; + using function_pointer_as_uint_type = + util::utype_helper::exact_type; - static constexpr size_type static_size = static_cast(sizeof(size_type)); + static constexpr auto function_size = static_cast(sizeof(function_pointer_as_uint_type)); }; - extern constructor_function_type::pointer _ctors_end[]; - extern constructor_function_type::pointer _ctors_begin[]; + extern ctor_type::function_type _ctors_end; + extern ctor_type::function_type _ctors_begin; } namespace crt @@ -33,19 +33,18 @@ namespace crt void crt::init_ctors() { - for(constructor_function_type::size_type rom_source - = reinterpret_cast(static_cast(_ctors_end)); - rom_source > reinterpret_cast(static_cast(_ctors_begin)); - rom_source -= constructor_function_type::static_size) + for(auto rom_source = reinterpret_cast(static_cast(&_ctors_end)); + rom_source > reinterpret_cast(static_cast(&_ctors_begin)); + rom_source -= ctor_type::function_size) { // Note that particular care needs to be taken to read program - // memory with the function mcal::cpu::read_program_memory. + // memory with the function mcal::memory::progmem::read. // Acquire the next constructor function address. - const constructor_function_type::size_type pf = - mcal::memory::progmem::read(rom_source - constructor_function_type::static_size); + const auto pf = + mcal::memory::progmem::read(rom_source - ctor_type::function_size); // Call the constructor function. - (reinterpret_cast(pf))(); + (reinterpret_cast(pf))(); } } diff --git a/examples/chapter04_04/target/micros/avr/startup/int_vect.cpp b/examples/chapter04_04/target/micros/avr/startup/int_vect.cpp index e0661ae87..32a4c3704 100644 --- a/examples/chapter04_04/target/micros/avr/startup/int_vect.cpp +++ b/examples/chapter04_04/target/micros/avr/startup/int_vect.cpp @@ -1,11 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2023. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // #include +#include #include #include @@ -22,49 +23,49 @@ void __vector_unused_irq() } } -namespace +namespace local { typedef struct struct_isr_type { typedef void(*function_type)(); - const std::uint8_t jmp[2]; // JMP instruction (0x940C): 0x0C = low byte, 0x94 = high byte. - const function_type func; // The interrupt service routine. + const std::uint8_t jmp[static_cast(UINT8_C(2))]; // JMP instruction (0x940C): 0x0C = low byte, 0x94 = high byte. + const function_type func; // The interrupt service routine. } isr_type; -} -extern "C" -const volatile std::array __isr_vector __attribute__((section(".isr_vector"))); + constexpr auto count_of_isr_vector = static_cast(UINT8_C(26)); -extern "C" -const volatile std::array __isr_vector = + using isr_vector_array_type = std::array; +} + +const volatile local::isr_vector_array_type my_isr_vector __attribute__((section(".isr_vector"))) = {{ - // addr. nr. interrupt source - { { 0x0C, 0x94 }, __my_startup }, // 0x00, 0, reset - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x02, 1, ext0 - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x04, 2, ext1 - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x06, 3, pin0 - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x08, 4, pin1 - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x0A, 5, pin2 - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x0C, 6, watchdog - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x0E, 7, timer2 cmp a - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x10, 8, timer2 cmp b - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x12, 9, timer2 ovf - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x14, 10, timer1 cap - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x16, 11, timer1 cmp a - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x18, 12, timer1 cmp b - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x1A, 13, timer1 ovf - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x1C, 14, timer0 cmp a - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x1E, 15, timer0 cmp b - { { 0x0C, 0x94 }, __vector_16 }, // 0x2E, 16, timer0 ovf - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x20, 17, spi(TM) - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x22, 18, usart rx - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x24, 19, usart err - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x26, 20, usart tx - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x28, 21, adc - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x2A, 22, eep ready - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x2C, 23, comparator - { { 0x0C, 0x94 }, __vector_unused_irq }, // 0x2E, 24, two-wire - { { 0x0C, 0x94 }, __vector_unused_irq } // 0x30, 25, spm + // address index interrupt source + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __my_startup }, // 0x00 0 reset + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x02 1 ext0 + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x04 2 ext1 + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x06 3 pin0 + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x08 4 pin1 + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x0A 5 pin2 + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x0C 6 watchdog + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x0E 7 timer2 cmp a + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x10 8 timer2 cmp b + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x12 9 timer2 ovf + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x14 10 timer1 cap + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x16 11 timer1 cmp a + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x18 12 timer1 cmp b + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x1A 13 timer1 ovf + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x1C 14 timer0 cmp a + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x1E 15 timer0 cmp b + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_16 }, // 0x2E 16 timer0 ovf + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x20 17 spi(TM) + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x22 18 usart rx + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x24 19 usart err + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x26 20 usart tx + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x28 21 adc + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x2A 22 eep ready + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x2C 23 comparator + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq }, // 0x2E 24 two-wire + { { static_cast(UINT8_C(0x0C)), static_cast(UINT8_C(0x94)) }, __vector_unused_irq } // 0x30 25 spm }};