diff --git a/examples/chapter09_08a/build.sh b/examples/chapter09_08a/build.sh index 3cfd4fef6..b280d4950 100755 --- a/examples/chapter09_08a/build.sh +++ b/examples/chapter09_08a/build.sh @@ -26,7 +26,7 @@ # ./build.sh /usr/local/real-time-cpp/examples/chapter09_08a/tools/Util/MinGW/msys/1.0/local/gcc-9.2.0-avr/bin avr # Usage example B (from Win* shell such as in Git for Win*) -# cd C:/Users/User/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter09_08a +# cd C:/Users/ckorm/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter09_08a # ./build.sh C:/Users/User/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter09_08a/tools/Util/MinGW/msys/1.0/local/gcc-9.2.0-avr/bin avr if [[ $# == 0 ]]; then ## $# is the number of arguments diff --git a/examples/chapter12_04/build.bat b/examples/chapter12_04/build.bat index 4bbd071b3..38596f52f 100644 --- a/examples/chapter12_04/build.bat +++ b/examples/chapter12_04/build.bat @@ -1,6 +1,6 @@ @rem -@rem Copyright Christopher Kormanyos 2014 - 2021. +@rem Copyright Christopher Kormanyos 2014 - 2025. @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) @@ -12,22 +12,22 @@ @rem build.bat directory_of_gcc_bin prefix_of_avr_gcc @rem Usage example A, -@rem cd "C:\Users\User\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04" +@rem cd "C:\Users\ckorm\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04" @rem build.bat "C:\Users\User\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04\tools\Util\msys64\usr\local\gcc-11.2.0-avr\bin" avr @rem Usage example A1 (use a relative tool path), -@rem cd "C:\Users\User\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04" -@rem build.bat ".\tools\Util\msys64\usr\local\gcc-11.2.0-avr\bin" avr +@rem cd "C:\Users\ckorm\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04" +@rem build.bat ".\tools\Util\msys64\usr\local\gcc-15.1.0-avr\bin" avr @rem Usage example B, -@rem cd "C:\Users\User\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04" -@rem build.bat "C:\Program Files (x86)\gcc-11.2.0-avr\bin" avr +@rem cd "C:\Users\ckorm\Documents\Ks\uC_Software\Boards\real-time-cpp\examples\chapter12_04" +@rem build.bat "C:\Program Files (x86)\gcc-15.1.0-avr\bin" avr @set TOOL_PATH=%1 @set TOOL_PREFIX=%2 -@set CFLAGS=-Wall -Wextra -pedantic -mmcu=atmega328p -fsigned-char -O2 -fno-exceptions -gdwarf-2 -ffunction-sections -fdata-sections +@set CFLAGS=-Wall -Wextra -Wpedantic -mmcu=atmega328p -fsigned-char -O2 -fno-exceptions -gdwarf-2 -ffunction-sections -fdata-sections @set CPPFLAGS=-std=c++14 -fno-rtti -fstrict-enums -fno-use-cxa-atexit -fno-use-cxa-get-exception-ptr -fno-nonansi-builtins -fno-threadsafe-statics -fno-enforce-eh-specs @set CINCLUDES=-Isrc/util/STL_C++XX_stdfloat -Isrc/util/STL -Isrc/mcal/avr -Isrc @@ -51,9 +51,6 @@ @echo.Compile : cmath_impl_gamma.cpp to bin/cmath_impl_gamma.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/util/STL/impl/cmath_impl_gamma.cpp -o bin/cmath_impl_gamma.o -@echo.Compile : avr_float_limits.cpp to bin/avr_float_limits.o -@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/util/STL/impl/avr/avr_float_limits.cpp -o bin/avr_float_limits.o - @echo.Compile : mcal.cpp to bin/mcal.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/mcal.cpp -o bin/mcal.o @@ -63,6 +60,9 @@ @echo.Compile : mcal_cpu.cpp to bin/mcal_cpu.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_cpu.cpp -o bin/mcal_cpu.o +@echo.Compile : mcal_eep.cpp to bin/mcal_eep.o +@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_eep.cpp -o bin/mcal_eep.o + @echo.Compile : mcal_gpt.cpp to bin/mcal_gpt.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_gpt.cpp -o bin/mcal_gpt.o @@ -78,15 +78,18 @@ @echo.Compile : mcal_port.cpp to bin/mcal_port.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_port.cpp -o bin/mcal_port.o +@echo.Compile : mcal_pwm.cpp to bin/mcal_pwm.o +@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_pwm.cpp -o bin/mcal_pwm.o + +@echo.Compile : mcal_spi.cpp to bin/mcal_spi.o +@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_spi.cpp -o bin/mcal_spi.o + @echo.Compile : mcal_wdg.cpp to bin/mcal_wdg.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_wdg.cpp -o bin/mcal_wdg.o @echo.Compile : os.cpp to bin/os.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/os/os.cpp -o bin/os.o -@echo.Compile : os.cpp to bin/os_task_control_block.o -@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/os/os_task_control_block.cpp -o bin/os_task_control_block.o - @echo.Compile : sys_idle.cpp to bin/sys_idle.o @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/sys/idle/sys_idle.cpp -o bin/sys_idle.o @@ -109,7 +112,7 @@ @%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c target/micros/avr/startup/int_vect.cpp -o bin/int_vect.o @echo.Link : objects to bin/chapter12_04.elf -@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x none -mrelax -nostartfiles %CFLAGS% %CPPFLAGS% %CINCLUDES% -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter12_04.map bin/app_benchmark.o bin/app_led.o bin/cmath_impl_gamma.o bin/avr_float_limits.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_gpt.o bin/mcal_irq.o bin/mcal_led.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_wdg.o bin/os.o bin/os_task_control_block.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter12_04.elf +@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x none -mrelax -nostartfiles %CFLAGS% %CPPFLAGS% %CINCLUDES% -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter12_04.map bin/app_benchmark.o bin/app_led.o bin/cmath_impl_gamma.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_eep.o bin/mcal_gpt.o bin/mcal_irq.o bin/mcal_led.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_pwm.o bin/mcal_spi.o bin/mcal_wdg.o bin/os.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter12_04.elf @echo. @echo.Extract : executable hex file : from bin/chapter12_04.elf @@ -127,8 +130,7 @@ @echo.Extract : demangled names : from bin/chapter12_04.elf @%TOOL_PATH%\%TOOL_PREFIX%-nm --numeric-sort --print-size bin/chapter12_04.elf | %TOOL_PATH%\%TOOL_PREFIX%-c++filt > bin\chapter12_04_cppfilt.txt -dir .\bin\chapter12_04.elf -dir .\bin\chapter12_04.hex +dir .\bin\chapter12_04.elf .\bin\chapter12_04.hex if not exist .\bin\chapter12_04.elf exit 1 if not exist .\bin\chapter12_04.hex exit 1 diff --git a/examples/chapter12_04/build.sh b/examples/chapter12_04/build.sh index ef9bf9e9a..80b4d497f 100755 --- a/examples/chapter12_04/build.sh +++ b/examples/chapter12_04/build.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright Christopher Kormanyos 2014 - 2020. +# Copyright Christopher Kormanyos 2014 - 2025. # 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) @@ -26,8 +26,8 @@ # ./build.sh /usr/local/real-time-cpp/examples/chapter12_04/tools/Util/MinGW/msys/1.0/local/gcc-9.2.0-avr/bin avr # Usage example B (from Win* shell such as in Git for Win*) -# cd C:/Users/User/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter12_04 -# ./build.sh C:/Users/User/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter12_04/tools/Util/MinGW/msys/1.0/local/gcc-9.2.0-avr/bin avr +# cd C:/Users/ckorm/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter12_04 +# ./build.sh C:/Users/User/Documents/Ks/uC_Software/Boards/real-time-cpp/examples/chapter12_04/tools/Util/MinGW/msys/1.0/local/gcc-15.1.0-avr/bin avr if [[ $# == 0 ]]; then ## $# is the number of arguments if [[ -n "$(which avr-g++)" ]]; then ## -n tests if string is not empty @@ -70,9 +70,6 @@ $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/app/led/a echo "Compile : cmath_impl_gamma.cpp to bin/cmath_impl_gamma.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/util/STL/impl/cmath_impl_gamma.cpp -o bin/cmath_impl_gamma.o -echo "Compile : avr_float_limits.cpp to bin/avr_float_limits.o" -$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/util/STL/impl/avr/avr_float_limits.cpp -o bin/avr_float_limits.o - echo "Compile : mcal.cpp to bin/mcal.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/mcal.cpp -o bin/mcal.o @@ -82,6 +79,9 @@ $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/mcal echo "Compile : mcal_cpu.cpp to bin/mcal_cpu.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_cpu.cpp -o bin/mcal_cpu.o +echo "Compile : mcal_eep.cpp to bin/mcal_eep.o" +$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_eep.cpp -o bin/mcal_eep.o + echo "Compile : mcal_gpt.cpp to bin/mcal_gpt.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_gpt.cpp -o bin/mcal_gpt.o @@ -100,12 +100,15 @@ $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/ echo "Compile : mcal_wdg.cpp to bin/mcal_wdg.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_wdg.cpp -o bin/mcal_wdg.o +echo "Compile : mcal_pwm.cpp to bin/mcal_pwm.o" +$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_pwm.cpp -o bin/mcal_pwm.o + +echo "Compile : mcal_spi.cpp to bin/mcal_spi.o" +$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_spi.cpp -o bin/mcal_spi.o + echo "Compile : os.cpp to bin/os.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/os/os.cpp -o bin/os.o -echo "Compile : os.cpp to bin/os_task_control_block.o". -$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/os/os_task_control_block.cpp -o bin/os_task_control_block.o - echo "Compile : sys_idle.cpp to bin/sys_idle.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/sys/idle/sys_idle.cpp -o bin/sys_idle.o @@ -128,7 +131,7 @@ echo "Compile : int_vect.cpp to bin/int_vect.o" $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c target/micros/avr/startup/int_vect.cpp -o bin/int_vect.o echo "Link : objects to bin/chapter12_04.elf" -$TOOL_PATH/$TOOL_PREFIX-g++ -x none -mrelax -nostartfiles $CFLAGS $CPPFLAGS $CINCLUDES -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter12_04.map bin/app_benchmark.o bin/app_led.o bin/cmath_impl_gamma.o bin/avr_float_limits.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_gpt.o bin/mcal_irq.o bin/mcal_led.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_wdg.o bin/os.o bin/os_task_control_block.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter12_04.elf +$TOOL_PATH/$TOOL_PREFIX-g++ -x none -mrelax -nostartfiles $CFLAGS $CPPFLAGS $CINCLUDES -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter12_04.map bin/app_benchmark.o bin/app_led.o bin/cmath_impl_gamma.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_eep.o bin/mcal_gpt.o bin/mcal_irq.o bin/mcal_led.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_pwm.o bin/mcal_spi.o bin/mcal_wdg.o bin/os.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter12_04.elf echo echo "Extract : executable hex file : from bin/chapter12_04.elf" diff --git a/examples/chapter12_04/chapter12_04.cppproj b/examples/chapter12_04/chapter12_04.cppproj index a43857226..e7f78bcb0 100644 --- a/examples/chapter12_04/chapter12_04.cppproj +++ b/examples/chapter12_04/chapter12_04.cppproj @@ -42,15 +42,15 @@ 2 - - - - - - - - - + + + + + + + + + 0 @@ -199,6 +199,12 @@ compile + + compile + + + compile + compile @@ -232,9 +238,39 @@ compile + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + compile + + compile + + + compile + + + compile + compile @@ -286,9 +322,6 @@ compile - - compile - compile @@ -319,15 +352,18 @@ compile - + compile - + compile compile + + compile + compile @@ -417,12 +453,30 @@ compile + + compile + + + compile + + + compile + compile + + compile + compile + + compile + + + compile + compile @@ -444,6 +498,9 @@ compile + + compile + compile @@ -465,9 +522,21 @@ compile + + compile + compile + + compile + + + compile + + + compile + compile @@ -483,6 +552,9 @@ compile + + compile + compile diff --git a/examples/chapter12_04/chapter12_04.vcxproj b/examples/chapter12_04/chapter12_04.vcxproj index a9bfff67e..4dc58b07d 100644 --- a/examples/chapter12_04/chapter12_04.vcxproj +++ b/examples/chapter12_04/chapter12_04.vcxproj @@ -178,6 +178,10 @@ true true + + true + true + true true @@ -198,6 +202,14 @@ true true + + true + true + + + true + true + true true @@ -207,13 +219,18 @@ true true + + + + + + - @@ -240,6 +257,10 @@ true true + + true + true + true true @@ -264,10 +285,22 @@ true true + + true + true + true true + + true + true + + + true + true + true true @@ -276,14 +309,27 @@ + + + + + + + + + + + + + @@ -291,6 +337,12 @@ + + + + + + diff --git a/examples/chapter12_04/chapter12_04.vcxproj.filters b/examples/chapter12_04/chapter12_04.vcxproj.filters index db210cf22..9c37c7f4d 100644 --- a/examples/chapter12_04/chapter12_04.vcxproj.filters +++ b/examples/chapter12_04/chapter12_04.vcxproj.filters @@ -73,6 +73,15 @@ {df5781cb-9e5b-4f3c-8e93-6f82e1d6c93f} + + {51e8332d-263d-4033-9812-c48cb215117f} + + + {2e764459-477f-497d-a7f3-b436e975e679} + + + {9df4229f-ee8f-4a42-96c3-868db9f071a2} + @@ -84,9 +93,6 @@ src\os - - src\os - src\sys\idle @@ -96,9 +102,27 @@ src\mcal + + src\util\STL\impl\avr + + + src\util\STD_LIBC + + + src\app\led + + + src\app\benchmark + + + src\util\STL\impl + src\mcal\avr + + src\mcal\avr + src\mcal\avr @@ -114,37 +138,46 @@ src\mcal\avr + + src\mcal\avr + + + src\mcal\avr + src\mcal\avr - + src\mcal\win32 - + src\mcal\win32 - + src\mcal\win32 - + src\mcal\win32 - - src\util\STL\impl\avr + + src\mcal\win32 - - src\util\STD_LIBC + + src\mcal\win32 - - src\app\led + + src\mcal\win32 - - src\app\benchmark + + src\mcal\win32 - - src\util\STL\impl + + src\mcal\win32 - + + src\mcal\win32 + + src\mcal\win32 @@ -203,48 +236,6 @@ src\os - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\avr - - - src\mcal\win32 - - - src\mcal\win32 - - - src\mcal\win32 - - - src\mcal\win32 - - - src\mcal\win32 - - - src\mcal\win32 - src\util\utility @@ -284,15 +275,6 @@ src\util\memory - - src\mcal\avr - - - src\mcal\win32 - - - src\mcal\win32 - src\math\functions @@ -326,15 +308,135 @@ src\mcal_memory + + src\mcal_led + + + src\mcal_led + + + src\mcal_led + + + src\mcal_led + + + src\mcal_led + + + src\mcal_led + + + src\mcal_led + + + src\mcal_led + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + src\mcal\avr + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\avr + + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + src\mcal\win32 + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + src\mcal\win32 + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal\win32 + + + src\mcal_pwm + + + src\mcal_pwm + + + src\mcal_pwm + + + src\mcal_pwm + + + src\mcal_spi + + + src\mcal_spi + diff --git a/examples/chapter12_04/src/app/led/app_led.cpp b/examples/chapter12_04/src/app/led/app_led.cpp index f7bf6e7ff..d6fe2e326 100644 --- a/examples/chapter12_04/src/app/led/app_led.cpp +++ b/examples/chapter12_04/src/app/led/app_led.cpp @@ -1,6 +1,5 @@ - /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,33 +8,46 @@ #include #include -namespace app +namespace app { namespace led { + +auto task_init() -> void; +auto task_func() -> void; + +} // namespace led +} // namespace app + +namespace local { - namespace led - { - void task_init(); - void task_func(); - } -} + using app_led_timer_type = util::timer; + + using app_led_tick_type = typename app_led_timer_type::tick_type; + + auto app_led_timer() noexcept -> app_led_timer_type&; -namespace + constexpr app_led_tick_type app_led_delay { app_led_timer_type::seconds(app_led_tick_type{ UINT8_C(1) }) }; +} // namespace local + +auto local::app_led_timer() noexcept -> app_led_timer_type& { - typedef util::timer timer_type; + static app_led_timer_type local_app_led_timer + { + local::app_led_delay + }; - timer_type app_led_timer(timer_type::seconds(1U)); + return local_app_led_timer; } -void app::led::task_init() +auto app::led::task_init() -> void { - mcal::led::led0.toggle(); + mcal::led::led0().toggle(); } -void app::led::task_func() +auto app::led::task_func() -> void { - if(app_led_timer.timeout()) + if(local::app_led_timer().timeout()) { - app_led_timer.start_interval(timer_type::seconds(1U)); + local::app_led_timer().start_interval(local::app_led_delay); - mcal::led::led0.toggle(); + mcal::led::led0().toggle(); } } diff --git a/examples/chapter12_04/src/math/constants/constants.h b/examples/chapter12_04/src/math/constants/constants.h index 9ff6836b2..f0d473c73 100644 --- a/examples/chapter12_04/src/math/constants/constants.h +++ b/examples/chapter12_04/src/math/constants/constants.h @@ -1,14 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2012 - 2018. +// Copyright Christopher Kormanyos 2012 - 2025. // 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 CONSTANTS_2012_01_09_H_ - #define CONSTANTS_2012_01_09_H_ - - #include +#ifndef CONSTANTS_2012_01_09_H + #define CONSTANTS_2012_01_09_H namespace math { @@ -17,69 +15,69 @@ template float_type root_two() { - return static_cast(FLOATMAX_C(1.4142135623730950488016887242096980785697)); + return static_cast(1.4142135623730950488016887242096980785697L); } template float_type pi() { - return static_cast(FLOATMAX_C(3.1415926535897932384626433832795028841972)); + return static_cast(3.1415926535897932384626433832795028841972L); } template float_type half_pi() { - return static_cast(FLOATMAX_C(1.5707963267948966192313216916397514420986)); + return static_cast(1.5707963267948966192313216916397514420986L); } template float_type root_pi() { - return static_cast(FLOATMAX_C(1.7724538509055160272981674833411451827975)); + return static_cast(1.7724538509055160272981674833411451827975L); } template float_type ln_two() { - return static_cast(FLOATMAX_C(0.6931471805599453094172321214581765680755)); + return static_cast(0.6931471805599453094172321214581765680755L); } template float_type e() { - return static_cast(FLOATMAX_C(2.7182818284590452353602874713526624977572)); + return static_cast(2.7182818284590452353602874713526624977572L); } template float_type euler() { - return static_cast(FLOATMAX_C(0.5772156649015328606065120900824024310422)); + return static_cast(0.5772156649015328606065120900824024310422L); } template float_type zeta_three() { - return static_cast(FLOATMAX_C(1.2020569031595942853997381615114499907650)); + return static_cast(1.2020569031595942853997381615114499907650L); } template float_type catalan() { - return static_cast(FLOATMAX_C(0.91596559417721901505460351493238411077415)); + return static_cast(0.91596559417721901505460351493238411077415L); } template float_type glaisher() { - return static_cast(FLOATMAX_C(1.2824271291006226368753425688697917277677)); + return static_cast(1.2824271291006226368753425688697917277677L); } template float_type khinchin() { - return static_cast(FLOATMAX_C(2.6854520010653064453097148354817956938204)); + return static_cast(2.6854520010653064453097148354817956938204L); } } } -#endif // CONSTANTS_2012_01_09_H_ +#endif // CONSTANTS_2012_01_09_H diff --git a/examples/chapter12_04/src/math/functions/math_functions_bessel.h b/examples/chapter12_04/src/math/functions/math_functions_bessel.h index b18131966..20bf91a1c 100644 --- a/examples/chapter12_04/src/math/functions/math_functions_bessel.h +++ b/examples/chapter12_04/src/math/functions/math_functions_bessel.h @@ -1,16 +1,14 @@ - /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2018. +// Copyright Christopher Kormanyos 2014 - 2025. // 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 MATH_FUNCTIONS_BESSEL_2014_04_30_H_ - #define MATH_FUNCTIONS_BESSEL_2014_04_30_H_ +#ifndef MATH_FUNCTIONS_BESSEL_2014_04_30_H + #define MATH_FUNCTIONS_BESSEL_2014_04_30_H #include - #include #include @@ -38,4 +36,4 @@ } } // namespace math::functions -#endif // MATH_FUNCTIONS_BESSEL_2014_04_30_H_ +#endif // MATH_FUNCTIONS_BESSEL_2014_04_30_H diff --git a/examples/chapter12_04/src/math/functions/math_functions_hypergeometric.h b/examples/chapter12_04/src/math/functions/math_functions_hypergeometric.h index fa10d6c45..02cf779f1 100644 --- a/examples/chapter12_04/src/math/functions/math_functions_hypergeometric.h +++ b/examples/chapter12_04/src/math/functions/math_functions_hypergeometric.h @@ -1,32 +1,33 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2018. +// Copyright Christopher Kormanyos 2014 - 2025. // 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 MATH_FUNCTIONS_HYPERGEOMETRIC_2014_04_29_H_ - #define MATH_FUNCTIONS_HYPERGEOMETRIC_2014_04_29_H_ +#ifndef MATH_FUNCTIONS_HYPERGEOMETRIC_2014_04_29_H + #define MATH_FUNCTIONS_HYPERGEOMETRIC_2014_04_29_H + + #include + #include #include #include + #include #include #include #include #include #include - #include - #include - namespace math { namespace functions { template - T hypergeometric_0f1(T b, - T x, - T tolerance = std::numeric_limits::epsilon() * T(10)) + auto hypergeometric_0f1(T b, + T x, + T tolerance = std::numeric_limits::epsilon() * T(10)) -> T { // Compute the Taylor series representation of hypergeometric_0f1. // There are no checks on input range or parameter boundaries. @@ -47,7 +48,7 @@ for(n = static_cast(2U); n < max_iteration; ++n) { x_pow_n_div_n_fact *= x; - x_pow_n_div_n_fact /= n; + x_pow_n_div_n_fact = static_cast(x_pow_n_div_n_fact / static_cast(n)); ++bp; @@ -69,22 +70,22 @@ } template - T hypergeometric_2f1(T a, - T b, - T c, - T x, - T tolerance = std::numeric_limits::epsilon() * T(10)) + auto hypergeometric_2f1(T a, + T b, + T c, + T x, + T tolerance = std::numeric_limits::epsilon() * T(10)) -> T { // Compute the Taylor series representation of hypergeometric_2f1. // There are no checks on input range or parameter boundaries. - T x_pow_n_div_n_fact (x); - T pochhammer_sequence_a(a); - T pochhammer_sequence_b(b); - T pochhammer_sequence_c(c); - T ap (a); - T bp (b); - T cp (c); + T x_pow_n_div_n_fact { x }; + T pochhammer_sequence_a { a }; + T pochhammer_sequence_b { b }; + T pochhammer_sequence_c { c }; + T ap { a }; + T bp { b }; + T cp { c }; T hypergeometric_2f1_result = T(1) + (((pochhammer_sequence_a * pochhammer_sequence_b) / pochhammer_sequence_c) * x_pow_n_div_n_fact); @@ -96,7 +97,7 @@ for(n = static_cast(2U); n < max_iteration; ++n) { x_pow_n_div_n_fact *= x; - x_pow_n_div_n_fact /= n; + x_pow_n_div_n_fact = static_cast(x_pow_n_div_n_fact / static_cast(n)); ++ap; ++bp; @@ -124,12 +125,12 @@ template - T hypergeometric_pfq(iterator_a_type coefficients_a_begin, - iterator_a_type coefficients_a_end, - iterator_b_type coefficients_b_begin, - iterator_b_type coefficients_b_end, - T x, - T tolerance = std::numeric_limits::epsilon() * T(10)) + auto hypergeometric_pfq(iterator_a_type coefficients_a_begin, + iterator_a_type coefficients_a_end, + iterator_b_type coefficients_b_begin, + iterator_b_type coefficients_b_end, + T x, + T tolerance = std::numeric_limits::epsilon() * T(10)) -> T { const std::ptrdiff_t count_of_a_terms = std::distance(coefficients_a_begin, coefficients_a_end); const std::ptrdiff_t count_of_b_terms = std::distance(coefficients_b_begin, coefficients_b_end); @@ -160,10 +161,10 @@ T x_pow_n_div_n_fact(x); // Define an allocator type for use in the containers below. - typedef util::ring_allocator allocator_type; + using allocator_type = util::ring_allocator; // Define a container type for the upcoming calculation. - typedef util::dynamic_array container_type; + using container_type = util::dynamic_array; // The pochhammer symbols for the multiplications in the series expansion // will be stored in non-constant STL vectors. @@ -191,26 +192,20 @@ T hypergeometric_pfq_result = my_one + first_term; - std::uint_fast16_t n; + std::uint_fast16_t n { }; // Calculate the maximum number of iterations allowed. - const std::uint_fast16_t max_iteration = - static_cast(std::numeric_limits::digits10 * 10); + const std::uint_fast16_t max_iteration = static_cast(std::numeric_limits::digits10 * 10); for(n = static_cast(2U); n < max_iteration; ++n) { x_pow_n_div_n_fact *= x; - x_pow_n_div_n_fact /= n; + x_pow_n_div_n_fact = static_cast(x_pow_n_div_n_fact / static_cast(n)); - if(count_of_a_terms_is_zero == false) + if(!count_of_a_terms_is_zero) { // Increment each of the pochhammer elements in {an}. - std::for_each(an.begin(), - an.end(), - [](T& a) - { - ++a; - }); + std::for_each(an.begin(), an.end(), [](T& a) { ++a; }); // Multiply the pochhammer product terms with the products of the // incremented pochhammer elements. This is a product of the form: @@ -218,15 +213,10 @@ pochhammer_sequence_a *= std::accumulate(an.begin(), an.end(), my_one, std::multiplies()); } - if(count_of_b_terms_is_zero == false) + if(!count_of_b_terms_is_zero) { // Increment each of the pochhammer elements in {bm}. - std::for_each(bm.begin(), - bm.end(), - [](T& b) - { - ++b; - }); + std::for_each(bm.begin(), bm.end(), [](T& b) { ++b; }); // Multiply the pochhammer product terms with the products of the // incremented pochhammer elements. This is a product of the form: @@ -244,7 +234,7 @@ using std::fabs; - if((n > UINT16_C(5)) && (fabs(next_term) < tolerance)) + if((n > UINT16_C(3)) && (fabs(next_term) < tolerance)) { break; } @@ -257,4 +247,4 @@ } } // namespace math::functions -#endif // MATH_FUNCTIONS_HYPERGEOMETRIC_2014_04_29_H_ +#endif // MATH_FUNCTIONS_HYPERGEOMETRIC_2014_04_29_H diff --git a/examples/chapter12_04/src/math/functions/math_functions_legendre.h b/examples/chapter12_04/src/math/functions/math_functions_legendre.h index 1951d37ee..86f6f3e7a 100644 --- a/examples/chapter12_04/src/math/functions/math_functions_legendre.h +++ b/examples/chapter12_04/src/math/functions/math_functions_legendre.h @@ -1,16 +1,14 @@ - /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2018. +// Copyright Christopher Kormanyos 2014 - 2025. // 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 MATH_FUNCTIONS_LEGENDRE_2014_04_30_H_ - #define MATH_FUNCTIONS_LEGENDRE_2014_04_30_H_ +#ifndef MATH_FUNCTIONS_LEGENDRE_2014_04_30_H + #define MATH_FUNCTIONS_LEGENDRE_2014_04_30_H #include - #include #include @@ -21,9 +19,7 @@ template T legendre_p(T v, T u, T x) { - // Compute the Taylor series representation of legendre_p - // on the real axis within the unit circle. - + // Compute the Taylor series representation of legendre_p. // There are no checks on input range or parameter boundaries. const T my_one(1); @@ -49,4 +45,4 @@ } } // namespace math::functions -#endif // MATH_FUNCTIONS_LEGENDRE_2014_04_30_H_ +#endif // MATH_FUNCTIONS_LEGENDRE_2014_04_30_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_benchmark.h b/examples/chapter12_04/src/mcal/avr/mcal_benchmark.h index e573589de..bef2f15db 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_benchmark.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_benchmark.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014. +// Copyright Christopher Kormanyos 2014 - 2025. // 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,18 +8,19 @@ #ifndef MCAL_BENCHMARK_2014_04_16_H_ #define MCAL_BENCHMARK_2014_04_16_H_ - #include #include #include + #include + namespace mcal { namespace benchmark { - typedef mcal::port::port_pin benchmark_port_type; + using benchmark_port_type = mcal::port::port_pin; } } diff --git a/examples/chapter12_04/src/mcal/avr/mcal_cpu.cpp b/examples/chapter12_04/src/mcal/avr/mcal_cpu.cpp index 563fa3ca9..3f5184e27 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_cpu.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_cpu.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,7 +10,7 @@ #include #include -void mcal::cpu::init() +auto mcal::cpu::init() -> void { mcal::wdg::init(nullptr); mcal::port::init(nullptr); diff --git a/examples/chapter12_04/src/mcal/avr/mcal_cpu.h b/examples/chapter12_04/src/mcal/avr/mcal_cpu.h index 628cdd28e..0c8cb16c9 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_cpu.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_cpu.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_CPU_2009_02_14_H_ - #define MCAL_CPU_2009_02_14_H_ +#ifndef MCAL_CPU_2009_02_14_H + #define MCAL_CPU_2009_02_14_H #include @@ -16,10 +16,10 @@ { void init(); - inline void post_init() { } + inline auto post_init() -> void { } - inline void nop() noexcept { asm volatile("nop"); } + inline auto nop() noexcept -> void { asm volatile("nop"); } } } -#endif // MCAL_CPU_2009_02_14_H_ +#endif // MCAL_CPU_2009_02_14_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_eep.cpp b/examples/chapter12_04/src/mcal/avr/mcal_eep.cpp new file mode 100644 index 000000000..1a36498c9 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_eep.cpp @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2018 - 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) +// + +#include +#include +#include + +namespace local +{ + auto mcal_eep_is_busy() -> bool; + + auto mcal_eep_is_busy() -> bool + { + return (mcal::reg::reg_access_static::bit_get()); + } +} // namespace local + +auto mcal::eep::init(const config_type*) -> void +{ +} + +auto mcal::eep::write(const address_type addr, const std::uint8_t data) -> void +{ + while(local::mcal_eep_is_busy()) + { + mcal::cpu::nop(); + } + + // Write the address register. + mcal::reg::reg_access_dynamic::reg_set(mcal::reg::eear, addr); + + // Write the data register. + mcal::reg::reg_access_dynamic::reg_set(mcal::reg::eedr, data); + + // Set eecr.eempe (bit 2). + mcal::reg::reg_access_static::bit_set(); + + // Set eecr.eepe (bit 1). + mcal::reg::reg_access_static::bit_set(); +} + +auto mcal::eep::read(const address_type addr) -> std::uint8_t +{ + while(local::mcal_eep_is_busy()) + { + mcal::cpu::nop(); + } + + // Write the address register. + mcal::reg::reg_access_dynamic::reg_set(mcal::reg::eear, addr); + + // Set eecr.eere (bit 0). + mcal::reg::reg_access_static::bit_set(); + + // Read one data byte. + const std::uint8_t data = + mcal::reg::reg_access_static::reg_get(); + + return data; +} + +/* +#define EERE 0 +#define EEPE 1 +#define EEMPE 2 +#define EERIE 3 +#define EEPM0 4 +#define EEPM1 5 +*/ + +/* +while(EECR & (1 << EEPE)); +EEAR = uiAddress; +EEDR = ucData; +EECR |= 1 << EEMPE; +EECR |= 1 << EEPE; +*/ + +/* + while (EECR & (1 << EEPE)); + EEAR = uiAddress; + EECR |= (1 << EERE); + return EEDR; +*/ diff --git a/examples/chapter12_04/src/mcal/avr/mcal_eep.h b/examples/chapter12_04/src/mcal/avr/mcal_eep.h new file mode 100644 index 000000000..aa875539a --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_eep.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2018 - 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_EEP_2018_12_15_H + #define MCAL_EEP_2018_12_15_H + + #include + + namespace mcal + { + namespace eep + { + using config_type = void; + using address_type = std::uint_fast16_t; + + auto init(const config_type*) -> void; + + auto write(const address_type addr, const std::uint8_t data)-> void; + auto read (const address_type addr) -> std::uint8_t; + } + } + +#endif // MCAL_EEP_2018_12_15_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_gpt.cpp b/examples/chapter12_04/src/mcal/avr/mcal_gpt.cpp index f2745cc63..1c715a12b 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_gpt.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_gpt.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2015. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,55 +8,101 @@ #include #include +#include + namespace { // The one (and only one) system tick. - mcal::gpt::value_type system_tick; + volatile auto mcal_gpt_system_tick = mcal::gpt::value_type { }; + + auto gpt_is_initialized() -> bool& ATTRIBUTE(used, noinline); + + auto gpt_is_initialized() -> bool& + { + static auto is_init = bool { }; + + return is_init; + } } extern "C" -void __vector_16() __attribute__((signal, used, externally_visible)); +auto __vector_16() -> void ATTRIBUTE(signal, used, externally_visible); -void __vector_16() +auto __vector_16() -> void { - // Increment the 32-bit system tick with 0x80, representing 128 microseconds. - system_tick += static_cast(0x80U); + // Increment the 32-bit system tick with 0x100, representing 256 [(1/2) us]. + // This is basically the roll-over of the 8-bit timer0 at 2MHz each 128us. + + const auto new_tick = + static_cast + ( + mcal_gpt_system_tick + static_cast(UINT16_C(0x100)) + ); + + mcal_gpt_system_tick = new_tick; } -void mcal::gpt::init(const config_type*) +auto mcal::gpt::init(const config_type*) -> void { - // Clear the timer0 overflow flag. - mcal::reg::reg_access_static::reg_set(); + if(!gpt_is_initialized()) + { + // Clear the timer0 overflow flag. + mcal::reg::reg_access_static(UINT8_C(0x01))>::reg_set(); - // Enable the timer0 overflow interrupt. - mcal::reg::reg_access_static::reg_set(); + // Enable the timer0 overflow interrupt. + mcal::reg::reg_access_static(UINT8_C(0x01))>::reg_set(); - // Set the timer0 clock source to f_osc/8 = 2MHz and begin counting. - mcal::reg::reg_access_static::reg_set(); + // Set the timer0 clock source to f_osc/8 = 2MHz and begin counting. + mcal::reg::reg_access_static(UINT8_C(0x02))>::reg_set(); + + // Set the is-initialized indication flag. + gpt_is_initialized() = true; + } } -mcal::gpt::value_type mcal::gpt::secure::get_time_elapsed() +auto mcal::gpt::secure::get_time_elapsed() -> mcal::gpt::value_type { - // Return the system tick using a multiple read to ensure data consistency. + if(gpt_is_initialized()) + { + // Return the system tick using a multiple read to ensure data consistency. + + using timer_address_type = std::uint8_t; + using timer_register_type = std::uint8_t; - typedef std::uint8_t timer_address_type; - typedef std::uint8_t timer_register_type; + // Do the first read of the timer0 counter and the system tick. + const auto t0_cnt_1 = mcal::reg::reg_access_static::reg_get(); + const auto sys_tick_1 = mcal_gpt_system_tick; - // Do the first read of the timer0 counter and the system tick. - const timer_register_type tim0_cnt_1 = mcal::reg::reg_access_static::reg_get(); - const mcal::gpt::value_type sys_tick_1 = system_tick; + // Do the second read of the timer0 counter. + const auto t0_cnt_2 = mcal::reg::reg_access_static::reg_get(); - // Do the second read of the timer0 counter. - const timer_register_type tim0_cnt_2 = mcal::reg::reg_access_static::reg_get(); + const auto t0_tick_is_consistent = (t0_cnt_2 >= t0_cnt_1); - // Perform the consistency check. - const mcal::gpt::value_type consistent_microsecond_tick - = ((tim0_cnt_2 >= tim0_cnt_1) ? mcal::gpt::value_type(sys_tick_1 | std::uint8_t(tim0_cnt_1 >> 1U)) - : mcal::gpt::value_type(system_tick | std::uint8_t(tim0_cnt_2 >> 1U))); + // Perform the consistency check. + const auto consistent_half_microsecond_tick = + static_cast + ( + t0_tick_is_consistent ? static_cast(sys_tick_1 | t0_cnt_1) + : static_cast(mcal_gpt_system_tick | t0_cnt_2) + ); - return consistent_microsecond_tick; + // Scale the timer0 tick to 1MHz and perform a rounding correction. + return + static_cast + ( + static_cast + ( + static_cast + ( + static_cast(consistent_half_microsecond_tick) + + static_cast(UINT8_C(1)) + ) + / static_cast(UINT8_C(2)) + ) + ); + } + else + { + return static_cast(UINT8_C(0)); + } } diff --git a/examples/chapter12_04/src/mcal/avr/mcal_gpt.h b/examples/chapter12_04/src/mcal/avr/mcal_gpt.h index 7ac3c2eb2..ce3a093e4 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_gpt.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_gpt.h @@ -1,44 +1,29 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. // 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_GPT_2011_10_20_H_ - #define MCAL_GPT_2011_10_20_H_ +#ifndef MCAL_GPT_2011_10_20_H + #define MCAL_GPT_2011_10_20_H - #include #include - #include - - // Forward declaration of the util::timer template class. - namespace util - { - template - class timer; - } - namespace mcal { namespace gpt { - typedef void config_type; - typedef std::uint32_t value_type; + using config_type = void; + using value_type = std::uint64_t; - void init(const config_type*); + auto init(const config_type*) -> void; - class secure final + struct secure final { - static value_type get_time_elapsed(); - - friend std::chrono::high_resolution_clock::time_point std::chrono::high_resolution_clock::now() UTIL_NOEXCEPT; - - template - friend class util::timer; + static auto get_time_elapsed() -> value_type; }; } } -#endif // MCAL_GPT_2011_10_20_H_ +#endif // MCAL_GPT_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_irq.cpp b/examples/chapter12_04/src/mcal/avr/mcal_irq.cpp index f9f983c47..5e60cf497 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_irq.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_irq.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,7 +7,7 @@ #include -void mcal::irq::init(const config_type*) +auto mcal::irq::init(const config_type*) -> void { mcal::irq::enable_all(); } diff --git a/examples/chapter12_04/src/mcal/avr/mcal_irq.h b/examples/chapter12_04/src/mcal/avr/mcal_irq.h index 4f650ed54..1adbd9536 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_irq.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_irq.h @@ -1,24 +1,24 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_IRQ_2010_04_10_H_ - #define MCAL_IRQ_2010_04_10_H_ +#ifndef MCAL_IRQ_2010_04_10_H + #define MCAL_IRQ_2010_04_10_H namespace mcal { namespace irq { - typedef void config_type; + using config_type = void; - void init(const config_type*); + auto init(const config_type*) -> void; - inline void enable_all () { asm volatile("sei"); } - inline void disable_all() { asm volatile("cli"); } + inline auto enable_all () noexcept -> void { asm volatile("sei"); } + inline auto disable_all() noexcept -> void { asm volatile("cli"); } } } -#endif // MCAL_IRQ_2010_04_10_H_ +#endif // MCAL_IRQ_2010_04_10_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_led.cpp b/examples/chapter12_04/src/mcal/avr/mcal_led.cpp index 3600a46db..d6ffb6b08 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_led.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_led.cpp @@ -1,16 +1,23 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // #include +#include -namespace mcal +auto mcal::led::led0() -> mcal::led::led_base& { - namespace led - { - const led_type led0; - } + using led0_port_type = mcal::port::port_pin; + + using led0_led_type = mcal::led::led_port; + + static led0_led_type l0; + + return l0; } diff --git a/examples/chapter12_04/src/mcal/avr/mcal_led.h b/examples/chapter12_04/src/mcal/avr/mcal_led.h index 9075f2805..6d939fec3 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_led.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_led.h @@ -1,57 +1,21 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef MCAL_LED_2010_09_14_H_ - #define MCAL_LED_2010_09_14_H_ +#ifndef MCAL_LED_2010_09_14_H + #define MCAL_LED_2010_09_14_H - #include - #include - #include + #include namespace mcal { namespace led { - template - class led final : private util::noncopyable - { - public: - led() - { - // Set the port pin value to low. - port_pin_type::set_pin_low(); - - // Set the port pin direction to output. - port_pin_type::set_direction_output(); - } - - static void toggle() - { - // Toggle the LED. - port_pin_type::toggle_pin(); - } - - private: - typedef mcal::port::port_pin port_pin_type; - }; - - typedef led led_type; - - extern const led_type led0; + auto led0() -> led_base&; } } -#endif // MCAL_LED_2010_09_14_H_ +#endif // MCAL_LED_2010_09_14_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_memory_progmem.h b/examples/chapter12_04/src/mcal/avr/mcal_memory_progmem.h index e4bc7f0ec..69812a21a 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_memory_progmem.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_memory_progmem.h @@ -1,17 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2019 - 2020. +// Copyright Christopher Kormanyos 2019 - 2025. // 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_MEMORY_PROGMEM_2019_08_17_H_ - #define MCAL_MEMORY_PROGMEM_2019_08_17_H_ - - #include +#ifndef MCAL_MEMORY_PROGMEM_2019_08_17_H + #define MCAL_MEMORY_PROGMEM_2019_08_17_H #include + #include + #define MY_PROGMEM PROGMEM #if defined(__cplusplus) @@ -59,4 +59,4 @@ } #endif -#endif // MCAL_MEMORY_PROGMEM_2019_08_17_H_ +#endif // MCAL_MEMORY_PROGMEM_2019_08_17_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_memory_sram.cpp b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram.cpp new file mode 100644 index 000000000..4ccad1d0f --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram.cpp @@ -0,0 +1,140 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#include + +#include +#include +#include +#include +#include + +namespace +{ + // SRAM port word expander configuration. + using mcal_memory_sram_parallel_port_word_expander_addr_04_to_19_type = mcal::port::port_word_expander; + + using mcal_memory_sram_parallel_port_pin_addr03_type = mcal::port::port_pin; + using mcal_memory_sram_parallel_port_pin_addr02_type = mcal::port::port_pin; + using mcal_memory_sram_parallel_port_pin_addr01_type = mcal::port::port_pin; + using mcal_memory_sram_parallel_port_pin_addr00_type = mcal::port::port_pin; + + using mcal_memory_sram_parallel_port_pin_ce1_not_type = mcal::port::port_pin; + using mcal_memory_sram_parallel_port_pin_ce2_____type = mcal::port::port_pin_dummy; // Pullup over 2.2k to +5V + using mcal_memory_sram_parallel_port_pin_oe__not_type = mcal::port::port_pin; + using mcal_memory_sram_parallel_port_pin_we__not_type = mcal::port::port_pin; + + using mcal_memory_sram_parallel_port_word_data_08_type = mcal::port::port_word; + + using mcal_memory_sram_parallel_type = + mcal::memory::sram::memory_sram_parallel_cypress_cy62158e; + + #if 0 + using mcal_memory_sram_parallel_type = + mcal::memory::sram::memory_sram_parallel_cypress_cy62167gn; + #endif + + mcal_memory_sram_parallel_type& mcal_memory_sram_device() + { + static mcal_memory_sram_parallel_type sram0; + + return sram0; + } +} + +extern "C" +uint8_t mcal_memory_sram_read_byte(const mcal_sram_uintptr_t src_addr) +{ + const std::uint8_t by = mcal_memory_sram_device().read(src_addr); + + return by; +} + +extern "C" +uint16_t mcal_memory_sram_read_word(const mcal_sram_uintptr_t src_addr) +{ + uint16_t dest = 0U; + + mcal_memory_sram_device().read_n(src_addr, 2U, (std::uint8_t*) &dest); + + return dest; +} + +extern "C" +uint32_t mcal_memory_sram_read_dword(const mcal_sram_uintptr_t src_addr) +{ + uint32_t dest = 0U; + + mcal_memory_sram_device().read_n(src_addr, 4U, (std::uint8_t*) &dest); + + return dest; +} + +extern "C" +uint64_t mcal_memory_sram_read_qword(const mcal_sram_uintptr_t src_addr) +{ + uint64_t dest = 0U; + + mcal_memory_sram_device().read_n(src_addr, 8U, (std::uint8_t*) &dest); + + return dest; +} + +extern "C" +void mcal_memory_sram_write_byte(const uint8_t src_value, const mcal_sram_uintptr_t dest_addr) +{ + mcal_memory_sram_device().write(dest_addr, src_value); +} + +extern "C" +void mcal_memory_sram_write_word(const uint16_t src_value, const mcal_sram_uintptr_t dest_addr) +{ + const uint16_t local_src_value = src_value; + + mcal_memory_sram_device().write_n(dest_addr, 2U, (const uint8_t*) &local_src_value); +} + +extern "C" +void mcal_memory_sram_write_dword(const uint32_t src_value, const mcal_sram_uintptr_t dest_addr) +{ + const uint32_t local_src_value = src_value; + + mcal_memory_sram_device().write_n(dest_addr, 4U, (const uint8_t*) &local_src_value); +} + +extern "C" +void mcal_memory_sram_write_qword(const uint64_t src_value, const mcal_sram_uintptr_t dest_addr) +{ + const uint64_t local_src_value = src_value; + + mcal_memory_sram_device().write_n(dest_addr, 8U, (const uint8_t*) &local_src_value); +} diff --git a/examples/chapter12_04/src/mcal/avr/mcal_memory_sram.h b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram.h new file mode 100644 index 000000000..0cd0a5638 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram.h @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 MCAL_MEMORY_SRAM_2020_04_09_H_ + #define MCAL_MEMORY_SRAM_2020_04_09_H_ + + #include + #include + + #if defined(__cplusplus) + extern "C" + { + #endif + + typedef uint32_t mcal_sram_uintptr_t; + typedef int32_t mcal_sram_ptrdiff_t; + + uint8_t mcal_memory_sram_read_byte (const mcal_sram_uintptr_t src_addr); + uint16_t mcal_memory_sram_read_word (const mcal_sram_uintptr_t src_addr); + uint32_t mcal_memory_sram_read_dword(const mcal_sram_uintptr_t src_addr); + uint64_t mcal_memory_sram_read_qword(const mcal_sram_uintptr_t src_addr); + + void mcal_memory_sram_write_byte (const uint8_t src_value, const mcal_sram_uintptr_t dest_addr); + void mcal_memory_sram_write_word (const uint16_t src_value, const mcal_sram_uintptr_t dest_addr); + void mcal_memory_sram_write_dword(const uint32_t src_value, const mcal_sram_uintptr_t dest_addr); + void mcal_memory_sram_write_qword(const uint64_t src_value, const mcal_sram_uintptr_t dest_addr); + + #if defined(__cplusplus) + } + #endif + +#endif // MCAL_MEMORY_SRAM_2020_04_09_H_ diff --git a/examples/chapter12_04/src/mcal/avr/mcal_memory_sram_parallel_cypress_cy62158e.h b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram_parallel_cypress_cy62158e.h new file mode 100644 index 000000000..4e6f7f045 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram_parallel_cypress_cy62158e.h @@ -0,0 +1,364 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_MEMORY_SRAM_PARALLEL_CYPRESS_CY62158E_2020_05_01_H + #define MCAL_MEMORY_SRAM_PARALLEL_CYPRESS_CY62158E_2020_05_01_H + + #include + #include + #include + + #include + + #include + + namespace mcal { namespace memory { namespace sram { + + template + class memory_sram_parallel_cypress_cy62158e : private util::noncopyable + { + private: + // The CY62158E MoBL(R)is a high performance CMOS static RAM + // organized as 1024K words by 8 bits (i.e., 1 Mbyte). + static auto nibble_port_pin_functions(const std::uint8_t nibble_value) -> void + { + switch(nibble_value) + { + case 0: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 1: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 2: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 3: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 4: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 5: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 6: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 7: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_low (); break; } + case 8: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + case 9: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + case 10: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + case 11: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_low (); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + case 12: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + case 13: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_low (); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + case 14: { sram_parallel_port_pin_addr00_type::set_pin_low (); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + default: case 15: { sram_parallel_port_pin_addr00_type::set_pin_high(); sram_parallel_port_pin_addr01_type::set_pin_high(); sram_parallel_port_pin_addr02_type::set_pin_high(); sram_parallel_port_pin_addr03_type::set_pin_high(); break; } + } + } + + public: + memory_sram_parallel_cypress_cy62158e() + { + // Initialize the parallel sram control pins. + sram_parallel_port_pin_ce1_not_type::set_pin_high(); + sram_parallel_port_pin_ce2_____type::set_pin_low(); + sram_parallel_port_pin_oe__not_type::set_pin_high(); + sram_parallel_port_pin_we__not_type::set_pin_high(); + + sram_parallel_port_pin_ce1_not_type::set_direction_output(); + sram_parallel_port_pin_ce2_____type::set_direction_output(); + sram_parallel_port_pin_oe__not_type::set_direction_output(); + sram_parallel_port_pin_we__not_type::set_direction_output(); + + // Set the microcontroller 8-bit port word to input. + // This is the port that is used for data read/write. + // the default direction. + sram_parallel_port_word08_data_type::set_direction_input(); + + // Initialize the 16-bit port word in the port expander. + // This is the port that is used for the upper word + // (bits 4-19) of the memory addresses. + sram_parallel_port_word16_addr_04_to_19_type::set_port(UINT16_C(0)); + sram_parallel_port_word16_addr_04_to_19_type::set_direction_output(); + + // Initialize individual address bit ports of the + // microcontroller. These ports are used for the + // lower nibble (bits 0...3) of the memory addresses. + sram_parallel_port_pin_addr00_type::set_pin_low(); + sram_parallel_port_pin_addr01_type::set_pin_low(); + sram_parallel_port_pin_addr02_type::set_pin_low(); + sram_parallel_port_pin_addr03_type::set_pin_low(); + + sram_parallel_port_pin_addr03_type::set_direction_output(); + sram_parallel_port_pin_addr02_type::set_direction_output(); + sram_parallel_port_pin_addr01_type::set_direction_output(); + sram_parallel_port_pin_addr00_type::set_direction_output(); + } + + ~memory_sram_parallel_cypress_cy62158e() = default; + + auto write(const std::uint32_t address_to_write, const std::uint8_t source_byte_to_write) -> void + { + // According to Document Number: 38-05684 Rev. *L: + // To write to the device, take Chip Enables (CE1_NOT LOW and CE2 + // HIGH) and Write Enable (WE_NOT) input LOW. Data on the eight I/O + // pins (I/O0 through I/O7) is then written into the location specified + // on the address pins (A0 through A19). + + // In detail, then, consider: + // Figure 6. Write Cycle No. 1 (WE_NOT Controlled) + // Document Number: 38-05684 Rev. *L Page 9 of 17 + + // Set the low 4 (nibble) bits of the address on portb.0-3. + nibble_port_pin_functions(static_cast(address_to_write & UINT8_C(0x0F))); + + const std::uint16_t input_word16_addr_04_to_19 = static_cast(address_to_write >> 4U); + + // Set the high 16 (word) bits of the address. + // Set these if (and only if) the high 16 (word) bits + // of the address has changed. + if(my_word16_addr_04_to_19 != input_word16_addr_04_to_19) + { + sram_parallel_port_word16_addr_04_to_19_type::set_port(input_word16_addr_04_to_19); + + my_word16_addr_04_to_19 = input_word16_addr_04_to_19; + } + + // Assert the control pins to select the memory device. + sram_parallel_port_pin_ce2_____type::set_pin_high(); + sram_parallel_port_pin_ce1_not_type::set_pin_low(); + + // Set the microcontroller port value (i.e., of port_address_read_write_data) + sram_parallel_port_word08_data_type::set_port(source_byte_to_write); + + mcal::helper::disable_all_interrupts(); + + // Set the microcontroller port direction (i.e., of port_address_read_write_data) + // to output (to write out the data). + sram_parallel_port_word08_data_type::set_direction_output(); + + // Assert WE_NOT to low in order to latch out the byte. + sram_parallel_port_pin_we__not_type::set_pin_low(); + + mcal::helper::nop_maker::execute_n(); + + // De-assert WE_NOT. + sram_parallel_port_pin_we__not_type::set_pin_high(); + + mcal::helper::enable_all_interrupts(); + + // De-assert the control pins to un-select the memory device. + sram_parallel_port_pin_ce1_not_type::set_pin_high(); + sram_parallel_port_pin_ce2_____type::set_pin_low(); + + // Set the microcontroller port (i.e., port_address_read_write_data) + // back to input (default direction). + sram_parallel_port_word08_data_type::set_direction_input(); + } + + auto write_n(const std::uint32_t address_to_write, + const std::size_t count, + const std::uint8_t* source_input_to_write) -> void + { + // Write n bytes, when n can be 1 but should + // be greater than 1 for improved efficiency. + + // Set the low 4 (nibble) bits of the address on portb.0-3. + std::uint8_t input_word08_addr_00_to_03 = static_cast (address_to_write & UINT8_C(0x0F)); + const std::uint16_t input_word16_addr_04_to_19 = static_cast(address_to_write >> 4U); + + // Set the high 16 (word) bits of the address. + // Set these if (and only if) the high 16 (word) bits + // of the address has changed. + if(my_word16_addr_04_to_19 != input_word16_addr_04_to_19) + { + my_word16_addr_04_to_19 = input_word16_addr_04_to_19; + + sram_parallel_port_word16_addr_04_to_19_type::set_port(my_word16_addr_04_to_19); + } + + // Set the microcontroller port direction (i.e., of port_address_read_write_data) + // to output (to write out the data). + sram_parallel_port_word08_data_type::set_direction_output(); + + for(std::size_t i = 0U; i < count; ++i) + { + if(input_word08_addr_00_to_03 == UINT8_C(0x10)) + { + // Important: + // By design, the body of this if-clause will *not* + // be executed on the zero'th trip through the enclosing + // for-loop. + input_word08_addr_00_to_03 = 0U; + + ++my_word16_addr_04_to_19; + + // Set the high 16 (word) bits of the address. + sram_parallel_port_word16_addr_04_to_19_type::set_port(my_word16_addr_04_to_19); + } + + // Set the low 4 (nibble) bits of the address on portb.0-3. + nibble_port_pin_functions(input_word08_addr_00_to_03); + + // Assert the control pins to select the memory device. + sram_parallel_port_pin_ce2_____type::set_pin_high(); + sram_parallel_port_pin_ce1_not_type::set_pin_low(); + + // Set the microcontroller port value (i.e., of port_address_read_write_data) + sram_parallel_port_word08_data_type::set_port(*(source_input_to_write + i)); + + mcal::helper::disable_all_interrupts(); + + // Assert WE_NOT to low in order to latch out the byte. + sram_parallel_port_pin_we__not_type::set_pin_low(); + + mcal::helper::nop_maker::execute_n(); + + // De-assert WE_NOT. + sram_parallel_port_pin_we__not_type::set_pin_high(); + + mcal::helper::enable_all_interrupts(); + + ++input_word08_addr_00_to_03; + } + + // De-assert the control pins to un-select the memory device. + sram_parallel_port_pin_ce1_not_type::set_pin_high(); + sram_parallel_port_pin_ce2_____type::set_pin_low(); + + // Set the microcontroller port (i.e., port_address_read_write_data) + // back to input (default direction). + sram_parallel_port_word08_data_type::set_direction_input(); + } + + auto read(const std::uint32_t address_to_read) -> std::uint8_t + { + // According to Document Number: 38-05684 Rev. *L: + // To read from the device, take Chip Enables (CE1_NOT LOW and CE2 + // HIGH) and OE_NOT LOW while forcing the WE_NOT HIGH. Under these + // conditions, the contents of the memory location specified by the + // address pins appear on the I/O pins. + + // In detail, then, consider: + // Figure 5. Read Cycle No. 2 (OE_NOT Controlled) + // Document Number: 38-05684 Rev. *L Page 8 of 17 + + // Set the low 4 (nibble) bits of the address on portb.0-3. + nibble_port_pin_functions(static_cast(address_to_read & UINT8_C(0x0F))); + + const std::uint16_t input_word16_addr_04_to_19 = static_cast(address_to_read >> 4U); + + // Set the high 16 (word) bits of the address. + // Set these if (and only if) the high 16 (word) bits + // of the address has changed. + if(my_word16_addr_04_to_19 != input_word16_addr_04_to_19) + { + sram_parallel_port_word16_addr_04_to_19_type::set_port(input_word16_addr_04_to_19); + + my_word16_addr_04_to_19 = input_word16_addr_04_to_19; + } + + // Assert the control pins to select the memory device. + sram_parallel_port_pin_ce2_____type::set_pin_high(); + sram_parallel_port_pin_ce1_not_type::set_pin_low(); + + mcal::helper::disable_all_interrupts(); + + // Assert OE_NOT to low and also disable write in order to strobe in the byte. + sram_parallel_port_pin_oe__not_type::set_pin_low(); + sram_parallel_port_pin_we__not_type::set_pin_high(); + + mcal::helper::nop_maker::execute_n(); + + // Get the byte to read. + const std::uint8_t byte_to_read = sram_parallel_port_word08_data_type::read_port(); + + // De-assert OE_NOT after reading the byte. + sram_parallel_port_pin_oe__not_type::set_pin_high(); + + mcal::helper::enable_all_interrupts(); + + // De-assert the control pins to un-select the memory device. + sram_parallel_port_pin_ce1_not_type::set_pin_high(); + sram_parallel_port_pin_ce2_____type::set_pin_low(); + + return byte_to_read; + } + + auto read_n(const std::uint32_t address_to_read, + const std::size_t count, + std::uint8_t* dest_to_store_read_data) -> void + { + // Read n bytes, when n can be 1 but should + // be greater than 1 for improved efficiency. + + std::uint8_t input_word08_addr_00_to_03 = static_cast ((address_to_read) & UINT8_C(0x0F)); + const std::uint16_t input_word16_addr_04_to_19 = static_cast((address_to_read) >> 4U); + + // Set the low 4 (nibble) bits of the address on portb.0-3. + nibble_port_pin_functions(input_word08_addr_00_to_03); + + // Set the high 16 (word) bits of the address. + // Set these if (and only if) the high 16 (word) bits + // of the address has changed. + if(my_word16_addr_04_to_19 != input_word16_addr_04_to_19) + { + my_word16_addr_04_to_19 = input_word16_addr_04_to_19; + + sram_parallel_port_word16_addr_04_to_19_type::set_port(my_word16_addr_04_to_19); + } + + // Assert the control pins to select the memory device. + sram_parallel_port_pin_ce2_____type::set_pin_high(); + sram_parallel_port_pin_ce1_not_type::set_pin_low(); + + mcal::helper::disable_all_interrupts(); + + // Assert OE_NOT to low in order to begin strobing + // in the byte stream. + sram_parallel_port_pin_oe__not_type::set_pin_low(); + sram_parallel_port_pin_we__not_type::set_pin_high(); + + mcal::helper::nop_maker::execute_n(); + + *dest_to_store_read_data = sram_parallel_port_word08_data_type::read_port(); + + for(std::size_t i = 1U; i < count; ++i) + { + ++input_word08_addr_00_to_03; + + if(input_word08_addr_00_to_03 == UINT8_C(0x10)) + { + input_word08_addr_00_to_03 = 0U; + + ++my_word16_addr_04_to_19; + + // Set the high 16 (word) bits of the address. + sram_parallel_port_word16_addr_04_to_19_type::set_port(my_word16_addr_04_to_19); + } + + // Set the low 4 (nibble) bits of the address on portb.0-3. + nibble_port_pin_functions(input_word08_addr_00_to_03); + + *(dest_to_store_read_data + i) = sram_parallel_port_word08_data_type::read_port(); + } + + // De-assert OE_NOT after reading n bytes. + sram_parallel_port_pin_oe__not_type::set_pin_high(); + + mcal::helper::enable_all_interrupts(); + + // De-assert the control pins to un-select the memory device. + sram_parallel_port_pin_ce1_not_type::set_pin_high(); + sram_parallel_port_pin_ce2_____type::set_pin_low(); + } + + private: + std::uint16_t my_word16_addr_04_to_19 { }; + }; + + } } } // namespace mcal::memory::sram + +#endif // MCAL_MEMORY_SRAM_PARALLEL_CYPRESS_CY62158E_2020_05_01_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_memory_sram_parallel_cypress_cy62167gn.h b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram_parallel_cypress_cy62167gn.h new file mode 100644 index 000000000..aa7796c65 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_memory_sram_parallel_cypress_cy62167gn.h @@ -0,0 +1,150 @@ +#ifndef MCAL_MEMORY_SRAM_PARALLEL_CYPRESS_CY62167GN_2020_05_21_H_ + #define MCAL_MEMORY_SRAM_PARALLEL_CYPRESS_CY62167GN_2020_05_21_H_ + + #include + #include + + namespace mcal { namespace memory { namespace sram { + + template + class memory_sram_parallel_cypress_cy62167gn final + : public mcal::memory::sram::memory_sram_parallel_cypress_cy62158e + { + private: + // The CY62167GN is a high performance CMOS static RAM + // organized as 1M words by 16 bits or 2M words by 8 bit + // (i.e., 2 Mbyte). + + using base_class_type = + mcal::memory::sram::memory_sram_parallel_cypress_cy62158e; + + public: + memory_sram_parallel_cypress_cy62167gn() : my_port_pin_addr20_is_high(false) { } + + ~memory_sram_parallel_cypress_cy62167gn() = default; + + void write(const std::uint32_t address_to_write, const std::uint8_t source_byte_to_write) + { + const bool input_port_pin_addr20_is_high = ((address_to_write & UINT32_C(0x00100000)) != UINT32_C(0)); + + if(input_port_pin_addr20_is_high != my_port_pin_addr20_is_high) + { + (input_port_pin_addr20_is_high ? sram_parallel_port_pin_addr20_type::set_pin_high() + : sram_parallel_port_pin_addr20_type::set_pin_low()); + + my_port_pin_addr20_is_high = input_port_pin_addr20_is_high; + + base_class_type::write(std::uint32_t(address_to_write & UINT32_C(0xFFEFFFFF)), source_byte_to_write); + } + else + { + base_class_type::write(address_to_write, source_byte_to_write); + } + } + + void write_n(const std::uint32_t address_to_write, + const std::size_t count, + const std::uint8_t* source_input_to_write) + { + const bool input_port_pin_addr20_is_high = ((address_to_write & UINT32_C(0x00100000)) != UINT32_C(0)); + + if(input_port_pin_addr20_is_high != my_port_pin_addr20_is_high) + { + (input_port_pin_addr20_is_high ? sram_parallel_port_pin_addr20_type::set_pin_high() + : sram_parallel_port_pin_addr20_type::set_pin_low()); + + my_port_pin_addr20_is_high = input_port_pin_addr20_is_high; + + base_class_type::write_n(std::uint32_t(address_to_write & UINT32_C(0xFFEFFFFF)), count, source_input_to_write); + } + else + { + base_class_type::write_n(address_to_write, count, source_input_to_write); + } + } + + std::uint8_t read(const std::uint32_t address_to_read) + { + std::uint8_t read_value; + + const bool input_port_pin_addr20_is_high = ((address_to_read & UINT32_C(0x00100000)) != UINT32_C(0)); + + if(input_port_pin_addr20_is_high != my_port_pin_addr20_is_high) + { + (input_port_pin_addr20_is_high ? sram_parallel_port_pin_addr20_type::set_pin_high() + : sram_parallel_port_pin_addr20_type::set_pin_low()); + + my_port_pin_addr20_is_high = input_port_pin_addr20_is_high; + + read_value = base_class_type::read(std::uint32_t(address_to_read & UINT32_C(0xFFEFFFFF))); + } + else + { + read_value = base_class_type::read(address_to_read); + } + + return read_value; + } + + void read_n(const std::uint32_t address_to_read, + const std::size_t count, + std::uint8_t* dest_to_store_read_data) + { + const bool input_port_pin_addr20_is_high = ((address_to_read & UINT32_C(0x00100000)) != UINT32_C(0)); + + if(input_port_pin_addr20_is_high != my_port_pin_addr20_is_high) + { + (input_port_pin_addr20_is_high ? sram_parallel_port_pin_addr20_type::set_pin_high() + : sram_parallel_port_pin_addr20_type::set_pin_low()); + + my_port_pin_addr20_is_high = input_port_pin_addr20_is_high; + + base_class_type::read_n(std::uint32_t(address_to_read & UINT32_C(0xFFEFFFFF)), count, dest_to_store_read_data); + } + else + { + base_class_type::read_n(address_to_read, count, dest_to_store_read_data); + } + } + + private: + bool my_port_pin_addr20_is_high; + }; + + } } } // namespace mcal::memory::sram + +#endif // MCAL_MEMORY_SRAM_PARALLEL_CYPRESS_CY62167GN_2020_05_21_H_ diff --git a/examples/chapter12_04/src/mcal/avr/mcal_osc.cpp b/examples/chapter12_04/src/mcal/avr/mcal_osc.cpp index 14787d20a..6ae0b6324 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_osc.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_osc.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,6 +7,6 @@ #include -void mcal::osc::init(const config_type*) +auto mcal::osc::init(const config_type*) -> void { } diff --git a/examples/chapter12_04/src/mcal/avr/mcal_osc.h b/examples/chapter12_04/src/mcal/avr/mcal_osc.h index 59b729640..cb8944d84 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_osc.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_osc.h @@ -1,21 +1,21 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_OSC_2011_10_20_H_ - #define MCAL_OSC_2011_10_20_H_ +#ifndef MCAL_OSC_2011_10_20_H + #define MCAL_OSC_2011_10_20_H namespace mcal { namespace osc { - typedef void config_type; + using config_type = void; - void init(const config_type*); + auto init(const config_type*) -> void; } } -#endif // MCAL_OSC_2011_10_20_H_ +#endif // MCAL_OSC_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_port.cpp b/examples/chapter12_04/src/mcal/avr/mcal_port.cpp index 4486c3fe8..e19b30c3b 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_port.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_port.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,6 +7,6 @@ #include -void mcal::port::init(const config_type*) +auto mcal::port::init(const config_type*) -> void { } diff --git a/examples/chapter12_04/src/mcal/avr/mcal_port.h b/examples/chapter12_04/src/mcal/avr/mcal_port.h index 077cb66c2..6676e1eb3 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_port.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_port.h @@ -1,22 +1,31 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_PORT_2012_06_27_H_ - #define MCAL_PORT_2012_06_27_H_ +#ifndef MCAL_PORT_2012_06_27_H + #define MCAL_PORT_2012_06_27_H #include + #include + + auto mcal_port_pin_expander_set_direction_output(const uint8_t bpos) -> void; + auto mcal_port_pin_expander_set_direction_input (const uint8_t bpos) -> void; + auto mcal_port_pin_expander_set_pin_high (const uint8_t bpos) -> void; + auto mcal_port_pin_expander_set_pin_low (const uint8_t bpos) -> void; + auto mcal_port_pin_expander_read_input_value (const uint8_t bpos) -> bool; + auto mcal_port_pin_expander_toggle_pin (const uint8_t bpos) -> void; + namespace mcal { namespace port { - typedef void config_type; + using config_type = void; - void init(const config_type*); + auto init(const config_type*) -> void; template void { // Set the port pin's direction to output. // C++: @@ -46,7 +55,7 @@ asm volatile("sbi %[myport],%[mybit]" : : [myport]"I"(pdir_address - sfr_offset), [mybit]"I"(bpos_value)); } - static void set_direction_input() + static auto set_direction_input() -> void { // Set the port pin's direction to input. // C++: @@ -57,7 +66,7 @@ asm volatile("cbi %[myport],%[mybit]" : : [myport]"I"(pdir_address - sfr_offset), [mybit]"I"(bpos_value)); } - static void set_pin_high() + static auto set_pin_high() -> void { // Set the port output value to high. // C++: @@ -68,7 +77,7 @@ asm volatile("sbi %[myport],%[mybit]" : : [myport]"I"(port_address - sfr_offset), [mybit]"I"(bpos_value)); } - static void set_pin_low() + static auto set_pin_low() -> void { // Set the port output value to low. // C++: @@ -79,7 +88,7 @@ asm volatile("cbi %[myport],%[mybit]" : : [myport]"I"(port_address - sfr_offset), [mybit]"I"(bpos_value)); } - static bool read_input_value() + static auto read_input_value() -> bool { // Read the port input value. return mcal::reg::reg_access_static::bit_get(); } - static void toggle_pin() + static auto toggle_pin() -> void { // Toggle the port output value. mcal::reg::reg_access_static::bit_not(); } }; + + template + class port_pin_expander + { + public: + static auto set_direction_output() -> void { mcal_port_pin_expander_set_direction_output(bpos); } + static auto set_direction_input () -> void { mcal_port_pin_expander_set_direction_input (bpos); } + static auto set_pin_high () -> void { mcal_port_pin_expander_set_pin_high (bpos); } + static auto set_pin_low () -> void { mcal_port_pin_expander_set_pin_low (bpos); } + static auto read_input_value () -> bool { return mcal_port_pin_expander_read_input_value (bpos); } + static auto toggle_pin () -> void { mcal_port_pin_expander_toggle_pin (bpos); } + }; } } -#endif // MCAL_PORT_2012_06_27_H_ +#endif // MCAL_PORT_2012_06_27_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_port_expander_microchip_mcp23s17.h b/examples/chapter12_04/src/mcal/avr/mcal_port_expander_microchip_mcp23s17.h new file mode 100644 index 000000000..b0c1d0543 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_port_expander_microchip_mcp23s17.h @@ -0,0 +1,211 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_PORT_WORD_EXPANDER_MICROCHIP_MCP23S17_2020_04_21_H + #define MCAL_PORT_WORD_EXPANDER_MICROCHIP_MCP23S17_2020_04_21_H + + #include + #include + + namespace mcal { namespace port { + + template + class port_regs_expander_microchip_mcp23s17 + { + public: + virtual ~port_regs_expander_microchip_mcp23s17() = default; + + protected: + static constexpr std::uint8_t reg_iodira = UINT8_C(0x00); // MCP23x17 I/O Direction Register + static constexpr std::uint8_t reg_iodirb = UINT8_C(0x01); // 1 = Input (default), 0 = Output + + static constexpr std::uint8_t reg_ipola = UINT8_C(0x02); // MCP23x17 Input Polarity Register + static constexpr std::uint8_t reg_ipolb = UINT8_C(0x03); // 0 = Normal (default)(low reads as 0), 1 = Inverted (low reads as 1) + + static constexpr std::uint8_t reg_gpintena = UINT8_C(0x04); // MCP23x17 Interrupt on Change Pin Assignements + static constexpr std::uint8_t reg_gpintenb = UINT8_C(0x05); // 0 = No Interrupt on Change (default), 1 = Interrupt on Change + + static constexpr std::uint8_t reg_defvala = UINT8_C(0x06); // MCP23x17 Default Compare Register for Interrupt on Change + static constexpr std::uint8_t reg_defvalb = UINT8_C(0x07); // Opposite of what is here will trigger an interrupt (default = 0) + + static constexpr std::uint8_t reg_intcona = UINT8_C(0x08); // MCP23x17 Interrupt on Change Control Register + static constexpr std::uint8_t reg_intconb = UINT8_C(0x09); // 1 = pin is compared to DEFVAL, 0 = pin is compared to previous state (default) + + static constexpr std::uint8_t reg_iocona = UINT8_C(0x0A); // MCP23x17 Configuration Register + static constexpr std::uint8_t reg_ioconb = UINT8_C(0x0B); // Also Configuration Register + + static constexpr std::uint8_t reg_gppua = UINT8_C(0x0C); // MCP23x17 Weak Pull-Up Resistor Register + static constexpr std::uint8_t reg_gppub = UINT8_C(0x0D); // INPUT ONLY: 0 = No Internal 100k Pull-Up (default) 1 = Internal 100k Pull-Up + + static constexpr std::uint8_t reg_intfa = UINT8_C(0x0E); // MCP23x17 Interrupt Flag Register + static constexpr std::uint8_t reg_intfb = UINT8_C(0x0F); // READ ONLY: 1 = This Pin Triggered the Interrupt + + static constexpr std::uint8_t reg_intcapa = UINT8_C(0x10); // MCP23x17 Interrupt Captured Value for Port Register + static constexpr std::uint8_t reg_intcapb = UINT8_C(0x11); // READ ONLY: State of the Pin at the Time the Interrupt Occurred + + static constexpr std::uint8_t reg_gpioa = UINT8_C(0x12); // MCP23x17 GPIO Port Register + static constexpr std::uint8_t reg_gpiob = UINT8_C(0x13); // Value on the Port - Writing Sets Bits in the Output Latch + + static constexpr std::uint8_t reg_olata = UINT8_C(0x14); // MCP23x17 Output Latch Register + static constexpr std::uint8_t reg_olatb = UINT8_C(0x15); // 1 = Latch High, 0 = Latch Low (default) Reading Returns Latch State, Not Port Value! + + static constexpr std::uint8_t cmd_write = UINT8_C(0x40); + static constexpr std::uint8_t cmd__read = UINT8_C(0x41); + + static constexpr std::uint8_t addr_max = UINT8_C(7); + + static constexpr std::uint8_t addr_enable = UINT8_C(0x08); + + static constexpr std::uint8_t my_address = ((hardware_address > addr_max) ? addr_max : hardware_address); + + static constexpr std::uint8_t my_cmd_write = std::uint8_t(UINT8_C(0x40) | std::uint8_t(my_address << 1U)); + static constexpr std::uint8_t my_cmd__read = std::uint8_t(UINT8_C(0x41) | std::uint8_t(my_address << 1U)); + + protected: + port_regs_expander_microchip_mcp23s17(util::communication_base& com) noexcept + : my_com(com) + { + // Set the address-enable bit. + my_com.select(); + my_com.send(my_cmd_write); + my_com.send(reg_iocona); + my_com.send(addr_enable); + my_com.deselect(); + } + + auto read__word(const std::uint8_t reg) -> std::uint16_t + { + std::uint8_t byte_to_read_lo = std::uint8_t(); + std::uint8_t byte_to_read_hi = std::uint8_t(); + + my_com.select(); + my_com.send(my_cmd__read); + my_com.send(reg); + my_com.send(UINT8_C(0)); + my_com.recv(byte_to_read_lo); + my_com.send(UINT8_C(0)); + my_com.recv(byte_to_read_hi); + my_com.deselect(); + + return util::make_long(byte_to_read_lo, byte_to_read_hi); + } + + auto write_word(const std::uint8_t reg, const std::uint16_t word_to_write) noexcept -> void + { + my_com.select(); + my_com.send(my_cmd_write); + my_com.send(reg); + my_com.send(util::lo_part(word_to_write)); + my_com.send(util::hi_part(word_to_write)); + my_com.deselect(); + } + + private: + util::communication_base& my_com; + }; + + template + class port_word_expander_microchip_mcp23s17 + : public port_regs_expander_microchip_mcp23s17 + { + private: + using base_class_type = port_regs_expander_microchip_mcp23s17; + + public: + port_word_expander_microchip_mcp23s17(util::communication_base& com) noexcept + : base_class_type(com) { } + + ~port_word_expander_microchip_mcp23s17() override = default; + + auto set_port(const std::uint16_t port_value) noexcept -> void + { + base_class_type::write_word(base_class_type::reg_gpioa, port_value); + } + + auto set_direction_output() noexcept -> void + { + // Set all ports to output (default is input 0xFFFF). + base_class_type::write_word(base_class_type::reg_iodira, UINT16_C(0x0000)); + } + + auto set_direction_input() noexcept -> void + { + // Set all ports to input (default is input 0xFFFF). + base_class_type::write_word(base_class_type::reg_iodira, UINT16_C(0xFFFF)); + } + }; + + template + class port_pin_expander_microchip_mcp23s17 + : public port_regs_expander_microchip_mcp23s17 + { + private: + // This implementation uses read-modify-write sequences + // to access port direction and value registers. + // It is designed this way in order to avoid member + // variables, even though read-modify-write might + // be slower than some other potential implementations. + + using base_class_type = port_regs_expander_microchip_mcp23s17; + + public: + port_pin_expander_microchip_mcp23s17(util::communication_base& com) noexcept + : base_class_type(com) { } + + ~port_pin_expander_microchip_mcp23s17() override = default; + + auto set_direction_output(const std::uint8_t bpos) noexcept -> void + { + const std::uint16_t dir = base_class_type::read__word(base_class_type::reg_iodira); + + base_class_type::write_word(base_class_type::reg_iodira, + std::uint16_t(dir & std::uint16_t(~std::uint16_t(1ULL << bpos)))); + } + + auto set_direction_input(const std::uint8_t bpos) noexcept -> void + { + const std::uint16_t dir = base_class_type::read__word(base_class_type::reg_iodira); + + base_class_type::write_word(base_class_type::reg_iodira, + std::uint16_t(dir | std::uint16_t(1ULL << bpos))); + } + + auto set_pin_high(const std::uint8_t bpos) noexcept -> void + { + const std::uint16_t val = base_class_type::read__word(base_class_type::reg_gpioa); + + base_class_type::write_word(base_class_type::reg_gpioa, + std::uint16_t(val | std::uint16_t(1ULL << bpos))); + } + + void set_pin_low(const std::uint8_t bpos) noexcept + { + const std::uint16_t val = base_class_type::read__word(base_class_type::reg_gpioa); + + base_class_type::write_word(base_class_type::reg_gpioa, + std::uint16_t(val & std::uint16_t(~std::uint16_t(1ULL << bpos)))); + } + + auto read_input_value(const std::uint8_t bpos) noexcept -> bool + { + const std::uint16_t val = base_class_type::read__word(base_class_type::reg_gpioa); + + return (std::uint_fast8_t((val >> bpos) & UINT8_C(1)) != UINT8_C(0)); + } + + auto toggle_pin(const std::uint8_t bpos) noexcept -> void + { + const std::uint16_t val = base_class_type::read__word(base_class_type::reg_gpioa); + + base_class_type::write_word(base_class_type::reg_gpioa, + std::uint16_t(val ^ std::uint16_t(1ULL << bpos))); + } + }; + + } } // namespace mcal::port + +#endif // MCAL_PORT_WORD_EXPANDER_MICROCHIP_MCP23S17_2020_04_21_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_port_pin_dummy.h b/examples/chapter12_04/src/mcal/avr/mcal_port_pin_dummy.h new file mode 100644 index 000000000..0b36dcdce --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_port_pin_dummy.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 PORT_PIN_DUMMY_2020_05_05_H + #define PORT_PIN_DUMMY_2020_05_05_H + + namespace mcal { namespace port { + + class port_pin_dummy + { + public: + static auto init () noexcept -> void { } + static auto set_direction_output() noexcept -> void { } + static auto set_direction_input () noexcept -> void { } + static auto set_pin_high () noexcept -> void { } + static auto set_pin_low () noexcept -> void { } + static auto read_input_value () noexcept -> bool { return false; } + static auto toggle_pin () noexcept -> void { } + }; + + } } // namespace mcal::port + +#endif // PORT_PIN_DUMMY_2020_05_05_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_port_word.h b/examples/chapter12_04/src/mcal/avr/mcal_port_word.h new file mode 100644 index 000000000..2b1b3e95f --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_port_word.h @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_PORT_WORD_2020_05_06_H + #define MCAL_PORT_WORD_2020_05_06_H + + #include + + void mcal_port_word_expander_set_port(const uint16_t value_to_write); + void mcal_port_word_expander_set_direction_output(); + void mcal_port_word_expander_set_direction_input(); + + namespace mcal { namespace port { + + template + class port_word + { + private: + using address_uintptr_type = addr_type; + using register_value_type = reg_type; + + static constexpr address_uintptr_type port_address = port; + static constexpr address_uintptr_type pdir_address = port_address - address_uintptr_type(1U); + static constexpr address_uintptr_type pinp_address = port_address - address_uintptr_type(2U); + + public: + static auto set_port(const register_value_type value_to_write) -> void + { + mcal::reg::reg_access_dynamic::reg_set(port_address, value_to_write); + } + + static auto set_direction_output() -> void + { + mcal::reg::reg_access_static::reg_set(); + } + + static auto set_direction_input() -> void + { + mcal::reg::reg_access_static::reg_set(); + } + + static register_value_type read_port() + { + const register_value_type value_to_read = mcal::reg::reg_access_static::reg_get(); + + return value_to_read; + } + }; + + template + class port_word_expander + { + public: + static auto set_port(const std::uint16_t value_to_write) -> void + { + mcal_port_word_expander_set_port(value_to_write); + } + + static auto set_direction_output() -> void + { + mcal_port_word_expander_set_direction_output(); + } + + static auto set_direction_input() -> void + { + mcal_port_word_expander_set_direction_input(); + } + }; + + } } // namespace mcal::port + +#endif // MCAL_PORT_WORD_2020_05_06_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_pwm.cpp b/examples/chapter12_04/src/mcal/avr/mcal_pwm.cpp new file mode 100644 index 000000000..0e08f3ef1 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_pwm.cpp @@ -0,0 +1,12 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#include + +auto mcal::pwm::init(const mcal::pwm::config_type*) -> void +{ +} diff --git a/examples/chapter12_04/src/mcal/avr/mcal_pwm.h b/examples/chapter12_04/src/mcal/avr/mcal_pwm.h new file mode 100644 index 000000000..1ced6476a --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_pwm.h @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_2010_09_14_H + #define MCAL_PWM_2010_09_14_H + + namespace mcal + { + namespace pwm + { + using config_type = void; + + auto init(const config_type*) -> void; + } + } + +#endif // MCAL_PWM_2010_09_14_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_pwm_lcd.h b/examples/chapter12_04/src/mcal/avr/mcal_pwm_lcd.h new file mode 100644 index 000000000..e053495aa --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_pwm_lcd.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 MCAL_PWM_LCD_2020_05_04_H_ + #define MCAL_PWM_LCD_2020_05_04_H_ + + #include + #include + + #include + + namespace mcal { namespace pwm { + + class pwm_lcd : public mcal::pwm::pwm_base + { + private: + using base_class_type = mcal::pwm::pwm_base; + + public: + pwm_lcd() + { + base_class_type::my_duty_cycle = UINT16_C(1000); + } + + virtual ~pwm_lcd() = default; + + virtual bool init() noexcept + { + return true; + } + + virtual void set_duty(const std::uint16_t duty_cycle) noexcept; + }; + + } } + +#endif // MCAL_PWM_LCD_2020_05_04_H_ diff --git a/examples/chapter12_04/src/mcal/avr/mcal_pwm_timer1.h b/examples/chapter12_04/src/mcal/avr/mcal_pwm_timer1.h new file mode 100644 index 000000000..63edf1914 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_pwm_timer1.h @@ -0,0 +1,111 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_TIMER1_2020_04_12_H + #define MCAL_PWM_TIMER1_2020_04_12_H + + #include + #include + + #include + #include + + namespace mcal { namespace pwm { + + class pwm_timer1 : public pwm_base + { + private: + using base_class_type = pwm_base; + + public: + pwm_timer1() = default; + + ~pwm_timer1() override = default; + + auto init() noexcept -> bool override + { + // Set portb.1 to output. + mcal::reg::reg_access_static::bit_set(); + + // Set the pwm top to 1000. + mcal::reg::reg_access_static::reg_set(); + + // Set the pwm duty cycle for channel a. + mcal::reg::reg_access_static::reg_set(); + + // Set the pwm duty cycle for channel b. + //mcal::reg::reg_access_static::reg_set(); + + { + constexpr std::uint8_t wgm11 = UINT8_C(1); + constexpr std::uint8_t wgm12 = UINT8_C(3); + constexpr std::uint8_t wgm13 = UINT8_C(4); + //constexpr std::uint8_t com1b1 = UINT8_C(5); + constexpr std::uint8_t com1a1 = UINT8_C(7); + constexpr std::uint8_t cs11 = UINT8_C(1); + + // Set non-inverting mode for channel a. + mcal::reg::reg_access_static::reg_or(); + + // Set non-inverting mode for channel b. + //mcal::reg::reg_access_static::reg_or(); + + // Set fast pwm mode using icr1 as top. + mcal::reg::reg_access_static::reg_or(); + + mcal::reg::reg_access_static::reg_or(); + + // Start the timer with prescaler (clock / 8). + mcal::reg::reg_access_static::reg_or(); + } + + return true; + } + + auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override + { + // Set the duty cycle 0...1000. + + base_class_type::set_duty((std::min)(duty_cycle, static_cast(UINT16_C(1000)))); + + mcal::reg::reg_access_dynamic::reg_set(mcal::reg::ocr1a, + base_class_type::get_duty()); + } + }; + + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_TIMER1_2020_04_12_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_reg.h b/examples/chapter12_04/src/mcal/avr/mcal_reg.h index d402fae64..62e084ec2 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_reg.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_reg.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2020. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_REG_2010_04_10_H_ - #define MCAL_REG_2010_04_10_H_ +#ifndef MCAL_REG_2010_04_10_H + #define MCAL_REG_2010_04_10_H #include @@ -17,76 +17,91 @@ constexpr std::uint8_t sfr_offset = 0x20U; // Bit-position values. - constexpr std::uint8_t bval0 = 1U; - constexpr std::uint8_t bval1 = 1U << 1U; - constexpr std::uint8_t bval2 = 1U << 2U; - constexpr std::uint8_t bval3 = 1U << 3U; - constexpr std::uint8_t bval4 = 1U << 4U; - constexpr std::uint8_t bval5 = 1U << 5U; - constexpr std::uint8_t bval6 = 1U << 6U; - constexpr std::uint8_t bval7 = 1U << 7U; + constexpr std::uint8_t bval0 { 1U }; + constexpr std::uint8_t bval1 { 1U << 1U }; + constexpr std::uint8_t bval2 { 1U << 2U }; + constexpr std::uint8_t bval3 { 1U << 3U }; + constexpr std::uint8_t bval4 { 1U << 4U }; + constexpr std::uint8_t bval5 { 1U << 5U }; + constexpr std::uint8_t bval6 { 1U << 6U }; + constexpr std::uint8_t bval7 { 1U << 7U }; // System registers. - constexpr std::uint8_t mcusr = 0x14U + sfr_offset; - constexpr std::uint8_t prr = 0x64U; + constexpr std::uint8_t mcusr { 0x14U + sfr_offset }; + constexpr std::uint8_t prr { 0x64U }; // Port registers. - constexpr std::uint8_t pinb = 0x03U + sfr_offset; - constexpr std::uint8_t ddrb = 0x04U + sfr_offset; - constexpr std::uint8_t portb = 0x05U + sfr_offset; - constexpr std::uint8_t pinc = 0x06U + sfr_offset; - constexpr std::uint8_t ddrc = 0x07U + sfr_offset; - constexpr std::uint8_t portc = 0x08U + sfr_offset; - constexpr std::uint8_t pind = 0x09U + sfr_offset; - constexpr std::uint8_t ddrd = 0x0AU + sfr_offset; - constexpr std::uint8_t portd = 0x0BU + sfr_offset; - constexpr std::uint8_t pine = 0x0CU + sfr_offset; - constexpr std::uint8_t ddre = 0x0DU + sfr_offset; - constexpr std::uint8_t porte = 0x0EU + sfr_offset; + constexpr std::uint8_t pinb { 0x03U + sfr_offset }; + constexpr std::uint8_t ddrb { 0x04U + sfr_offset }; + constexpr std::uint8_t portb { 0x05U + sfr_offset }; + constexpr std::uint8_t pinc { 0x06U + sfr_offset }; + constexpr std::uint8_t ddrc { 0x07U + sfr_offset }; + constexpr std::uint8_t portc { 0x08U + sfr_offset }; + constexpr std::uint8_t pind { 0x09U + sfr_offset }; + constexpr std::uint8_t ddrd { 0x0AU + sfr_offset }; + constexpr std::uint8_t portd { 0x0BU + sfr_offset }; + constexpr std::uint8_t pine { 0x0CU + sfr_offset }; + constexpr std::uint8_t ddre { 0x0DU + sfr_offset }; + constexpr std::uint8_t porte { 0x0EU + sfr_offset }; + + // Timer register values + constexpr std::uint8_t cs10 = 0U; + constexpr std::uint8_t cs11 = 1U; + constexpr std::uint8_t cs12 = 2U; + constexpr std::uint8_t wgm12 = 3U; + constexpr std::uint8_t toie1 = 0U; + constexpr std::uint8_t ocie0a = 1U; + constexpr std::uint8_t ocie0b = 2U; + constexpr std::uint8_t toie0 = 0U; + constexpr std::uint8_t ocie1a = 1U; + constexpr std::uint8_t ocie1b = 2U; + constexpr std::uint8_t toie2 = 0U; + constexpr std::uint8_t ocie2a = 1U; + constexpr std::uint8_t ocie2b = 2U; // Timer registers - constexpr std::uint8_t tifr0 = 0x15U + sfr_offset; - constexpr std::uint8_t tccr0a = 0x24U + sfr_offset; - constexpr std::uint8_t tccr0b = 0x25U + sfr_offset; - constexpr std::uint8_t tcnt0 = 0x26U + sfr_offset; - constexpr std::uint8_t ocr0a = 0x27U + sfr_offset; - constexpr std::uint8_t timsk0 = 0x6EU; + constexpr std::uint8_t tifr0 { 0x15U + sfr_offset }; + constexpr std::uint8_t tccr0a { 0x24U + sfr_offset }; + constexpr std::uint8_t tccr0b { 0x25U + sfr_offset }; + constexpr std::uint8_t tcnt0 { 0x26U + sfr_offset }; + constexpr std::uint8_t ocr0a { 0x27U + sfr_offset }; + constexpr std::uint8_t timsk0 { 0x6EU }; - constexpr std::uint8_t tifr1 = 0x16U + sfr_offset; - constexpr std::uint8_t tccr1a = 0x80U; - constexpr std::uint8_t tccr1b = 0x81U; - constexpr std::uint8_t tcnt1l = 0x84U; - constexpr std::uint8_t tcnt1h = 0x85U; - constexpr std::uint8_t icr1 = 0x86U; // 16-bit register - constexpr std::uint8_t ocr1a = 0x88U; // 16-bit register - constexpr std::uint8_t ocr1b = 0x8AU; // 16-bit register - constexpr std::uint8_t timsk1 = 0x6FU; + constexpr std::uint8_t tifr1 { 0x16U + sfr_offset }; + constexpr std::uint8_t tccr1a { 0x80U }; + constexpr std::uint8_t tccr1b { 0x81U }; + constexpr std::uint8_t tcnt1l { 0x84U }; + constexpr std::uint8_t tcnt1h { 0x85U }; + constexpr std::uint8_t icr1 { 0x86U }; // 16-bit register + constexpr std::uint8_t ocr1a { 0x88U }; // 16-bit register + constexpr std::uint8_t ocr1b { 0x8AU }; // 16-bit register + constexpr std::uint8_t timsk1 { 0x6FU }; - constexpr std::uint8_t tifr2 = 0x17U + sfr_offset; - constexpr std::uint8_t tccr2a = 0xB0U; - constexpr std::uint8_t tccr2b = 0xB1U; - constexpr std::uint8_t tcnt2 = 0xB2U; - constexpr std::uint8_t ocr2a = 0xB3U; - constexpr std::uint8_t timsk2 = 0x70U; + constexpr std::uint8_t tifr2 { 0x17U + sfr_offset }; + constexpr std::uint8_t tccr2a { 0xB0U }; + constexpr std::uint8_t tccr2b { 0xB1U }; + constexpr std::uint8_t tcnt2 { 0xB2U }; + constexpr std::uint8_t ocr2a { 0xB3U }; + constexpr std::uint8_t timsk2 { 0x70U }; // SPI(TM) registers. - constexpr std::uint8_t spcr = 0x2CU + sfr_offset; - constexpr std::uint8_t spsr = 0x2DU + sfr_offset; - constexpr std::uint8_t spdr = 0x2EU + sfr_offset; + constexpr std::uint8_t spcr { 0x2CU + sfr_offset }; + constexpr std::uint8_t spsr { 0x2DU + sfr_offset }; + constexpr std::uint8_t spdr { 0x2EU + sfr_offset }; // Watchdog registers - constexpr std::uint8_t wdtcsr = 0x60U; + constexpr std::uint8_t wdtcsr { 0x60U }; // Eeprom registers - constexpr std::uint8_t eecr = 0x1FU + sfr_offset; - constexpr std::uint8_t eedr = 0x20U + sfr_offset; - constexpr std::uint8_t eear = 0x21U + sfr_offset; - constexpr std::uint8_t eearl = 0x21U + sfr_offset; - constexpr std::uint8_t eearh = 0x22U + sfr_offset; + constexpr std::uint8_t eecr { 0x1FU + sfr_offset }; + constexpr std::uint8_t eedr { 0x20U + sfr_offset }; + constexpr std::uint8_t eear { 0x21U + sfr_offset }; + constexpr std::uint8_t eearl { 0x21U + sfr_offset }; + constexpr std::uint8_t eearh { 0x22U + sfr_offset }; } } #include #include -#endif // MCAL_REG_2010_04_10_H_ +#endif // MCAL_REG_2010_04_10_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_ser.h b/examples/chapter12_04/src/mcal/avr/mcal_ser.h new file mode 100644 index 000000000..bdcb95ad9 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_ser.h @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_SER_2011_10_20_H + #define MCAL_SER_2011_10_20_H + + namespace mcal + { + namespace ser + { + using config_type = void; + + inline auto init(const config_type*) -> void { } + } + } + +#endif // MCAL_SER_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_spi.cpp b/examples/chapter12_04/src/mcal/avr/mcal_spi.cpp new file mode 100644 index 000000000..cf6952d71 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_spi.cpp @@ -0,0 +1,12 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#include + +auto mcal::spi::init(const config_type*) -> void +{ +} diff --git a/examples/chapter12_04/src/mcal/avr/mcal_spi.h b/examples/chapter12_04/src/mcal/avr/mcal_spi.h new file mode 100644 index 000000000..81790dbd3 --- /dev/null +++ b/examples/chapter12_04/src/mcal/avr/mcal_spi.h @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 MCAL_SPI_2012_05_24_H + #define MCAL_SPI_2012_05_24_H + + namespace mcal { namespace spi { + + using config_type = void; + + auto init(const config_type*) -> void; + + } } + +#endif // MCAL_SPI_2012_05_24_H diff --git a/examples/chapter12_04/src/mcal/avr/mcal_wdg.cpp b/examples/chapter12_04/src/mcal/avr/mcal_wdg.cpp index ab4e54b7e..2165648cd 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_wdg.cpp +++ b/examples/chapter12_04/src/mcal/avr/mcal_wdg.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,12 +8,7 @@ #include #include -// This following function is not used. -// It is, however, kept as an example of *turning off* -// the wdt if wdton is set in the fuse bits. -void mcal_wdg_turn_off_wdt_if_wdton_is_set(); - -void mcal::wdg::init(const config_type*) +auto mcal::wdg::init(const config_type*) -> void { // Read the MCU status register. volatile const std::uint8_t mcu_status_register = @@ -34,45 +29,32 @@ void mcal::wdg::init(const config_type*) // Reset the watchdog timer. asm volatile("wdr"); - // Set the watchdog timer period and activate the watchdog timer. + // Start timed sequence in order to set the watchdog + // timer period and activate the watchdog timer. mcal::reg::reg_access_static::reg_set(); - // See Chapter 11.9.2, Table 11-2: Watchdog Timer Prescale Select. - // Select WDP3:WDP0 in WDTCSR to binary 0011, resulting in a watchdog - // period of approximately 125ms. + // In "Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf", + // see Chapter 10.9.2, Table 10-3: Watchdog Timer Prescale Select. + // Set WDP3 (bit 5) and clear WDP2:WDP0 (bits 0, 1 and 2) in WDTCSR + // (i.e., set to hex 0x20). This results in a watchdog period + // of approximately 4s. mcal::reg::reg_access_static::reg_set(); -} - -void mcal::wdg::secure::trigger() -{ - asm volatile("wdr"); -} + std::uint8_t(0x20U)>::reg_set(); -void mcal_wdg_turn_off_wdt_if_wdton_is_set() -{ - asm volatile("wdr"); - - // Clear WDRF in the MCU status register. + // Set WDRF in the MCU status register. mcal::reg::reg_access_static::bit_clr(); - - // Set WDCE and WDE. - mcal::reg::reg_access_static::reg_or(); + std::uint8_t(3U)>::bit_set(); +} - // Turn off the WDT. - mcal::reg::reg_access_static::reg_set(); +auto mcal::wdg::secure::trigger() -> void +{ + asm volatile("wdr"); } + diff --git a/examples/chapter12_04/src/mcal/avr/mcal_wdg.h b/examples/chapter12_04/src/mcal/avr/mcal_wdg.h index 97527bb64..94949ac58 100644 --- a/examples/chapter12_04/src/mcal/avr/mcal_wdg.h +++ b/examples/chapter12_04/src/mcal/avr/mcal_wdg.h @@ -1,34 +1,26 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_WDT_2010_04_10_H_ - #define MCAL_WDT_2010_04_10_H_ - - extern "C" void __my_startup() __attribute__((section(".startup"), used, noinline)); - - namespace sys { namespace idle { void task_func(); } } +#ifndef MCAL_WDT_2010_04_10_H + #define MCAL_WDT_2010_04_10_H namespace mcal { namespace wdg { - typedef void config_type; + using config_type = void; - void init(const config_type*); + auto init(const config_type*) -> void; struct secure final { - private: - static void trigger(); - - friend void ::sys::idle::task_func(); - friend void ::__my_startup(); + static auto trigger() -> void; }; } } -#endif // MCAL_WDT_2010_04_10_H_ +#endif // MCAL_WDT_2010_04_10_H diff --git a/examples/chapter12_04/src/mcal/mcal.cpp b/examples/chapter12_04/src/mcal/mcal.cpp index 06c77cb46..985f7f0d9 100644 --- a/examples/chapter12_04/src/mcal/mcal.cpp +++ b/examples/chapter12_04/src/mcal/mcal.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,7 +7,7 @@ #include -void mcal::init() +auto mcal::init() -> void { // Initialize the microcontroller abstraction layer. @@ -20,6 +20,10 @@ void mcal::init() mcal::irq::init(nullptr); mcal::gpt::init(nullptr); + mcal::ser::init(nullptr); + mcal::spi::init(nullptr); + mcal::pwm::init(nullptr); + mcal::eep::init(nullptr); mcal::cpu::post_init(); } diff --git a/examples/chapter12_04/src/mcal/mcal.h b/examples/chapter12_04/src/mcal/mcal.h index 063017a4f..ba0967737 100644 --- a/examples/chapter12_04/src/mcal/mcal.h +++ b/examples/chapter12_04/src/mcal/mcal.h @@ -1,28 +1,35 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_2011_10_20_H_ - #define MCAL_2011_10_20_H_ +#ifndef MCAL_2011_10_20_H + #define MCAL_2011_10_20_H #include + #include #include #include #include - #include + #include + #include + #include + #include #include - static_assert( (std::numeric_limits::digits >= 32) - && (std::numeric_limits::is_integer == true) - && (std::numeric_limits::is_signed == false), - "The gpt value type must be an unsigned integer type having at least 32 bits"); + #include + #include + + static_assert( (std::numeric_limits::digits >= static_cast(INT8_C(64))) + && std::numeric_limits::is_integer + && (!std::numeric_limits::is_signed), + "The gpt value type must be an unsigned integer type having at least 64 bits."); namespace mcal { - void init(); - } + auto init() -> void; + } // namespace mcal -#endif // MCAL_2011_10_20_H_ +#endif // MCAL_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/mcal_gcc_cxx_completion.cpp b/examples/chapter12_04/src/mcal/mcal_gcc_cxx_completion.cpp index 1aaa4b8e8..7b5774387 100644 --- a/examples/chapter12_04/src/mcal/mcal_gcc_cxx_completion.cpp +++ b/examples/chapter12_04/src/mcal/mcal_gcc_cxx_completion.cpp @@ -1,22 +1,28 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. // 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 +#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 +43,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) { // This is a naive and not completely functional // implementation of operator new(). In particular, there is @@ -51,10 +52,10 @@ void* operator new(std::size_t size) UTIL_NOEXCEPT volatile static std::uint8_t* get_ptr = buffer; // Get the newly allocated pointer. - volatile std::uint8_t* p = get_ptr; + volatile std::uint8_t* p { get_ptr }; // Does this allocation overflow the top of the buffer? - const bool is_overflow = ((get_ptr + size) >= (buffer + sizeof(buffer))); + const bool is_overflow { ((get_ptr + size) >= (buffer + sizeof(buffer))) }; // Increment the pointer for next time. // But only do this if the buffer does *not* overflow. @@ -70,10 +71,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 +88,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 () __attribute__((noreturn)); + int atexit (void (*)()); + int at_quick_exit (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); @@ -105,17 +107,16 @@ extern "C" int _kill (int, int); void __cxa_pure_virtual (); 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 () { 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; } @@ -128,22 +129,40 @@ extern "C" int _kill (int, int) { return -1; } void __cxa_pure_virtual () { } 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 }; + const char* const __env[1U] = { nullptr }; + + char** environ { nullptr }; + + #if (defined(__GNUC__) && defined(__v850__)) + #else + extern int* __errno(); + int* __errno() { return nullptr; } + #endif + + std::uint8_t __fdlib_version; - int __errno = 0; - std::uint8_t __fdlib_version = UINT8_C(0); + // Patched DSO label. + void* __dso_handle; +} + +void mcal_gcc_cxx_dummy() +{ + static_cast(__env); + static_cast(environ); } -// 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/chapter12_04/src/mcal/mcal_helper.h b/examples/chapter12_04/src/mcal/mcal_helper.h new file mode 100644 index 000000000..44b4b9d50 --- /dev/null +++ b/examples/chapter12_04/src/mcal/mcal_helper.h @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_HELPER_2020_05_21_H + #define MCAL_HELPER_2020_05_21_H + + #include + #include + + #include + #include + + namespace mcal { namespace helper { + + template + auto nop_maker() -> typename std::enable_if<(1U < nop_count) && (nop_count <= 12U), void>::type + { + nop_maker(); + + mcal::cpu::nop(); + } + + template + auto nop_maker() -> typename std::enable_if<(nop_count == 1U), void>::type + { + mcal::cpu::nop(); + } + + template + auto nop_maker() -> typename std::enable_if<(nop_count == 0U), void>::type + { + } + + template + auto nop_maker() -> typename std::enable_if<(12U < nop_count), void>::type + { + for(std::uint_fast16_t i = 0U; i < nop_count; ++i) + { + mcal::cpu::nop(); + } + } + + template + auto disable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if::type* = nullptr) noexcept -> void + { + mcal::irq::disable_all(); + } + + template + auto enable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if::type* = nullptr) noexcept -> void + { + mcal::irq::enable_all(); + } + + template + auto disable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if<(!has_disable_enable_interrupts)>::type* = nullptr) noexcept -> void { } + + template + auto enable_all_interrupts(const bool = has_disable_enable_interrupts, + const typename std::enable_if<(!has_disable_enable_interrupts)>::type* = nullptr) noexcept -> void { } + + } } // namespace mcal::helper + +#endif // MCAL_HELPER_2020_05_21_H diff --git a/examples/chapter12_04/src/mcal/mcal_reg_access_dynamic.h b/examples/chapter12_04/src/mcal/mcal_reg_access_dynamic.h index 85cd37341..3bc3cf54b 100644 --- a/examples/chapter12_04/src/mcal/mcal_reg_access_dynamic.h +++ b/examples/chapter12_04/src/mcal/mcal_reg_access_dynamic.h @@ -1,37 +1,60 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2013 - 2019. +// Copyright Christopher Kormanyos 2013 - 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_REG_ACCESS_DYNAMIC_2013_12_13_H_ - #define MCAL_REG_ACCESS_DYNAMIC_2013_12_13_H_ +#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)); } }; } } -#endif // MCAL_REG_ACCESS_DYNAMIC_2013_12_13_H_ + #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/chapter12_04/src/mcal/mcal_reg_access_static.h b/examples/chapter12_04/src/mcal/mcal_reg_access_static.h index 457ffa60a..564c3dc2f 100644 --- a/examples/chapter12_04/src/mcal/mcal_reg_access_static.h +++ b/examples/chapter12_04/src/mcal/mcal_reg_access_static.h @@ -1,39 +1,60 @@ -/////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef MCAL_REG_ACCESS_STATIC_2010_12_01_H_ - #define MCAL_REG_ACCESS_STATIC_2010_12_01_H_ +#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)); } }; } } -#endif // MCAL_REG_ACCESS_STATIC_2010_12_01_H_ + #if defined(__GNUC__) && (__GNUC__ >= 12) + #pragma GCC diagnostic pop + #endif + +#endif // MCAL_REG_ACCESS_STATIC_2010_12_01_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_benchmark.h b/examples/chapter12_04/src/mcal/win32/mcal_benchmark.h index d82ada498..4795ccb6d 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_benchmark.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_benchmark.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014. +// Copyright Christopher Kormanyos 2014 - 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_BENCHMARK_2014_04_16_H_ - #define MCAL_BENCHMARK_2014_04_16_H_ +#ifndef MCAL_BENCHMARK_2014_04_16_H + #define MCAL_BENCHMARK_2014_04_16_H #include @@ -14,8 +14,8 @@ { namespace benchmark { - typedef mcal::port::port_pin benchmark_port_type; - } - } + using benchmark_port_type = mcal::port::port_pin; + } // namespace benchmark + } // namespace mcal -#endif // MCAL_BENCHMARK_2014_04_16_H_ +#endif // MCAL_BENCHMARK_2014_04_16_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_cpu.cpp b/examples/chapter12_04/src/mcal/win32/mcal_cpu.cpp index baa759ffe..7c24cbb78 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_cpu.cpp +++ b/examples/chapter12_04/src/mcal/win32/mcal_cpu.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2019. +// 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) @@ -7,6 +7,7 @@ #include -void mcal::cpu::init() +auto mcal::cpu::init() -> void { + // Subroutine is empty on purpose. } diff --git a/examples/chapter12_04/src/mcal/win32/mcal_cpu.h b/examples/chapter12_04/src/mcal/win32/mcal_cpu.h index de20b6b76..e5ea780c6 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_cpu.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_cpu.h @@ -1,26 +1,30 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef MCAL_CPU_2009_02_14_H_ - #define MCAL_CPU_2009_02_14_H_ +#ifndef MCAL_CPU_2009_02_14_H + #define MCAL_CPU_2009_02_14_H #define MY_PROGMEM #include #include - namespace mcal { namespace cpu { + namespace mcal + { + namespace cpu + { - void init(); + auto init() -> void; - inline void post_init() { } + inline auto post_init() -> void { } - inline void nop() { } + inline auto nop() -> void { } - } } // namespace mcal::cpu + } // namespace cpu + } // namespace mcal -#endif // MCAL_CPU_2009_02_14_H_ +#endif // MCAL_CPU_2009_02_14_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_eep.cpp b/examples/chapter12_04/src/mcal/win32/mcal_eep.cpp new file mode 100644 index 000000000..2c7c06b8b --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_eep.cpp @@ -0,0 +1,14 @@ +#include + +auto mcal::eep::write(const address_type addr, const std::uint8_t data) -> void // NOLINT(bugprone-easily-swappable-parameters) +{ + static_cast(addr); + static_cast(data); +} + +auto mcal::eep::read(const address_type addr) -> std::uint8_t +{ + static_cast(addr); + + return static_cast(UINT8_C(0)); +} diff --git a/examples/chapter12_04/src/mcal/win32/mcal_eep.h b/examples/chapter12_04/src/mcal/win32/mcal_eep.h new file mode 100644 index 000000000..3e7d03690 --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_eep.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 MCAL_EEP_2018_12_15_H + #define MCAL_EEP_2018_12_15_H + + #include + + namespace mcal + { + namespace eep + { + using config_type = void; + using address_type = std::uint64_t; + + inline auto init(const config_type*) -> void { } + + auto write(const address_type addr, const std::uint8_t data) -> void; + auto read (const address_type addr) -> std::uint8_t; + } // namespace eep + } // namespace mcal + +#endif // MCAL_EEP_2018_12_15_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_gpt.cpp b/examples/chapter12_04/src/mcal/win32/mcal_gpt.cpp index be20522fb..d045e18f9 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_gpt.cpp +++ b/examples/chapter12_04/src/mcal/win32/mcal_gpt.cpp @@ -1,50 +1,22 @@ /////////////////////////////////////////////////////////////////////////////// -// 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 -namespace +auto mcal::gpt::secure::get_time_elapsed() -> mcal::gpt::value_type { - using mcal_gpt_time_point_type = - std::chrono::high_resolution_clock::time_point; - - static const mcal_gpt_time_point_type& mcal_gpt_time_point_init() - { - static const mcal_gpt_time_point_type init = - std::chrono::high_resolution_clock::now(); - - return init; - } - - std::uint_fast16_t mcal_gpt_sleep_prescaler; -} - -mcal::gpt::value_type mcal::gpt::secure::get_time_elapsed() -{ - ++mcal_gpt_sleep_prescaler; - - if((mcal_gpt_sleep_prescaler % UINT16_C(8192)) == 0U) - { - // Sleep in order to reduce the load on a PC target. - std::this_thread::sleep_for(std::chrono::milliseconds(3U)); - } - else - { - std::this_thread::yield(); - } - - const std::chrono::microseconds duration_in_microseconds = + // Return the system tick with a resolution of 1us. + const auto epoch_now_micro_sec = std::chrono::duration_cast - (std::chrono::high_resolution_clock::now() - mcal_gpt_time_point_init()); + ( + std::chrono::high_resolution_clock::now().time_since_epoch() + ); - // Return the system tick with a resolution of 1us. - return static_cast(duration_in_microseconds.count()); + return static_cast(epoch_now_micro_sec.count()); } diff --git a/examples/chapter12_04/src/mcal/win32/mcal_gpt.h b/examples/chapter12_04/src/mcal/win32/mcal_gpt.h index 78be29bfe..e1a6ee00e 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_gpt.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_gpt.h @@ -1,44 +1,29 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2018. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_GPT_2011_10_20_H_ - #define MCAL_GPT_2011_10_20_H_ +#ifndef MCAL_GPT_2011_10_20_H + #define MCAL_GPT_2011_10_20_H - #include #include - #include - - // Forward declaration of the util::timer template class. - namespace util - { - template - class timer; - } - namespace mcal { namespace gpt { - typedef void config_type; - typedef std::uint64_t value_type; + using config_type = void; + using value_type = std::uint64_t; - inline void init(const config_type*) { } + inline auto init(const config_type*) noexcept -> void { } - class secure final + struct secure final { - static value_type get_time_elapsed(); - - friend std::chrono::high_resolution_clock::time_point std::chrono::high_resolution_clock::now() UTIL_NOEXCEPT; - - template - friend class util::timer; + static auto get_time_elapsed() -> value_type; }; - } - } + } // namespace gpt + } // namespace mcal -#endif // MCAL_GPT_2011_10_20_H_ +#endif // MCAL_GPT_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_irq.cpp b/examples/chapter12_04/src/mcal/win32/mcal_irq.cpp index f9f983c47..c6f1b0b97 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_irq.cpp +++ b/examples/chapter12_04/src/mcal/win32/mcal_irq.cpp @@ -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) @@ -7,7 +7,7 @@ #include -void mcal::irq::init(const config_type*) +auto mcal::irq::init(const config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter) { mcal::irq::enable_all(); } diff --git a/examples/chapter12_04/src/mcal/win32/mcal_irq.h b/examples/chapter12_04/src/mcal/win32/mcal_irq.h index 74a244f9d..0eee5f010 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_irq.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_irq.h @@ -1,24 +1,24 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_IRQ_2010_04_10_H_ - #define MCAL_IRQ_2010_04_10_H_ +#ifndef MCAL_IRQ_2010_04_10_H + #define MCAL_IRQ_2010_04_10_H namespace mcal { namespace irq { - typedef void config_type; + using config_type = void; - void init(const config_type*); + auto init(const config_type*) -> void; - inline void enable_all () { } - inline void disable_all() { } - } - } + inline auto enable_all () noexcept -> void { } + inline auto disable_all() noexcept -> void { } + } // namespace irq + } // namespace mcal -#endif // MCAL_IRQ_2010_04_10_H_ +#endif // MCAL_IRQ_2010_04_10_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_led.cpp b/examples/chapter12_04/src/mcal/win32/mcal_led.cpp index 0cf8e3e21..5ff98bfd1 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_led.cpp +++ b/examples/chapter12_04/src/mcal/win32/mcal_led.cpp @@ -1,33 +1,16 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // #include -#include +#include -namespace mcal +auto mcal::led::led0() -> mcal::led::led_base& { - namespace led - { - const led_type led0; - } -} - -void mcal::led::led::toggle() const -{ - // Toggle the LED state. - is_on = (!is_on); + static mcal::led::led_console local_led0; - // Print the LED state. - if(is_on) - { - std::cout << "LED is on" << std::endl; - } - else - { - std::cout << "LED is off" << std::endl; - } + return local_led0; } diff --git a/examples/chapter12_04/src/mcal/win32/mcal_led.h b/examples/chapter12_04/src/mcal/win32/mcal_led.h index 62af958b8..1897eb522 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_led.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_led.h @@ -1,34 +1,21 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef MCAL_LED_2010_09_14_H_ - #define MCAL_LED_2010_09_14_H_ +#ifndef MCAL_LED_2010_09_14_H + #define MCAL_LED_2010_09_14_H - #include + #include namespace mcal { namespace led { - class led final : private util::noncopyable - { - public: - led() : is_on(false) { } + auto led0() -> led_base&; + } // namespace led + } // namespace mcal - void toggle() const; - - private: - mutable bool is_on; - }; - - typedef led led_type; - - extern const led_type led0; - } - } - -#endif // MCAL_LED_2010_09_14_H_ +#endif // MCAL_LED_2010_09_14_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_memory_progmem.h b/examples/chapter12_04/src/mcal/win32/mcal_memory_progmem.h index 045aa65d1..68b4da38a 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_memory_progmem.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_memory_progmem.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2019 - 2020. +// 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 MCAL_MEMORY_PROGMEM_2019_08_17_H_ - #define MCAL_MEMORY_PROGMEM_2019_08_17_H_ +#ifndef MCAL_MEMORY_PROGMEM_2019_08_17_H + #define MCAL_MEMORY_PROGMEM_2019_08_17_H #include @@ -71,4 +71,4 @@ } #endif -#endif // MCAL_MEMORY_PROGMEM_2019_08_17_H_ +#endif // MCAL_MEMORY_PROGMEM_2019_08_17_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_osc.cpp b/examples/chapter12_04/src/mcal/win32/mcal_osc.cpp new file mode 100644 index 000000000..79036e733 --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_osc.cpp @@ -0,0 +1,13 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 + +auto mcal::osc::init(const config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter) +{ + // Subroutine is empty on purpose. +} diff --git a/examples/chapter12_04/src/mcal/win32/mcal_osc.h b/examples/chapter12_04/src/mcal/win32/mcal_osc.h new file mode 100644 index 000000000..603503bab --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_osc.h @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#ifndef MCAL_OSC_2011_10_20_H + #define MCAL_OSC_2011_10_20_H + + namespace mcal + { + namespace osc + { + using config_type = void; + + auto init(const config_type*) -> void; + } // namespace osc + } // namespace mcal + +#endif // MCAL_OSC_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_port.cpp b/examples/chapter12_04/src/mcal/win32/mcal_port.cpp new file mode 100644 index 000000000..7d5c0e23a --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_port.cpp @@ -0,0 +1,13 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2018. +// 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 + +auto mcal::port::init(const config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter) +{ + // Subroutine is empty on purpose. +} diff --git a/examples/chapter12_04/src/mcal/win32/mcal_port.h b/examples/chapter12_04/src/mcal/win32/mcal_port.h index ab7786dcb..85a2d865c 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_port.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_port.h @@ -1,31 +1,32 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef MCAL_PORT_2012_06_27_H_ - #define MCAL_PORT_2012_06_27_H_ +#ifndef MCAL_PORT_2012_06_27_H + #define MCAL_PORT_2012_06_27_H namespace mcal { namespace port { - typedef void config_type; - inline void init(const config_type*) { } + using config_type = void; + + auto init(const config_type*) -> void; class port_pin { public: - static void set_direction_output() { } - static void set_direction_input() { } - static void set_pin_high() { } - static void set_pin_low() { } - static bool read_input_value() { return false; } - static void toggle_pin() { } + static constexpr auto set_direction_output() noexcept -> void { } + static constexpr auto set_direction_input () noexcept -> void { } + static constexpr auto set_pin_high () noexcept -> void { } + static constexpr auto set_pin_low () noexcept -> void { } + static constexpr auto read_input_value () noexcept -> bool { return false; } + static constexpr auto toggle_pin () noexcept -> void { } }; - } - } + } // namespace port + } // namespace mcal -#endif // MCAL_PORT_2012_06_27_H_ +#endif // MCAL_PORT_2012_06_27_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_pwm.cpp b/examples/chapter12_04/src/mcal/win32/mcal_pwm.cpp new file mode 100644 index 000000000..ed11d307b --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_pwm.cpp @@ -0,0 +1,20 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 + +auto mcal::pwm::pwm0() noexcept -> mcal::pwm::pwm_base& +{ + static mcal::pwm::pwm_console pwm; + + static const volatile bool init_is_ok = pwm.init(); + + static_cast(init_is_ok); + + return pwm; +} diff --git a/examples/chapter12_04/src/mcal/win32/mcal_pwm.h b/examples/chapter12_04/src/mcal/win32/mcal_pwm.h new file mode 100644 index 000000000..55e35aa0b --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_pwm.h @@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#ifndef MCAL_PWM_2010_09_14_H + #define MCAL_PWM_2010_09_14_H + + #include + + namespace mcal + { + namespace pwm + { + using config_type = void; + + inline auto init(const config_type*) -> void { } + + auto pwm0() noexcept -> mcal::pwm::pwm_base&; + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_2010_09_14_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_reg.h b/examples/chapter12_04/src/mcal/win32/mcal_reg.h index 0d515d259..1a1f5a019 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_reg.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_reg.h @@ -1,14 +1,14 @@ /////////////////////////////////////////////////////////////////////////////// -// 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 MCAL_REG_2010_04_10_H_ - #define MCAL_REG_2010_04_10_H_ +#ifndef MCAL_REG_2010_04_10_H + #define MCAL_REG_2010_04_10_H #include #include -#endif // MCAL_REG_2010_04_10_H_ +#endif // MCAL_REG_2010_04_10_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_ser.h b/examples/chapter12_04/src/mcal/win32/mcal_ser.h new file mode 100644 index 000000000..599e71bd5 --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_ser.h @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#ifndef MCAL_SER_2011_10_20_H + #define MCAL_SER_2011_10_20_H + + namespace mcal + { + namespace ser + { + using config_type = void; + + inline auto init(const config_type*) -> void { } + } // namespace ser + } // namespace mcal + +#endif // MCAL_SER_2011_10_20_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_spi.cpp b/examples/chapter12_04/src/mcal/win32/mcal_spi.cpp new file mode 100644 index 000000000..b0f02b30b --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_spi.cpp @@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2012 - 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 + +auto mcal::spi::init(const mcal::spi::config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter) +{ + // Subroutine is empty on purpose. +} + +auto mcal::spi::spi0() -> util::communication_base& +{ + static mcal::spi::spi_software_dummy com0; + + return com0; +} diff --git a/examples/chapter12_04/src/mcal/win32/mcal_spi.h b/examples/chapter12_04/src/mcal/win32/mcal_spi.h new file mode 100644 index 000000000..c0f26e71b --- /dev/null +++ b/examples/chapter12_04/src/mcal/win32/mcal_spi.h @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2012 - 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 MCAL_SPI_2012_05_24_H + #define MCAL_SPI_2012_05_24_H + + #include + + namespace mcal + { + namespace spi + { + + using config_type = void; + + auto init(const config_type*) -> void; + + auto spi0() -> util::communication_base&; + + } // namespace spi + } // namespace mcal + +#endif // MCAL_SPI_2012_05_24_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_wdg.cpp b/examples/chapter12_04/src/mcal/win32/mcal_wdg.cpp index 61ec5b480..ca35c55aa 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_wdg.cpp +++ b/examples/chapter12_04/src/mcal/win32/mcal_wdg.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) @@ -7,11 +7,18 @@ #include -void mcal::wdg::init(const config_type*) +auto mcal::wdg::init(const config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter) { + // Subroutine is empty on purpose. } -void mcal::wdg::secure::trigger() +auto mcal::wdg::secure::trigger() -> void { - mcal::wdg::watchdog::the_watchdog.reset_watchdog_timer(); + using local_watchdog_timer_type = watchdog_base::base_timer_type; + + constexpr auto time_two_seconds = static_cast(UINT8_C(2)); + + using local_watchdog_type = watchdog; + + local_watchdog_type::my_watchdog.reset_watchdog_timer(); } diff --git a/examples/chapter12_04/src/mcal/win32/mcal_wdg.h b/examples/chapter12_04/src/mcal/win32/mcal_wdg.h index e79d6714d..a26e36a84 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_wdg.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_wdg.h @@ -1,30 +1,26 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_WDG_2010_04_10_H_ - #define MCAL_WDG_2010_04_10_H_ - - namespace sys { namespace idle { void task_func(); } } +#ifndef MCAL_WDG_2010_04_10_H + #define MCAL_WDG_2010_04_10_H namespace mcal { namespace wdg { - typedef void config_type; + using config_type = void; - void init(const config_type*); + auto init(const config_type*) -> void; - class secure final + struct secure final { - static void trigger(); - - friend void ::sys::idle::task_func(); + static auto trigger() -> void; }; - } - } + } // namespace wdg + } // namespace mcal -#endif // MCAL_WDG_2010_04_10_H_ +#endif // MCAL_WDG_2010_04_10_H diff --git a/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.cpp b/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.cpp index decb2bcba..e82bdb756 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.cpp +++ b/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.cpp @@ -1,55 +1,15 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2013. +// 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) // -#include #include -#include - -const mcal::wdg::watchdog::timer_type::tick_type mcal::wdg::watchdog::my_period(timer_type::seconds(2U)); -mcal::wdg::watchdog mcal::wdg::watchdog::the_watchdog(watchdog::the_watchdog_thread_function); - -bool mcal::wdg::watchdog::get_watchdog_timeout() -{ - my_mutex.lock(); - const bool timeout_result = my_timer.timeout(); - my_mutex.unlock(); - return timeout_result; -} - -void mcal::wdg::watchdog::reset_watchdog_timer() -{ - my_mutex.lock(); - my_timer.start_relative(the_watchdog.my_period); - my_mutex.unlock(); -} +#include -void mcal::wdg::watchdog::the_watchdog_thread_function() +auto mcal::wdg::print_timeout_message() -> void { - std::this_thread::sleep_for(std::chrono::milliseconds(10U)); - - bool timeout_has_occurred = false; - - for(;;) - { - if(timeout_has_occurred) - { - std::cout << "error: at least one watchdog timeout has occurred" << std::endl; - - std::this_thread::sleep_for(std::chrono::milliseconds(500U)); - } - else - { - if(watchdog::the_watchdog.get_watchdog_timeout()) - { - timeout_has_occurred = true; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(20U)); - } - } + std::cout << "error: at least one watchdog timeout has occurred" << std::endl; } diff --git a/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.h b/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.h index 039302c61..d93c2eda2 100644 --- a/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.h +++ b/examples/chapter12_04/src/mcal/win32/mcal_wdg_watchdog.h @@ -1,55 +1,129 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2013. +// 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_WDG_WATCHDOG_2013_12_11_H_ - #define MCAL_WDG_WATCHDOG_2013_12_11_H_ +#ifndef MCAL_WDG_WATCHDOG_2013_12_11_H + #define MCAL_WDG_WATCHDOG_2013_12_11_H - #include - #include #include + #include #include + #include + #include + #include + #include + + #if defined(_MSC_VER) + #define MCAL_WDG_NORETURN + #else + #define MCAL_WDG_NORETURN [[noreturn]] + #endif + namespace mcal { namespace wdg { - class watchdog; + auto print_timeout_message() -> void; + + class watchdog_base : private util::noncopyable + { + public: + using base_timer_type = util::timer; + + watchdog_base() noexcept = default; + watchdog_base(const watchdog_base&) = delete; + watchdog_base(watchdog_base&&) = delete; + + auto operator=(const watchdog_base&) -> watchdog_base& = delete; + auto operator=(watchdog_base&&) -> watchdog_base& = delete; + + virtual ~watchdog_base() noexcept = default; + }; - class watchdog : private util::noncopyable + template + class watchdog : public watchdog_base { public: - typedef util::timer timer_type; + using timer_type = watchdog_base::base_timer_type; + + watchdog() noexcept = delete; + watchdog(const watchdog&) = delete; + watchdog(watchdog&&) = delete; + + auto operator=(const watchdog&) -> watchdog& = delete; + auto operator=(watchdog&&) -> watchdog& = delete; - ~watchdog() { } + ~watchdog() noexcept override = default; private: - typedef void(*function_type)(); + using function_type = std::function; + + explicit watchdog(const function_type& pf) : my_thread(pf) { } + + static constexpr timer_type::tick_type my_period = MyPeriod; + + timer_type my_timer { my_period }; + const std::thread my_thread; - watchdog(function_type function) : my_timer (my_period), - my_mutex (), - my_thread(function) { } + static watchdog my_watchdog; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static std::atomic_flag my_lock; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - static const timer_type::tick_type my_period; + auto get_watchdog_timeout() const -> bool + { + while(my_lock.test_and_set()) { ; } + const auto timeout_result = my_timer.timeout(); + my_lock.clear(); - timer_type my_timer; - std::mutex my_mutex; - std::thread my_thread; + return timeout_result; + } - static watchdog the_watchdog; + auto reset_watchdog_timer() -> void + { + while(my_lock.test_and_set()) { ; } + my_timer.start_relative(my_period); + my_lock.clear(); + } - bool get_watchdog_timeout(); - void reset_watchdog_timer(); + MCAL_WDG_NORETURN static auto thread_function() -> void + { + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(UINT8_C(10)))); - static void the_watchdog_thread_function(); + bool timeout_has_occurred = false; - friend class ::mcal::wdg::secure; + for(;;) + { + if(timeout_has_occurred) + { + print_timeout_message(); + + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(UINT16_C(500)))); + } + else + { + if(watchdog::my_watchdog.get_watchdog_timeout()) + { + timeout_has_occurred = true; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(UINT8_C(20)))); + } + } + } + + friend struct ::mcal::wdg::secure; }; - } - } -#endif // MCAL_WDG_WATCHDOG_2013_12_11_H_ + template + watchdog watchdog::my_watchdog(thread_function); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,cert-err58-cpp) + + template + std::atomic_flag watchdog::my_lock = ATOMIC_FLAG_INIT; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + } // namespace wdg + } // namespace mcal + +#endif // MCAL_WDG_WATCHDOG_2013_12_11_H diff --git a/examples/chapter12_04/src/mcal_lcd/mcal_lcd_base.h b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_base.h new file mode 100644 index 000000000..4b5a0cabf --- /dev/null +++ b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_base.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_LCD_BASE_2020_06_10_H // NOLINT(llvm-header-guard) + #define MCAL_LCD_BASE_2020_06_10_H + + #include + + #include + #include + + #if(__cplusplus >= 201703L) + namespace mcal::lcd { + #else + namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) + #endif + + class lcd_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + virtual ~lcd_base() = default; + + virtual auto init() -> bool = 0; + + virtual auto write(const char* pstr, + const std::size_t length, + const std::uint_fast8_t line_index) -> bool = 0; + + protected: + lcd_base() = default; // LCOV_EXCL_LINE + + virtual auto set_line_index(const std::uint8_t index) -> bool { static_cast(index); return true; } // LCOV_EXCL_LINE + }; + + #if(__cplusplus >= 201703L) + } // namespace mcal::lcd + #else + } // namespace lcd + } // namespace mcal + #endif + +#endif // MCAL_LCD_BASE_2020_06_10_H diff --git a/examples/chapter12_04/src/mcal_lcd/mcal_lcd_buffered_instance.h b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_buffered_instance.h new file mode 100644 index 000000000..12f8aa15f --- /dev/null +++ b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_buffered_instance.h @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 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_LCD_BUFFERED_INSTANCE_2024_02_07_H // NOLINT(llvm-header-guard) + #define MCAL_LCD_BUFFERED_INSTANCE_2024_02_07_H + + #include + + #include + #include + + #if(__cplusplus >= 201703L) + namespace mcal::lcd { + #else + namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) + #endif + + template + class lcd_buffered_instance : public mcal::lcd::lcd_base + { + private: + using backend_display_type = BackendDisplayType; + + using row_array_type = std::array(WidthInCols)>; + + using row_col_array_buffer_type = std::array(HeightInRows)>; + + public: + explicit lcd_buffered_instance(backend_display_type& backend_display) + : my_backend_display(backend_display) + { + for(auto& row : row_col_array_buffer) + { + row.fill(' '); + } + } + + lcd_buffered_instance() = delete; + + ~lcd_buffered_instance() override = default; + + static constexpr auto width () noexcept -> std::size_t { return std::tuple_size::value; } + static constexpr auto height() noexcept -> std::size_t { return std::tuple_size::value; } + + auto init() -> bool override { return my_backend_display.init(); } + + auto write(const char* pstr, + const std::size_t length, + const std::uint_fast8_t line_index) -> bool override + { + bool result_write_is_ok { }; + + if(line_index < static_cast(height())) + { + result_write_is_ok = true; + + row_array_type candidate_row; + + candidate_row.fill(' '); + + const auto length_to_copy = (std::min)(static_cast(length), static_cast(width())); + + std::copy(pstr, pstr + length_to_copy, candidate_row.begin()); + + if(candidate_row != row_col_array_buffer[static_cast(line_index)]) + { + result_write_is_ok = + my_backend_display.write + ( + candidate_row.data(), + static_cast(width()), + line_index + ); + + row_col_array_buffer[static_cast(line_index)] = candidate_row; + } + } + + return result_write_is_ok; + } + + private: + backend_display_type& my_backend_display; + + row_col_array_buffer_type row_col_array_buffer { }; + }; + + #if(__cplusplus >= 201703L) + } // namespace mcal::lcd + #else + } // namespace lcd + } // namespace mcal + #endif + +#endif // MCAL_LCD_BUFFERED_INSTANCE_2024_02_07_H diff --git a/examples/chapter12_04/src/mcal_lcd/mcal_lcd_console.h b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_console.h new file mode 100644 index 000000000..8d788208b --- /dev/null +++ b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_console.h @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_LCD_CONSOLE_2020_06_10_H // NOLINT(llvm-header-guard) + #define MCAL_LCD_CONSOLE_2020_06_10_H + + #include + + #include + #include + + #if(__cplusplus >= 201703L) + namespace mcal::lcd { + #else + namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) + #endif + + class lcd_console : public mcal::lcd::lcd_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + lcd_console() = default; // LCOV_EXCL_LINE + + ~lcd_console() override = default; + + auto write(const char* pstr, + const std::size_t length, // NOLINT(bugprone-easily-swappable-parameters) + const std::uint_fast8_t line_index) -> bool override + { + static_cast(line_index); + + bool write_is_ok { }; + + if((pstr != nullptr) && (length > 0U)) + { + const std::string str(pstr, pstr + length); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + + std::cout << str << std::endl; + + write_is_ok = true; + } + else + { + write_is_ok = false; + } + + return write_is_ok; + } + + auto init() -> bool override { return true; } // LCOV_EXCL_LINE + }; + + #if(__cplusplus >= 201703L) + } // namespace mcal::lcd + #else + } // namespace lcd + } // namespace mcal + #endif + +#endif // MCAL_LCD_CONSOLE_2020_06_10_H diff --git a/examples/chapter12_04/src/mcal_lcd/mcal_lcd_generic_st7066.h b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_generic_st7066.h new file mode 100644 index 000000000..acb3d1334 --- /dev/null +++ b/examples/chapter12_04/src/mcal_lcd/mcal_lcd_generic_st7066.h @@ -0,0 +1,166 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_LCD_GENERIC_ST7066_2020_05_07_H // NOLINT(llvm-header-guard) + #define MCAL_LCD_GENERIC_ST7066_2020_05_07_H + + #include + #include + + #include + + #include + #include + + #if(__cplusplus >= 201703L) + namespace mcal::lcd { + #else + namespace mcal { namespace lcd { // NOLINT(modernize-concat-nested-namespaces) + #endif + + template + class lcd_generic_st7066 final : public mcal::lcd::lcd_base + { + private: + using timer_type = util::timer; + + public: + lcd_generic_st7066() = default; + + ~lcd_generic_st7066() override = default; + + auto init() -> bool override + { + port_pin_rs__type::set_pin_low(); + port_pin_rw__type::set_pin_low(); + port_pin_e___type::set_pin_high(); + + P1_set(UINT8_C(0)); + + port_pin_rs__type::set_direction_output(); + port_pin_rw__type::set_direction_output(); + port_pin_e___type::set_direction_output(); + + P1_set_direction_output(); + + port_pin_e___type::set_pin_low(); + + blocking_delay(timer_type::milliseconds(15U)); // Set a timer which is at least 15ms from system start. + command(UINT8_C(0x30)); // Command 0x30 = Wake up + blocking_delay(timer_type::milliseconds(7U)); // Must wait 5ms, busy flag not available. + command(UINT8_C(0x30)); // Command 0x30 = Wake up 2 + blocking_delay(timer_type::microseconds(200U)); // Must wait 160us, busy flag not available + command(UINT8_C(0x30)); // Command 0x30 = Wake up 3 + blocking_delay(timer_type::microseconds(200U)); // Must wait 160us, busy flag not available + command(UINT8_C(0x38)); // Function set: 8-bit/2-line + command(UINT8_C(0x10)); // Set cursor + command(UINT8_C(0x0C)); // Display ON; Cursor ON + command(UINT8_C(0x06)); // Entry mode set + + const auto write_clear_lines_is_ok = ( write_n(nullptr, 0U, 0U) + && write_n(nullptr, 0U, 1U)); + + + return write_clear_lines_is_ok; + } + + auto write(const char* pstr, + const std::size_t length, + const std::uint_fast8_t line_index) -> bool override + { + std::uint_fast8_t char_index = 0U; + + command(std::uint8_t(0x80U + ((line_index == 0U) ? 0x00U : 0x40U))); + + if(pstr != nullptr) + { + // Write the line at line_index. + for( ; char_index < (std::min)(lcd_line_width, length); ++char_index) + { + write(std::uint8_t { pstr[char_index] }); + } + } + + for( ; char_index < lcd_line_width; ++char_index) + { + write(std::uint8_t { ' ' }); + } + + return true; + } + + private: + static void blocking_delay(const typename timer_type::tick_type blocking_delay_value) + { + timer_type::blocking_delay(blocking_delay_value); + } + + auto write(const std::uint8_t i) -> void + { + P1_set(i); // P1 = i; // Put data on the output Port + port_pin_rs__type::set_pin_high(); // D_I =1; // D/I=HIGH : send data + port_pin_rw__type::set_pin_low(); // R_W =0; // R/W=LOW : Write + port_pin_e___type::set_pin_high(); // E = 1; + blocking_delay(timer_type::microseconds(10U)); // Delay(1); // Enable pulse width >= 300ns + port_pin_e___type::set_pin_low(); // E = 0; // Clock enable: falling edge + } + + auto command(std::uint8_t i) -> void + { + P1_set(i); // P1 = i; // Put data on output Port + port_pin_rs__type::set_pin_low(); // D_I =0; // D/I=LOW : send instruction + port_pin_rw__type::set_pin_low(); // R_W =0; // R/W=LOW : Write + port_pin_e___type::set_pin_high(); // E = 1; + blocking_delay(timer_type::microseconds(10U)); // Delay(1); // Enable pulse width >= 300ns + port_pin_e___type::set_pin_low(); // E = 0; // Clock enable: falling edge + blocking_delay(timer_type::microseconds(40U)); // Command execution delay + } + + auto P1_set(const std::uint8_t c) -> void + { + (static_cast(c & UINT8_C(0x01)) != UINT8_C(0)) ? port_pin_db0_type::set_pin_high() : port_pin_db0_type::set_pin_low(); + (static_cast(c & UINT8_C(0x02)) != UINT8_C(0)) ? port_pin_db1_type::set_pin_high() : port_pin_db1_type::set_pin_low(); + (static_cast(c & UINT8_C(0x04)) != UINT8_C(0)) ? port_pin_db2_type::set_pin_high() : port_pin_db2_type::set_pin_low(); + (static_cast(c & UINT8_C(0x08)) != UINT8_C(0)) ? port_pin_db3_type::set_pin_high() : port_pin_db3_type::set_pin_low(); + (static_cast(c & UINT8_C(0x10)) != UINT8_C(0)) ? port_pin_db4_type::set_pin_high() : port_pin_db4_type::set_pin_low(); + (static_cast(c & UINT8_C(0x20)) != UINT8_C(0)) ? port_pin_db5_type::set_pin_high() : port_pin_db5_type::set_pin_low(); + (static_cast(c & UINT8_C(0x40)) != UINT8_C(0)) ? port_pin_db6_type::set_pin_high() : port_pin_db6_type::set_pin_low(); + (static_cast(c & UINT8_C(0x80)) != UINT8_C(0)) ? port_pin_db7_type::set_pin_high() : port_pin_db7_type::set_pin_low(); + } + + static auto P1_set_direction_output() -> void + { + port_pin_db0_type::set_direction_output(); + port_pin_db1_type::set_direction_output(); + port_pin_db2_type::set_direction_output(); + port_pin_db3_type::set_direction_output(); + port_pin_db4_type::set_direction_output(); + port_pin_db5_type::set_direction_output(); + port_pin_db6_type::set_direction_output(); + port_pin_db7_type::set_direction_output(); + } + }; + + #if(__cplusplus >= 201703L) + } // namespace mcal::lcd + #else + } // namespace lcd + } // namespace mcal + #endif + +#endif // MCAL_LCD_GENERIC_ST7066_2020_05_07_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_base.h b/examples/chapter12_04/src/mcal_led/mcal_led_base.h new file mode 100644 index 000000000..3d24f22f2 --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_base.h @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2025. +// 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 + + namespace mcal { namespace led { + + class led_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + virtual ~led_base() = default; + + virtual auto toggle() -> void = 0; + + virtual auto state_is_on() const noexcept -> bool = 0; + + protected: + constexpr led_base() = default; + }; + + } // namespace led + } // namespace mcal + +#endif // MCAL_LED_BASE_2020_04_32_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_boolean_state_base.h b/examples/chapter12_04/src/mcal_led/mcal_led_boolean_state_base.h new file mode 100644 index 000000000..f0faf337c --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_boolean_state_base.h @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2025. +// 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 // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + ~led_boolean_state_base() override = default; + + auto state_is_on() const noexcept -> bool override { return is_on; } + + protected: + constexpr led_boolean_state_base() = default; + + auto toggle() -> void override + { + // Toggle the LED state. + set_is_on(!is_on); + } + + auto set_is_on(const bool val) noexcept -> void { is_on = val; } + + private: + bool is_on { }; + }; + + } // namespace led + } // namespace mcal + +#endif // MCAL_LED_BOOLEAN_STATE_BASE_2020_08_07_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_console.h b/examples/chapter12_04/src/mcal_led/mcal_led_console.h new file mode 100644 index 000000000..8c15b5bba --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_console.h @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2025. +// 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 + #include + + namespace mcal { namespace led { + + class led_console final : public mcal::led::led_boolean_state_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + explicit constexpr led_console(const std::uint_fast8_t idx = std::uint_fast8_t { UINT8_C(0) }) noexcept + : my_index(idx) { } + + ~led_console() override = default; + + auto toggle() -> void override + { + using base_class_type = mcal::led::led_boolean_state_base; + + base_class_type::toggle(); + + // Print the LED state to the console. + std::stringstream strm { }; + + strm << "LED" + << static_cast(my_index) + << " is " + << (base_class_type::state_is_on() ? "on" : "off"); + + while(console_sync().test_and_set(std::memory_order_acquire)) { } + std::cout << strm.str() << std::endl; + console_sync().clear(std::memory_order_release); + } + + private: + const std::uint_fast8_t my_index { }; + + static auto console_sync() noexcept -> std::atomic_flag& + { + static std::atomic_flag console_lock { }; + + return console_lock; + } + }; + + } // namespace led + } // namespace mcal + +#endif // MCAL_LED_CONSOLE_2020_04_23_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_dummy.h b/examples/chapter12_04/src/mcal_led/mcal_led_dummy.h new file mode 100644 index 000000000..ea451ac5b --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_dummy.h @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2025. +// 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_DUMMY_2025_02_22_H + #define MCAL_LED_DUMMY_2025_02_22_H + + #include + #include + + namespace mcal { namespace led { + + class led_dummy : public mcal::led::led_boolean_state_base + { + public: + led_dummy() noexcept + { + } + + ~led_dummy() override = default; + + auto toggle() noexcept -> void override + { + using base_class_type = mcal::led::led_boolean_state_base; + + base_class_type::toggle(); + } + }; + + } // namespace led + } // namespace mcal + +#endif // MCAL_LED_DUMMY_2025_02_22_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_port.h b/examples/chapter12_04/src/mcal_led/mcal_led_port.h new file mode 100644 index 000000000..4157ec58c --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_port.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2025. +// 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 + + #include + #include + + namespace mcal { namespace led { + + template + class led_port : public mcal::led::led_boolean_state_base + { + public: + led_port() noexcept + { + port_type::set_pin_low(); + port_type::set_direction_output(); + } + + ~led_port() override = default; + + auto toggle() noexcept -> 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_2020_04_23_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_port_inverted.h b/examples/chapter12_04/src/mcal_led/mcal_led_port_inverted.h new file mode 100644 index 000000000..95daaf686 --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_port_inverted.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2025. +// 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() noexcept + { + port_type::set_pin_high(); + port_type::set_direction_output(); + } + + ~led_port_inverted() override = default; + + auto toggle() noexcept -> 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/chapter12_04/src/mcal_led/mcal_led_pwm.h b/examples/chapter12_04/src/mcal_led/mcal_led_pwm.h new file mode 100644 index 000000000..711699092 --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_pwm.h @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2013 - 2025. +// 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 + + namespace mcal { namespace led { + + class led_pwm : public mcal::led::led_base + { + public: + explicit led_pwm(mcal::pwm::pwm_base& pwm) : my_pwm(pwm) + { + my_pwm.set_duty(mcal::pwm::pwm_base::duty_type { UINT8_C(0) }); + } + + ~led_pwm() override = default; + + auto state_is_on() const noexcept -> bool override { return (my_pwm.get_duty() > static_cast(UINT8_C(0))); } + + auto toggle() -> void override + { + // Toggle the duty cycle. + const auto new_duty = + static_cast + ( + state_is_on() ? UINT16_C(0) : UINT16_C(1000) + ); + + my_pwm.set_duty(new_duty); + } + + private: + mcal::pwm::pwm_base& my_pwm; + }; + + } // namespace led + } // namespace mcal + +#endif // MCAL_LED_PWM_2020_04_23_H diff --git a/examples/chapter12_04/src/mcal_led/mcal_led_rgb_base.h b/examples/chapter12_04/src/mcal_led/mcal_led_rgb_base.h new file mode 100644 index 000000000..2c9611773 --- /dev/null +++ b/examples/chapter12_04/src/mcal_led/mcal_led_rgb_base.h @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2017 - 2025. +// 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: + ~led_rgb_base() override = default; + + auto toggle() noexcept -> 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 led + } // namespace mcal + +#endif // MCAL_LED_RGB_BASE_2023_07_12_H diff --git a/examples/chapter12_04/src/mcal_memory/mcal_memory_progmem_array.h b/examples/chapter12_04/src/mcal_memory/mcal_memory_progmem_array.h index be302e2d9..508c2c1c9 100644 --- a/examples/chapter12_04/src/mcal_memory/mcal_memory_progmem_array.h +++ b/examples/chapter12_04/src/mcal_memory/mcal_memory_progmem_array.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2019 - 2020. +// Copyright Christopher Kormanyos 2019 - 2025. // 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) @@ -103,7 +103,7 @@ template bool operator!=(const array& left, const array& right) { - return ((left == right) == false); + return (!(left == right)); } template @@ -115,13 +115,13 @@ template bool operator>=(const array& left, const array& right) { - return ((left < right) == false); + return (!(left < right)); } template bool operator<=(const array& left, const array& right) { - return ((right < left) == false); + return (!(right < left)); } template diff --git a/examples/chapter12_04/src/mcal_pwm/mcal_pwm_base.h b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_base.h new file mode 100644 index 000000000..66f27f3a8 --- /dev/null +++ b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_base.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2025. +// 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 + + #include + + #include + + namespace mcal { namespace pwm { + + class pwm_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + using duty_type = std::uint16_t; + + virtual ~pwm_base() noexcept = default; + + virtual auto init() noexcept -> bool = 0; + + virtual auto set_duty(const duty_type duty_cycle) -> void { my_duty_cycle = duty_cycle; } + + auto get_duty() const noexcept -> duty_type { return my_duty_cycle; } + + protected: + 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 { }; // NOLINT(readability-identifier-naming) + }; + + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_BASE_2020_04_12_H diff --git a/examples/chapter12_04/src/mcal_pwm/mcal_pwm_console.h b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_console.h new file mode 100644 index 000000000..9d19e3dc1 --- /dev/null +++ b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_console.h @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2025. +// 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 + + #include + + #include + #include + #include + + namespace mcal { namespace pwm { + + class pwm_console : public mcal::pwm::pwm_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + private: + using base_class_type = mcal::pwm::pwm_base; + + public: + pwm_console() = default; + + auto init() noexcept -> bool override { return true; } + + auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override + { + base_class_type::set_duty(duty_cycle); + + const auto duty_cycle_as_percent = + static_cast + ( + static_cast(base_class_type::get_duty()) / 10.0F + ); + + std::stringstream strm; + + strm << "duty cycle: " + << std::fixed + << std::setprecision(1) + << duty_cycle_as_percent + << "%"; + + std::cout << strm.str() + (std::string(2U, ' ') + "\r"); + } + + ~pwm_console() override = default; + }; + + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_CONSOLE_2020_04_12_H diff --git a/examples/chapter12_04/src/mcal_pwm/mcal_pwm_dummy.h b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_dummy.h new file mode 100644 index 000000000..2a37fa113 --- /dev/null +++ b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_dummy.h @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2020 - 2025. +// 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 + + #include + + namespace mcal { namespace pwm { + + class pwm_dummy : public mcal::pwm::pwm_base + { + private: + using base_class_type = mcal::pwm::pwm_base; + + public: + pwm_dummy() = default; + + auto init() noexcept -> bool override { return true; } + + auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override + { + base_class_type::set_duty(duty_cycle); + } + + ~pwm_dummy() override = default; + }; + + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_DUMMY_2020_04_29_H diff --git a/examples/chapter12_04/src/mcal_pwm/mcal_pwm_port.h b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_port.h new file mode 100644 index 000000000..7b454062e --- /dev/null +++ b/examples/chapter12_04/src/mcal_pwm/mcal_pwm_port.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. +// 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 + + #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 + 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; + } + + static constexpr auto get_resolution() noexcept -> duty_type { return duty_type { UINT16_C(1000) }; } + + auto set_duty(const duty_type duty_cycle) noexcept -> void override + { + my_duty_shadow = (std::min)(duty_cycle, get_resolution()); + } + + 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/chapter12_04/src/mcal_spi/mcal_spi_software_dummy.h b/examples/chapter12_04/src/mcal_spi/mcal_spi_software_dummy.h new file mode 100644 index 000000000..2deb3e08d --- /dev/null +++ b/examples/chapter12_04/src/mcal_spi/mcal_spi_software_dummy.h @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_SPI_SOFTWARE_DUMMY_2020_04_10_H + #define MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H + + #include + + namespace mcal { namespace spi { + + class spi_software_dummy : public util::communication_buffer_depth_one_byte // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + private: + using base_class_type = util::communication_buffer_depth_one_byte; + + public: + // This class implements a dummy SPI with no real functionality. + + spi_software_dummy() = default; + + ~spi_software_dummy() override = default; + + auto send(const std::uint8_t byte_to_send) noexcept -> bool override + { + static_cast(byte_to_send); + + base_class_type::recv_buffer = 0U; + + return true; + } + + auto select() -> void override { } + auto deselect() -> void override { } + }; + + } // namespace spi + } // namespace mcal + +#endif // MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H diff --git a/examples/chapter12_04/src/mcal_spi/mcal_spi_software_port_driver.h b/examples/chapter12_04/src/mcal_spi/mcal_spi_software_port_driver.h new file mode 100644 index 000000000..74bc0c60f --- /dev/null +++ b/examples/chapter12_04/src/mcal_spi/mcal_spi_software_port_driver.h @@ -0,0 +1,145 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_SPI_SOFTWARE_PORT_DRIVER_2020_04_09_H + #define MCAL_SPI_SOFTWARE_PORT_DRIVER_2020_04_09_H + + #include + #include + #include + + #include + + namespace mcal { namespace spi { + + template + class spi_software_port_driver : public util::communication_buffer_depth_one_byte + { + private: + // Consider: + // https://en.wikipedia.org/wiki/Serial_Peripheral_Interface + + // Timing applies to both the master and the slave device. + + // CPOL=0: + // The clock idles to 0 and each cycle consists + // of a pulse of 1. The leading edge is a rising edge + // and the trailing edge is a falling edge. + + // CPHA=0: + // Data out changes on the trailing edge of the + // preceding clock cycle, while data in is captured + // on (or shortly after) the leading edge of the + // clock cycle. + + using base_class_type = util::communication_buffer_depth_one_byte; + + public: + spi_software_port_driver() + { + port_pin_csn__type::set_pin_high(); + port_pin_sck__type::set_pin_low(); + port_pin_mosi_type::set_pin_low(); + + port_pin_csn__type::set_direction_output(); + port_pin_sck__type::set_direction_output(); + port_pin_mosi_type::set_direction_output(); + port_pin_miso_type::set_direction_input(); + } + + ~spi_software_port_driver() override = default; + + auto send(const std::uint8_t byte_to_send) noexcept -> bool override + { + base_class_type::recv_buffer = 0U; + + for(std::uint_fast8_t bit_mask = UINT8_C(0x80); bit_mask != UINT8_C(0); bit_mask = std::uint_fast8_t(bit_mask >> 1U)) + { + ((std::uint_fast8_t(byte_to_send & bit_mask) != UINT8_C(0)) ? port_pin_mosi_type::set_pin_high() + : port_pin_mosi_type::set_pin_low()); + + mcal::helper::disable_all_interrupts(); + + port_pin_sck__type::set_pin_high(); + mcal::helper::nop_maker(); + + port_pin_sck__type::set_pin_low (); + mcal::helper::nop_maker(); + + if(port_pin_miso_type::read_input_value()) + { + base_class_type::recv_buffer = + base_class_type::buffer_type(base_class_type::recv_buffer | bit_mask); + } + + mcal::helper::enable_all_interrupts(); + } + + return true; + } + + auto select() -> void override { port_pin_csn__type::set_pin_low(); } + auto deselect() -> void override { port_pin_csn__type::set_pin_high(); } + }; + + template + class spi_software_port_driver : public util::communication_buffer_depth_one_byte + { + public: + spi_software_port_driver() + { + port_pin_csn__type::set_pin_high(); + port_pin_sck__type::set_pin_low(); + port_pin_mosi_type::set_pin_low(); + + port_pin_csn__type::set_direction_output(); + port_pin_sck__type::set_direction_output(); + port_pin_mosi_type::set_direction_output(); + } + + ~spi_software_port_driver() override = default; + + auto send(const std::uint8_t byte_to_send) noexcept -> bool override + { + for(std::uint_fast8_t bit_mask = UINT8_C(0x80); + bit_mask != UINT8_C(0); + bit_mask = std::uint_fast8_t(bit_mask >> 1U)) + { + ((std::uint_fast8_t(byte_to_send & bit_mask) != UINT8_C(0)) ? port_pin_mosi_type::set_pin_high() + : port_pin_mosi_type::set_pin_low()); + + mcal::helper::disable_all_interrupts(); + + port_pin_sck__type::set_pin_high(); + port_pin_sck__type::set_pin_low(); + + mcal::helper::enable_all_interrupts(); + } + + return true; + } + + auto select() -> void override { port_pin_csn__type::set_pin_low(); } + auto deselect() -> void override { port_pin_csn__type::set_pin_high(); } + }; + + } // namespace spi + } // namespace mcal + +#endif // MCAL_SPI_SOFTWARE_PORT_DRIVER_2020_04_09_H diff --git a/examples/chapter12_04/src/os/os.cpp b/examples/chapter12_04/src/os/os.cpp index 5578dc732..a1bd651a5 100644 --- a/examples/chapter12_04/src/os/os.cpp +++ b/examples/chapter12_04/src/os/os.cpp @@ -1,35 +1,44 @@ -/////////////////////////////////////////////////////////////////////////////// -// 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) // -#include -#include -#include #include #include #include -namespace +#include +#include + +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); + auto os_task_list() -> task_list_type&; // 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 + +// The one (and only one) operating system task list. +auto local::os_task_list() -> local::task_list_type& +{ + static task_list_type my_task_list(OS_TASK_LIST); + + return my_task_list; } -void os::start_os() +OS_NORETURN auto os::start_os() -> void { + auto& task_list = local::os_task_list(); + // 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(task_list.cbegin(), + task_list.cend(), [](const task_control_block& the_tcb) { the_tcb.initialize(); @@ -51,36 +60,40 @@ 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(task_list.begin(), + 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 == 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 { }; + + auto& task_list = local::os_task_list(); + + 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 = ( 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 +102,20 @@ 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 { + const auto& task_list = local::os_task_list(); + // 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 = (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 != task_list.cend()) { // Get the event of the running task. mcal::irq::disable_all(); @@ -115,23 +128,25 @@ 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 { + auto& task_list = local::os_task_list(); + // 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 = (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 != 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/chapter12_04/src/os/os.h b/examples/chapter12_04/src/os/os.h index fdd9ef67f..8adc64573 100644 --- a/examples/chapter12_04/src/os/os.h +++ b/examples/chapter12_04/src/os/os.h @@ -1,24 +1,31 @@ /////////////////////////////////////////////////////////////////////////////// -// 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_2011_10_20_H_ - #define OS_2011_10_20_H_ +#ifndef OS_2011_10_20_H + #define OS_2011_10_20_H - #include - #include #include #include + #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; + } // namespace os -#endif // OS_2011_10_20_H_ +#endif // OS_2011_10_20_H diff --git a/examples/chapter12_04/src/os/os_cfg.h b/examples/chapter12_04/src/os/os_cfg.h index 38241021f..353e74efd 100644 --- a/examples/chapter12_04/src/os/os_cfg.h +++ b/examples/chapter12_04/src/os/os_cfg.h @@ -1,73 +1,91 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +// Copyright Christopher Kormanyos 2007 - 2025. // 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 #include #include - #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; + + } // namespace idle + } // namespace sys // 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 sys { namespace mon { void task_init(); void task_func(); } } + namespace app { namespace led { + + auto task_init() -> void; auto task_func() -> void; + + } // namespace led + } // namespace app + + namespace app { namespace benchmark { + + auto task_init() -> void; auto task_func() -> void; + + } // namespace benchmark + } // namespace app + + namespace sys { namespace mon { + + auto task_init() -> void; auto task_func() -> void; + + } // namespace mon + } // namespace sys 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 // NOLINT(performance-enum-size) { task_id_app_led, task_id_app_benchmark, task_id_sys_mon, 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, + static_assert(std::numeric_limits::digits >= static_cast(INT8_C(32)), "The operating system timer_type must be at least 32-bits wide."); - static_assert(std::numeric_limits::digits >= 16, + static_assert(std::numeric_limits::digits >= static_cast(INT8_C(16)), "The operating system event_type must be at least 16-bits wide."); - } + } // namespace os // Configure the operating system tasks. // Use small prime numbers (representing microseconds) for task offsets. - // Use Wolfram's Alpha or Mathematica(R): Table[Prime[n], {n, 50, 4000, 50}] + // Use Wolfram's Alpha or Mathematica(R): Table[Prime[n], {n, 25, 1000, 25}] // to obtain: - // 229, 541, 863, 1223, 1583, 1987, 2357, 2741, 3181, 3571, - // 3989, 4409, 4831, 5279, 5693, 6133, 6571, 6997, 7499, 7919, - // 8387, 8831, 9283, 9733, 10177, 10657, 11149, 11657, 12109, 12553, - // 13007, 13499, 13967, 14519, 14947, 15401, 15881, 16381, 16903, 17389, - // 17891, 18313, 18899, 19423, 19891, 20357, 20897, 21383, 21841, 22307, - // 22817, 23321, 23827, 24281, 24877, 25391, 25913, 26399, 26891, 27449, - // 27947, 28499, 28933, 29443, 30059, 30559, 31091, 31601, 32159, 32609, - // 33113, 33613, 34157, 34649, 35159, 35759, 36277, 36781, 37309, 37813 + // 97, 229, 379, 541, 691, 863, 1039, 1223, 1427, 1583, 1777, + // 1987, 2153, 2357, 2557, 2741, 2953, 3181, 3371, 3571, 3769, 3989, + // 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) + constexpr auto OS_TASK_COUNT = static_cast(os::task_id_type::task_id_end); #define OS_TASK_LIST \ { \ @@ -87,6 +105,6 @@ } \ } - 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/chapter12_04/src/os/os_task_control_block.cpp b/examples/chapter12_04/src/os/os_task_control_block.cpp deleted file mode 100644 index 216068567..000000000 --- a/examples/chapter12_04/src/os/os_task_control_block.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. -// 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 - -bool os::task_control_block::execute(const os::tick_type& timepoint_of_ckeck_ready) -{ - // Check for a task event. - const bool task_does_have_event = (my_event != event_type(0U)); - - if(task_does_have_event) - { - // Call the task function because of an event. - my_func(); - } - - // Check for a task timeout. - const bool task_does_have_timeout = ( (my_cycle != os::tick_type(0U)) - && my_timer.timeout_of_specific_timepoint(timepoint_of_ckeck_ready)); - - if(task_does_have_timeout) - { - // Increment the task's interval timer with the task cycle. - my_timer.start_interval(my_cycle); - - // Call the task function because of a timer timeout. - my_func(); - } - - return (task_does_have_event || task_does_have_timeout); -} - diff --git a/examples/chapter12_04/src/os/os_task_control_block.h b/examples/chapter12_04/src/os/os_task_control_block.h index 89f5530fa..d0a60bd2b 100644 --- a/examples/chapter12_04/src/os/os_task_control_block.h +++ b/examples/chapter12_04/src/os/os_task_control_block.h @@ -1,59 +1,85 @@ -/////////////////////////////////////////////////////////////////////////////// -// 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_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 #include #include - #include namespace os { class task_control_block final { public: - 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() { } - - 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() { } + task_control_block(const function_type init, // NOLINT(bugprone-easily-swappable-parameters) + const function_type func, // NOLINT(bugprone-easily-swappable-parameters) + const tick_type cycle, // NOLINT(bugprone-easily-swappable-parameters) + const tick_type offset) // NOLINT(bugprone-easily-swappable-parameters) + : my_init { init }, + my_func { func }, + my_cycle { cycle }, + my_timer { offset } { } + + task_control_block(const task_control_block& other_tcb) = default; + + task_control_block(task_control_block&& other_tcb) noexcept = default; + + 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; + const function_type my_init; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + const function_type my_func; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + const tick_type my_cycle; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) timer_type my_timer; - event_type my_event; + event_type my_event { }; + + auto initialize() const -> void { my_init(); } + + auto execute(const tick_type& timepoint_of_ckeck_ready) -> bool + { + // Check for a task event. + const auto task_does_have_event = (my_event != static_cast(UINT8_C(0))); + + if(task_does_have_event) + { + // Call the task function because of an event. + my_func(); + } + + // Check for a task timeout. + const bool task_does_have_timeout = ( (my_cycle != static_cast(UINT8_C(0))) + && my_timer.timeout_of_specific_timepoint(timepoint_of_ckeck_ready)); - void initialize() const { my_init(); } + if(task_does_have_timeout) + { + // Increment the task's interval timer with the task cycle. + my_timer.start_interval(my_cycle); - bool execute(const tick_type& timepoint_of_ckeck_ready); + // Call the task function because of a timer timeout. + my_func(); + } - task_control_block(); - task_control_block& operator=(const task_control_block&); + return (task_does_have_event || task_does_have_timeout); + } - 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; }; - } + } // namespace os -#endif // OS_TASK_CONTROL_BLOCK_2013_07_30_H_ +#endif // OS_TASK_CONTROL_BLOCK_2013_07_30_H diff --git a/examples/chapter12_04/src/sys/idle/sys_idle.cpp b/examples/chapter12_04/src/sys/idle/sys_idle.cpp index dd7bc5d36..a8b049f30 100644 --- a/examples/chapter12_04/src/sys/idle/sys_idle.cpp +++ b/examples/chapter12_04/src/sys/idle/sys_idle.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,18 +7,17 @@ #include -namespace sys -{ - namespace idle - { - void task_init(); - void task_func(); - } -} +namespace sys { namespace idle { + +auto task_init() -> void; +auto task_func() -> void; + +} // namespace idle +} // namespace sys -void sys::idle::task_init() { } +auto sys::idle::task_init() -> void { } -void sys::idle::task_func() +auto sys::idle::task_func() -> void { // Service the watchdog. mcal::wdg::secure::trigger(); diff --git a/examples/chapter12_04/src/sys/mon/sys_mon.cpp b/examples/chapter12_04/src/sys/mon/sys_mon.cpp index 2e50c95e9..6b03045e1 100644 --- a/examples/chapter12_04/src/sys/mon/sys_mon.cpp +++ b/examples/chapter12_04/src/sys/mon/sys_mon.cpp @@ -1,24 +1,25 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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) // -namespace sys -{ - namespace mon - { - void task_init(); - void task_func(); - } -} +namespace sys { namespace mon { + +auto task_init() -> void; +auto task_func() -> void; + +} // namespace mon +} // namespace sys -void sys::mon::task_init() +auto sys::mon::task_init() -> void { + // Subroutine is empty on purpose. } -void sys::mon::task_func() +auto sys::mon::task_func() -> void { + // Subroutine is empty on purpose. } diff --git a/examples/chapter12_04/src/sys/start/sys_start.cpp b/examples/chapter12_04/src/sys/start/sys_start.cpp index c7e0b0ea9..8a0744365 100644 --- a/examples/chapter12_04/src/sys/start/sys_start.cpp +++ b/examples/chapter12_04/src/sys/start/sys_start.cpp @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. // 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,11 +8,28 @@ #include #include -extern "C" int main() +#include + +#if (defined(__XTENSA__) && !defined(CONFIG_IDF_TARGET_ESP32S3)) +extern "C" auto app_main_loop() -> int ATTRIBUTE(used); +#else +ATTRIBUTE(used) auto main() -> int; +#endif + +#if (defined(__XTENSA__) && !defined(CONFIG_IDF_TARGET_ESP32S3)) +auto app_main_loop() -> int +#else +auto main() -> int +#endif { // Initialize the microcontroller abstraction layer. mcal::init(); - // Start the multitasking scheduler, and never return. + // Start the multitasking scheduler. This does not return. + // Handle an unexpected return from main() in the startup code. os::start_os(); + + #if (defined(__XTENSA__) && !defined(CONFIG_IDF_TARGET_ESP32S3)) + return 0; + #endif } diff --git a/examples/chapter12_04/src/util/STL/algorithm b/examples/chapter12_04/src/util/STL/algorithm index dac149edc..b00919672 100644 --- a/examples/chapter12_04/src/util/STL/algorithm +++ b/examples/chapter12_04/src/util/STL/algorithm @@ -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) @@ -8,6 +8,7 @@ #ifndef ALGORITHM_2010_02_23_ #define ALGORITHM_2010_02_23_ + #include #include #include #include @@ -18,32 +19,35 @@ 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; - if(first == last) - { - } - else + if(first != last) { ++first; @@ -61,16 +65,13 @@ 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; - if(first == last) - { - } - else + if(first != last) { ++first; @@ -87,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(), @@ -103,30 +104,27 @@ } 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; - if(first == last) - { - } - else + if(first != last) { ++first; @@ -144,16 +142,13 @@ 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; - if(first == last) - { - } - else + if(first != last) { ++first; @@ -170,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(), @@ -205,44 +200,64 @@ : std::pair(a, b)); } - template + template bool lexicographical_compare(input_iterator1 first1, input_iterator1 last1, input_iterator2 first2, input_iterator2 last2) { - while(first1 != last1) + for( ; (first1 != last1) && (first2 != last2); static_cast(++first1), static_cast(++first2)) { - if((first2 == last2) || (*first2 < *first1)) - { - return false; - } - else if(*first1 < *first2) + if(*first1 < *first2) { return true; } - ++first1; - ++first2; + if(*first2 < *first1) + { + return false; + } } - return (first2 != last2); + return ((first1 == last1) && (first2 != last2)); } 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) { - *result = *first; + using result_value_type = typename std::iterator_traits::value_type; + + *result = result_value_type(*first); } return result; } + template + STL_LOCAL_CONSTEXPR_ALGORITHMS bidirectional_output_iterator2 copy_backward(bidirectional_input__iterator1 first1, + bidirectional_input__iterator1 last1, + bidirectional_output_iterator2 last2) + { + while (first1 != last1) + { + using out2_value_type = typename std::iterator_traits::value_type; + + --last1; + --last2; + + *last2 = out2_value_type(*last1); + } + + return last2; + } + template @@ -255,7 +270,9 @@ { if(unary_function(*first)) { - *result = *first; + using output_value_type = typename std::iterator_traits::value_type; + + *result = output_value_type(*first); ++result; } @@ -268,22 +285,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) { for( ; first != last; ++first) { - *first = value; + using forward_value_type = typename std::iterator_traits::value_type; + + *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); @@ -300,7 +319,9 @@ { while(first != last) { - *first = generator(); + using forward_value_type = typename std::iterator_traits::value_type; + + *first = forward_value_type(generator()); ++first; } @@ -315,7 +336,9 @@ { for(size_type i = size_type(0); i < count; ++i) { - *first = generator(); + using output_value_type = typename std::iterator_traits::value_type; + + *first = output_value_type(generator()); ++first; } @@ -324,24 +347,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); } } @@ -355,7 +365,9 @@ { for( ; first != last; ++first, ++result) { - *result = unary_function(*first); + using output_value_type = typename std::iterator_traits::value_type; + + *result = output_value_type(unary_function(*first)); } return result; @@ -373,7 +385,9 @@ { for( ; first1 != last1; ++first1, ++first2, ++result) { - *result = binary_function(*first1, *first2); + using output_value_type = typename std::iterator_traits::value_type; + + *result = output_value_type(binary_function(*first1, *first2)); } return result; @@ -409,7 +423,7 @@ { while(first1 != last1) { - if(binary_function(*first1, *first2) == false) + if(!binary_function(*first1, *first2)) { break; } @@ -423,9 +437,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)) { @@ -441,7 +455,7 @@ iterator_type last, unary_function_type unary_function) { - while((first != last) && (unary_function(*first) == false)) + while((first != last) && (!unary_function(*first))) { ++first; } @@ -455,7 +469,7 @@ iterator_type last, unary_function_type unary_function) { - while((first != last) && (unary_function(*first) == false)) + while((first != last) && (!unary_function(*first))) { ++first; } @@ -546,6 +560,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 @@ -570,6 +597,93 @@ return count_value; } + template + forward_iterator lower_bound(forward_iterator first, + forward_iterator last, + const value_type& value) + { + typename std::iterator_traits::difference_type count = std::distance(first, last); + typename std::iterator_traits::difference_type step; + + while(count > 0) + { + forward_iterator it = first; + + step = count / 2; + std::advance(it, step); + + if(*it < value) + { + first = ++it; + count -= step + 1; + } + else + { + count = step; + } + } + + return first; + } + + template + forward_iterator lower_bound(forward_iterator first, + forward_iterator last, + const value_type& value, + binary_function_type binary_function) + { + typename std::iterator_traits::difference_type step; + + typename std::iterator_traits::difference_type count = + std::distance(first,last); + + while(count > 0) + { + forward_iterator it = first; + step = count / 2; + std::advance(it, step); + + if(binary_function(*it, value)) + { + first = ++it; + count -= step + 1; + } + else + { + count = step; + } + } + + return first; + } + + template + bool binary_search(forward_iterator first, + forward_iterator last, + const value_type& value) + { + first = std::lower_bound(first, last, value); + + return (!(first == last) && !(value < *first)); + } + + template + bool binary_search(forward_iterator first, + forward_iterator last, + const value_type& value, + binary_function_type binary_function) + { + first = std::lower_bound(first, last, value, binary_function); + + return (!(first == last) && !(binary_function(value, *first))); + } + template @@ -653,8 +767,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) { @@ -665,25 +779,35 @@ } } + 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 left_type; - typedef typename std::iterator_traits::value_type right_type; + typedef typename std::iterator_traits::value_type value_left_type; + typedef typename std::iterator_traits::value_type value_right_type; - const left_type tmp(*left); + const value_left_type tmp(*left); - *left = left_type (*right); - *right = right_type(tmp); + *left = value_left_type (*right); + *right = value_right_type(tmp); } 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) { @@ -698,8 +822,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]); } @@ -712,7 +836,7 @@ { for( ; ; ++first) { - for( ; (first != last) && (unary_function(*first) == true); ++first) + for( ; (first != last) && unary_function(*first); ++first) { ; } @@ -722,7 +846,7 @@ break; } - for( ; (first != --last) && (unary_function(*last) == false); ) + for( ; (first != --last) && (!unary_function(*last)); ) { ; } diff --git a/examples/chapter12_04/src/util/STL/array b/examples/chapter12_04/src/util/STL/array index 65e9fa350..334327a5f 100644 --- a/examples/chapter12_04/src/util/STL/array +++ b/examples/chapter12_04/src/util/STL/array @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2012 - 2019. // 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,11 +8,8 @@ #ifndef ARRAY_2010_02_23_ #define ARRAY_2010_02_23_ - #if defined(__GNUC__) - #pragma GCC system_header - #endif - #include + #include #include #include @@ -23,92 +20,93 @@ 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 iterator begin() { return elems; } + STL_LOCAL_CONSTEXPR iterator end () { return elems + N; } - const_iterator begin() const { return elems; } - const_iterator end () const { return elems + N; } + STL_LOCAL_CONSTEXPR const_iterator begin() const { return elems; } + STL_LOCAL_CONSTEXPR const_iterator end () const { return elems + N; } - const_iterator cbegin() const { return elems; } - const_iterator cend () const { return elems + N; } + 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 reverse_iterator rbegin() { return reverse_iterator(elems + N); } + STL_LOCAL_CONSTEXPR reverse_iterator rend () { return reverse_iterator(elems); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(elems + N); } - const_reverse_iterator rend () const { return const_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); } - const_reverse_iterator crbegin() const { return const_reverse_iterator(elems + N); } - const_reverse_iterator crend () const { return const_reverse_iterator(elems); } + 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]; } - const_reference operator[](const size_type i) const { return elems[i]; } + STL_LOCAL_CONSTEXPR 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]; } - const_reference at(const size_type i) const { return elems[i]; } + STL_LOCAL_CONSTEXPR 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]; } - const_reference front() const { return elems[0U]; } + STL_LOCAL_CONSTEXPR reference front() { return elems[0U]; } + STL_LOCAL_CONSTEXPR const_reference front() const { return elems[0U]; } - reference back() { return elems[N - 1U]; } - const_reference back() const { return elems[N - 1U]; } + STL_LOCAL_CONSTEXPR reference back() { return elems[N - 1U]; } + STL_LOCAL_CONSTEXPR const_reference back() const { return elems[N - 1U]; } - static size_type size() { return N; } - static bool empty() { return false; } - static size_type max_size() { return N; } + 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 void swap(array& y) { std::swap_ranges(begin(), end(), y.begin()); } - const_pointer data() const { return elems; } - pointer data() { return elems; } + STL_LOCAL_CONSTEXPR const_pointer data() const { return elems; } + STL_LOCAL_CONSTEXPR pointer data() { return elems; } pointer c_array() { return elems; } template - array& operator=(const array& y) + STL_LOCAL_CONSTEXPR array& operator=(const array& y) { std::copy(y.begin(), y.end(), begin()); + return *this; } - void assign(const value_type& value) + STL_LOCAL_CONSTEXPR void assign(const value_type& value) { std::fill_n(elems, N, value); } - void fill(const value_type& value) + STL_LOCAL_CONSTEXPR void fill(const value_type& value) { std::fill_n(elems, N, value); } }; template - bool operator==(const array& left, const array& right) + STL_LOCAL_CONSTEXPR bool operator==(const array& left, const array& right) { return std::equal(left.begin(), left.end(), right.begin()); } @@ -123,31 +121,31 @@ } template - bool operator!=(const array& left, const array& right) + STL_LOCAL_CONSTEXPR bool operator!=(const array& left, const array& right) { - return ((left == right) == false); + return (!(left == right)); } template - bool operator>(const array& left, const array& right) + STL_LOCAL_CONSTEXPR bool operator>(const array& left, const array& right) { return (right < left); } template - bool operator>=(const array& left, const array& right) + STL_LOCAL_CONSTEXPR bool operator>=(const array& left, const array& right) { - return ((left < right) == false); + return (!(left < right)); } template - bool operator<=(const array& left, const array& right) + STL_LOCAL_CONSTEXPR bool operator<=(const array& left, const array& right) { - return ((right < left) == false); + return (!(right < left)); } template - void swap(array& x, array& y) + STL_LOCAL_CONSTEXPR void swap(array& x, array& y) { swap_ranges(x.begin(), x.end(), y.begin()); } diff --git a/examples/chapter12_04/src/util/STL/bitset b/examples/chapter12_04/src/util/STL/bitset new file mode 100644 index 000000000..b4b001ffa --- /dev/null +++ b/examples/chapter12_04/src/util/STL/bitset @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2018. +// 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 BITSET_2018_06_10_ + #define BITSET_2018_06_10_ + + #include + #include + #include + #include + #include + + #include + + namespace std + { + template + class bitset + { + public: + using element_type = bool; + + STL_LOCAL_CONSTEXPR bitset() : my_memory() + { + std::fill(my_memory, my_memory + my_elem_count, 0U); + } + + STL_LOCAL_CONSTEXPR bitset(unsigned long long val) : my_memory() + { + std::fill(my_memory, my_memory + my_elem_count, 0U); + + for(std::uint_fast8_t i = 0U; i < (std::min)(my_bit_count, std::size_t(std::numeric_limits::digits)); ++i) + { + if((val & 1U) != 0U) + { + set(i); + } + + val >>= 1; + } + } + + template + explicit bitset(const std::basic_string& str, + typename std::basic_string::size_type pos = 0U, + typename std::basic_string::size_type n = + std::basic_string::npos, + T zero = T('0'), + T one = T('1')) + { + } + + template + explicit bitset(const T* str, + typename std::basic_string::size_type n = std::basic_string::npos, + T zero = T('0'), + T one = T('1')) + { + } + + ~bitset() = default; + + void set() + { + if(my_elem_count > 0U) + { + std::size_t i; + + for(i = 0U; i < my_elem_count - 1U; ++i) + { + my_memory[i] = UINT8_C(0xFF); + } + + std::uint_fast8_t mask = 1U; + + for(std::uint_fast8_t j = 0U; j < (my_elem_count % 8U); ++j) + { + my_memory[i] |= std::uint8_t(mask); + + mask <<= 1; + } + } + } + + bitset& set(size_t pos, bool value = true) + { + if(value) + { + my_memory[i / 8U] |= (UINT8_C(1) << (i % 8U)); + } + else + { + my_memory[i / 8U] &= std::uint8_t(~(UINT8_C(1) << (i % 8U))); + } + + return *this; + } + + void flip(const std::size_t i) + { + my_memory[i / 8U] ^= (UINT8_C(1) << (i % 8U)); + } + + private: + static const std::size_t my_elem_count = (my_bit_count / 8U) + (((my_bit_count % 8U) != 0U) ? 1U : 0U); + + std::uint8_t my_memory[my_elem_count]; + }; + } + +#endif // BITSET_2018_06_10_ diff --git a/examples/chapter12_04/src/util/STL/cassert b/examples/chapter12_04/src/util/STL/cassert new file mode 100644 index 000000000..a31576237 --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/STL/cerrno b/examples/chapter12_04/src/util/STL/cerrno new file mode 100644 index 000000000..a20898ca3 --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/STL/charconv b/examples/chapter12_04/src/util/STL/charconv new file mode 100644 index 000000000..1cb80c4ec --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/STL/chrono b/examples/chapter12_04/src/util/STL/chrono index 17029742e..0b047620a 100644 --- a/examples/chapter12_04/src/util/STL/chrono +++ b/examples/chapter12_04/src/util/STL/chrono @@ -1,5 +1,12 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2011 - 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) +// + /////////////////////////////////////////////////////////////////////////////// -/// \author (c) Marco Paland (info@paland.com) +/// \author (c) Marco Paland (info (AT) paland.com) /// 2011-2012, PALANDesign Hannover, Germany /// /// \license LGPLv3 @@ -15,15 +22,15 @@ /// along with chrono. If not, see . /// /// -/// \brief implementation of C++11 on Windows(tm) +/// \brief implementation of C++11 chronological classes /// -/// This class implements the class of C++11 for compilers -/// which do not support this standard. -/// Needs , and standard , headers +/// This class implements the classes of C++11 for compilers +/// which do not yet support this standard. +/// Needs , and standard , headers. /// -/// To adapt to you own system you need to write your own +/// To adapt to your own system you need to write your own /// xxx_clock::now() functions and define your clock accuracy in CLOCKS section. -/// This is the only part which is OS dependent! +/// This is the only part which is dependent on hardware of the OS! /// This way you can easily adapt to your target system /// /// \todo - add more specializations of missing common_types for duration arithmetic @@ -69,7 +76,7 @@ }; // TBD: Add more specializations of common_type here - // common_type is in namespace std::chrono cause its usage is private here + // common_type is in namespace std::chrono because its usage is private here template struct common_type { typedef Tp type; }; // default return is 1. param (Tp) if no specialization is found @@ -99,7 +106,6 @@ struct common_type { typedef int64_t type; }; - // specialization of common_type (for duration) template struct common_type, chrono::duration > @@ -133,7 +139,7 @@ duration() : rep_() { } - ~duration() { } + ~duration() = default; template explicit duration(const Rep2& r) @@ -278,7 +284,6 @@ return _ct(lhs) %= rhs; } - // comparisons template inline bool operator==(const duration& lhs, @@ -318,7 +323,7 @@ inline bool operator>(const duration& lhs, const duration& rhs) { - return rhs < lhs; + return (rhs < lhs); } template @@ -392,13 +397,13 @@ typedef duration milliseconds; // seconds - typedef duration > seconds; + typedef duration> seconds; // minutes - typedef duration > minutes; + typedef duration> minutes; // hours - typedef duration > hours; + typedef duration> hours; ////////////////////////////////////////////////////////////////////////// @@ -426,6 +431,8 @@ : d_(t.time_since_epoch()) { } + ~time_point() = default; + // observer duration time_since_epoch() const { return d_; } @@ -525,7 +532,7 @@ inline bool operator>(const time_point& lhs, const time_point& rhs) { - return rhs < lhs; + return (rhs < lhs); } template @@ -538,7 +545,7 @@ ////////////////////////////////////////////////////////////////////////// - // C L O C K S + // The CLOCKS Section // class system_clock @@ -568,7 +575,7 @@ static const bool is_steady = false; // !!! PLATFORM AND OS SPECIFIC IMPLEMENTATION !!! - static time_point now() STL_LOCAL_NOEXCEPT; + static time_point now() noexcept; }; @@ -598,7 +605,7 @@ static const bool is_steady = true; // !!! PLATFORM AND OS SPECIFIC IMPLEMENTATION !!! - static time_point now() STL_LOCAL_NOEXCEPT; + static time_point now() noexcept; }; @@ -606,6 +613,13 @@ typedef high_resolution_clock steady_clock; } // namespace chrono + ////////////////////////////////////////////////////////////////////////// + // The String Literals Section + // + + #if defined(__GNUC__) && (__GNUC__ < 5) + #else + namespace literals { namespace chrono_literals @@ -642,6 +656,8 @@ using std::literals::chrono_literals::operator""min; using std::literals::chrono_literals::operator""h; } + + #endif // __GNUC__ >= 5 } // namespace std #endif // CHRONO_2012_06_01_ diff --git a/examples/chapter12_04/src/util/STL/cinttypes b/examples/chapter12_04/src/util/STL/cinttypes new file mode 100644 index 000000000..168731795 --- /dev/null +++ b/examples/chapter12_04/src/util/STL/cinttypes @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2021 - 2025. +// 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_ + + #if (defined(__GNUC__) && (defined(__RL78__) || defined(__v850__))) + #include + #else + #include + #endif + #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/chapter12_04/src/util/STL/ciso646 b/examples/chapter12_04/src/util/STL/ciso646 new file mode 100644 index 000000000..9d7087bec --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/STL/cmath b/examples/chapter12_04/src/util/STL/cmath index 538ca7a2e..c8debf968 100644 --- a/examples/chapter12_04/src/util/STL/cmath +++ b/examples/chapter12_04/src/util/STL/cmath @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. // 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,245 +8,830 @@ #ifndef CMATH_2010_02_23_ #define CMATH_2010_02_23_ + #include + #include + // Implement most of for compilers that do not yet support it. - #include + #if (defined(__GNUC__) && defined(__AVR__)) + + #include + + #if !defined(_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 + + #if !defined(HUGE_VAL) + #define HUGE_VAL ((double)INFINITY) + #endif + + #if !defined(HUGE_VALF) + #define HUGE_VALF ((float)INFINITY) + #endif + + #if !defined(HUGE_VALL) + #define HUGE_VALL ((long double)INFINITY) + #endif + + #if !defined(NAN) + #define NAN (-(float)(INFINITY * 0.0F)) + #endif + + #if !defined(FP_NAN) + #define FP_NAN 0 + #endif + #if !defined(FP_INFINITE) + #define FP_INFINITE 1 + #endif + #if !defined(FP_ZERO) + #define FP_ZERO 2 + #endif + #if !defined(FP_SUBNORMAL) + #define FP_SUBNORMAL 3 + #endif + #if !defined(FP_NORMAL) + #define FP_NORMAL 4 + #endif + + #define _C2 1L // 0 if not 2's complement + #define FP_ILOGB0 (-0x7fffffffL - _C2) + #define FP_ILOGBNAN 0x7fffffffL + + static_assert((__SIZEOF_LONG_DOUBLE__ > 0) && (__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_ISINFF __builtin_isinf + #define __BUILTIN_ISINF __builtin_isinf + #define __BUILTIN_ISINFL __builtin_isinfl + #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_ISINFF __builtin_isinff + #define __BUILTIN_ISINF __builtin_isinfl + #define __BUILTIN_ISINFL __builtin_isinfl + #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 + + #if defined(__cplusplus) + extern "C" + { + #endif + 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); + int ilogbf(float x); + int ilogb (double x); + int ilogbl(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); + #if defined(__cplusplus) + } + #endif + + namespace std + { + using float_t = float; + using double_t = double; + + 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 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); } + + namespace cmath_detail { + + __attribute__((always_inline)) static inline bool isinf_impl(float x) { return (__BUILTIN_ISINFF(x) == 1); } + __attribute__((always_inline)) static inline bool isinf_impl(double x) { return (__BUILTIN_ISINF (x) == 1); } + __attribute__((always_inline)) static inline bool isinf_impl(long double x) { return (__BUILTIN_ISINFL(x) == 1); } + + } // namespace cmath_detail + + inline bool isinf(float x) { return ::std::cmath_detail::isinf_impl(x); } + inline bool isinf(double x) { return ::std::cmath_detail::isinf_impl(x); } + inline bool isinf(long double x) { return ::std::cmath_detail::isinf_impl(x); } + + namespace cmath_detail { + + template + inline int fpclassify_impl(FloatType x) + { + #if defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #endif + + using float_type = FloatType; + + if((::std::isnan)(x)) + { + return FP_NAN; + } + else if((::std::isinf)(x)) + { + return FP_INFINITE; + } + else if((::std::fabs)(x) == static_cast(0.0L)) + { + return FP_ZERO; + } + else + { + const bool + is_subnormal + { + ( + ((::std::fabs)(x) > static_cast(0.0L)) + && ((::std::fabs)(x) < (std::numeric_limits::min)()) + ) + }; + + return (is_subnormal ? FP_SUBNORMAL : FP_NORMAL); + } + + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif + } + + } // namespace cmath_detail + + inline bool isfinite(float x) { return ((!(::std::isinf)(x)) && (!(::std::isnan)(x))); } + inline bool isfinite(double x) { return ((!(::std::isinf)(x)) && (!(::std::isnan)(x))); } + inline bool isfinite(long double x) { return ((!(::std::isinf)(x)) && (!(::std::isnan)(x))); } + + inline int fpclassify(float x) { return ::std::cmath_detail::fpclassify_impl(x); } + inline int fpclassify(double x) { return ::std::cmath_detail::fpclassify_impl(x); } + inline int fpclassify(long double x) { return ::std::cmath_detail::fpclassify_impl(x); } + + 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 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 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); } + 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); } + } - #if defined(__GNUC__) + #else - namespace std + #if defined(__cplusplus) + extern "C" + { + #endif + // These are (most of) the functions from having C-linkage. + int isinff (float); + int isinfl (long double); + int isnanf (float); + int isnanl (long double); + 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 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__) && !defined(__clang__)) + 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 bool isinf (float x) { return (::isnanf)(x); } + bool isinf (double x); + inline bool isinf (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 bool isfinite (float x) { return ((!(::isinff)(x)) && (!(::isnanf)(x))); } + extern "C" bool isfinite (double x); + inline bool isfinite (long double x) { return ((!(::isinfl)(x)) && (!(::isnanl)(x))); } + 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 (defined(__cplusplus) && (__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 + + #if !defined(FP_NAN) + #define FP_NAN 0 + #endif + #if !defined(FP_INFINITE) + #define FP_INFINITE 1 + #endif + #if !defined(FP_ZERO) + #define FP_ZERO 2 + #endif + #if !defined(FP_SUBNORMAL) + #define FP_SUBNORMAL 3 + #endif + #if !defined(FP_NORMAL) + #define FP_NORMAL 4 + #endif + + namespace std + { + using float_t = float; + using double_t = double; + + using ::isfinite; + using ::ilogb; + + namespace cmath_detail { + + template + inline bool isinf_impl(FloatType x) { - #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 - - float tgamma(float); - - 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 + #if defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #endif + + using float_type = FloatType; + + return + ( + ( x == std::numeric_limits::infinity()) + || (-x == std::numeric_limits::infinity()) + ); + + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif + } - #else + } // namespace cmath_detail + + inline bool isinf(float x) { return ::std::cmath_detail::isinf_impl(x); } + inline bool isinf(double x) { return ::std::cmath_detail::isinf_impl(x); } + inline bool isinf(long double x) { return ::std::cmath_detail::isinf_impl(x); } - #include + using ::isnan; + using ::abs; + using ::fabs; + using ::fmod; - namespace std + namespace cmath_detail { + + template + inline int fpclassify_impl(FloatType x) { - 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; + #if defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #endif + + using float_type = FloatType; + + if((::std::isnan)(x)) + { + return FP_NAN; + } + else if((::std::isinf)(x)) + { + return FP_INFINITE; + } + else if((::std::fabs)(x) == static_cast(0.0L)) + { + return FP_ZERO; + } + else + { + const bool + is_subnormal + { + ( + ((::std::fabs)(x) > static_cast(0.0L)) + && ((::std::fabs)(x) < (std::numeric_limits::min)()) + ) + }; + + return (is_subnormal ? FP_SUBNORMAL : FP_NORMAL); + } + + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif } - #endif // __GNUC__ or not __GNUC__ stuff - - // Provide certain functions that are often missing from . - // Here, we patch some of these in an exemplary fashion for the - // proposed std::float32_t. - std::float32_t asinh (std::float32_t x); - std::float32_t acosh (std::float32_t x); - std::float32_t atanh (std::float32_t x); - std::float32_t tgamma(std::float32_t x); + } // namespace cmath_detail + + inline int fpclassify(float x) { return ::std::cmath_detail::fpclassify_impl(x); } + inline int fpclassify(double x) { return ::std::cmath_detail::fpclassify_impl(x); } + inline int fpclassify(long double x) { return ::std::cmath_detail::fpclassify_impl(x); } + + 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/chapter12_04/src/util/STL/complex b/examples/chapter12_04/src/util/STL/complex index 7c7233713..7d6117896 100644 --- a/examples/chapter12_04/src/util/STL/complex +++ b/examples/chapter12_04/src/util/STL/complex @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +/////////////////////////////////////////////////////////////////////////////// +// 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) @@ -7,18 +7,17 @@ // Implement templates for the standard complex class and // its associated functions. These are intended to be used -// with both user-defined types as well as built-in float, -// double and long double. +// with the built-in types float, double and long double. #ifndef COMPLEX_2012_02_20_ #define COMPLEX_2012_02_20_ #if !defined(STD_COMPLEX_DISABLE_IOSTREAM) - #define STD_COMPLEX_DISABLE_IOSTREAM + #define STD_COMPLEX_DISABLE_IOSTREAM #endif #if defined(__GNUC__) - #pragma GCC system_header + #pragma GCC system_header #endif #include @@ -1231,10 +1230,10 @@ const bool __my_real_part_is_neg(__my_z.real() < 0U); - const T __my_real_part_fabs((__my_real_part_is_neg == false) ? __my_z.real() : -__my_z.real()); + const T __my_real_part_fabs((!__my_real_part_is_neg) ? __my_z.real() : -__my_z.real()); const T __my_sqrt_part (sqrt((__my_real_part_fabs + abs(__my_z)) / 2U)); - if(__my_real_part_is_neg == false) + if(!__my_real_part_is_neg) { return complex(__my_sqrt_part, __my_z.imag() / (__my_sqrt_part * 2U)); @@ -1243,10 +1242,10 @@ { const bool __my_imag_part_is_neg(__my_z.imag() < 0U); - const T __my_imag_part_fabs((__my_imag_part_is_neg == false) ? __my_z.imag() : -__my_z.imag()); + const T __my_imag_part_fabs((!__my_imag_part_is_neg) ? __my_z.imag() : -__my_z.imag()); return complex( __my_imag_part_fabs / (__my_sqrt_part * 2U), - ((__my_imag_part_is_neg == false) ? __my_sqrt_part : -__my_sqrt_part)); + ((!__my_imag_part_is_neg) ? __my_sqrt_part : -__my_sqrt_part)); } } @@ -1288,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/chapter12_04/src/util/STL/cstdbool b/examples/chapter12_04/src/util/STL/cstdbool index 833781c82..35fbdae3b 100644 --- a/examples/chapter12_04/src/util/STL/cstdbool +++ b/examples/chapter12_04/src/util/STL/cstdbool @@ -8,15 +8,18 @@ #ifndef CSTDBOOL_2012_12_14_ #define CSTDBOOL_2012_12_14_ - #include + #if (!defined(__cplusplus) && !defined(__bool_true_false_are_defined)) + + #define bool _Bool + #define false 0 + #define true 1 + + #define __bool_true_false_are_defined 1 + + #endif #if !defined(__bool_true_false_are_defined) #define __bool_true_false_are_defined 1 #endif - namespace std - { - using ::bool; - } - #endif // CSTDBOOL_2012_12_14_ diff --git a/examples/chapter12_04/src/util/STL/cstdint b/examples/chapter12_04/src/util/STL/cstdint index 58f70a9ce..0e2e8d7ed 100644 --- a/examples/chapter12_04/src/util/STL/cstdint +++ b/examples/chapter12_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) @@ -13,32 +13,32 @@ // Implement some C macros that belong in if they are not present. #if !defined(INT8_C) - #define INT8_C(x) ((signed char) (x)) + #define INT8_C(x) ((int8_t) (x)) #endif #if !defined(INT16_C) - #define INT16_C(x) ((signed int) (x)) + #define INT16_C(x) ((int16_t) (x)) #endif #if !defined(INT32_C) - #define INT32_C(x) ((signed long) (x##L)) + #define INT32_C(x) ((int32_t) (x##L)) #endif #if !defined(INT64_C) - #define INT64_C(x) ((signed long long) (x##LL)) + #define INT64_C(x) ((int64_t) (x##LL)) #endif #if !defined(INTMAX_C) #define INTMAX_C(x) ((signed long long) (x##LL)) #endif #if !defined(UINT8_C) - #define UINT8_C(x) ((unsigned char) (x##U)) + #define UINT8_C(x) ((uint8_t) (x##U)) #endif #if !defined(UINT16_C) - #define UINT16_C(x) ((unsigned int) (x##U)) + #define UINT16_C(x) ((uint16_t) (x##U)) #endif #if !defined(UINT32_C) - #define UINT32_C(x) ((unsigned long) (x##UL)) + #define UINT32_C(x) ((uint32_t) (x##UL)) #endif #if !defined(UINT64_C) - #define UINT64_C(x) ((unsigned long long) (x##ULL)) + #define UINT64_C(x) ((uint64_t) (x##ULL)) #endif #if !defined(UINTMAX_C) #define UINTMAX_C(x) ((unsigned long long) (x##ULL)) @@ -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/chapter12_04/src/util/STL/cstdlib b/examples/chapter12_04/src/util/STL/cstdlib index 83e04fe69..fbad04c23 100644 --- a/examples/chapter12_04/src/util/STL/cstdlib +++ b/examples/chapter12_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 (); + int atexit(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/chapter12_04/src/util/STL/cstring b/examples/chapter12_04/src/util/STL/cstring new file mode 100644 index 000000000..3a899f75e --- /dev/null +++ b/examples/chapter12_04/src/util/STL/cstring @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 CSTRING_2018_10_04_ + #define CSTRING_2018_10_04_ + + #include + + 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 + { + using ::memcpy; + using ::memmove; + using ::memset; + using ::strlen; + using ::strcpy; + } + +#endif // CSTRING_2018_10_04_ diff --git a/examples/chapter12_04/src/util/STL/functional b/examples/chapter12_04/src/util/STL/functional index c9311e538..ca8441843 100644 --- a/examples/chapter12_04/src/util/STL/functional +++ b/examples/chapter12_04/src/util/STL/functional @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 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,8 +8,67 @@ #ifndef FUNCTIONAL_2013_08_30_ #define FUNCTIONAL_2013_08_30_ + #include + #include + #include + 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; } + template void func_ref_or_moveref(T&&) = delete; + } + + template + class reference_wrapper + { + public: + typedef T type; + + template(std::declval()), + std::enable_if_t<(!std::is_same>::value)>())> + constexpr reference_wrapper(U&& u) noexcept(noexcept(xfunctional_impl::func_ref_or_moveref(std::forward(u)))) + : my_ptr(std::addressof(xfunctional_impl::func_ref_or_moveref(std::forward(u)))) { } + + reference_wrapper(const reference_wrapper&) noexcept = default; + + reference_wrapper& operator=(const reference_wrapper& x) noexcept = default; + + constexpr operator T& () const noexcept { return *my_ptr; } + constexpr T& get() const noexcept { return *my_ptr; } + + //template< class... ArgTypes > + //constexpr std::invoke_result_t + //operator() ( ArgTypes&&... args ) const + //{ + // return std::invoke(get(), std::forward(args)...); + //} + + private: + T* my_ptr; + }; + + //template + //reference_wrapper(T&) -> reference_wrapper; + + template + struct identity + { + using type = T; + }; + template struct unary_function diff --git a/examples/chapter12_04/src/util/STL/impl/alloc_traits.h b/examples/chapter12_04/src/util/STL/impl/alloc_traits.h new file mode 100644 index 000000000..be8bd3d62 --- /dev/null +++ b/examples/chapter12_04/src/util/STL/impl/alloc_traits.h @@ -0,0 +1,305 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +// Allocator 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 ALLOC_TRAITS_2021_01_26_H_ + #define ALLOC_TRAITS_2021_01_26_H_ + + #include + + #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/chapter12_04/src/util/STL/impl/allocator_impl.h b/examples/chapter12_04/src/util/STL/impl/allocator_impl.h index 72b757ba0..ac7e8c742 100644 --- a/examples/chapter12_04/src/util/STL/impl/allocator_impl.h +++ b/examples/chapter12_04/src/util/STL/impl/allocator_impl.h @@ -8,10 +8,6 @@ #ifndef ALLOCATOR_IMPL_2010_02_23_H_ #define ALLOCATOR_IMPL_2010_02_23_H_ - #if defined(__GNUC__) - #pragma GCC system_header - #endif - #include #include diff --git a/examples/chapter12_04/src/util/STL/impl/avr/avr_atomic.h b/examples/chapter12_04/src/util/STL/impl/avr/avr_atomic.h index 958112895..7179cc287 100644 --- a/examples/chapter12_04/src/util/STL/impl/avr/avr_atomic.h +++ b/examples/chapter12_04/src/util/STL/impl/avr/avr_atomic.h @@ -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) diff --git a/examples/chapter12_04/src/util/STL/impl/avr/avr_float_limits.cpp b/examples/chapter12_04/src/util/STL/impl/avr/avr_float_limits.cpp deleted file mode 100644 index badd3d6aa..000000000 --- a/examples/chapter12_04/src/util/STL/impl/avr/avr_float_limits.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. -// 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 float_limits -{ - // 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()); -} - -namespace std -{ - float numeric_limits_details::my_value_that_needs_to_be_provided_flt_quiet_NaN() - { - return float_limits::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 float_limits::avr_inf_flt; - } - - double numeric_limits_details::my_value_that_needs_to_be_provided_dbl_quiet_NaN() - { - return float_limits::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 float_limits::avr_inf_dbl; - } - - long double numeric_limits_details::my_value_that_needs_to_be_provided_ldbl_quiet_NaN() - { - return float_limits::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 float_limits::avr_inf_ldbl; - } -} diff --git a/examples/chapter12_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp b/examples/chapter12_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp new file mode 100644 index 000000000..f06d5df8e --- /dev/null +++ b/examples/chapter12_04/src/util/STL/impl/avr/avr_hardware_random_device.cpp @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#include + +#include +#include +#include +#include + +auto my_hardware_random_device_generator() -> 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() +{ + return 1U; +} diff --git a/examples/chapter12_04/src/util/STL/impl/cmath_impl_gamma.cpp b/examples/chapter12_04/src/util/STL/impl/cmath_impl_gamma.cpp index c1b6c2cc3..3658e1b28 100644 --- a/examples/chapter12_04/src/util/STL/impl/cmath_impl_gamma.cpp +++ b/examples/chapter12_04/src/util/STL/impl/cmath_impl_gamma.cpp @@ -1,144 +1,142 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +// 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) // -#if defined(__GNUC__) || (defined(_WIN32) && (_MSC_VER <= 1700)) +#include +#include - #include - #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 . +#if defined(__GNUC__) && defined(__AVR__) +extern "C" float tgammaf(float x); +#endif - namespace detail - { - std::float32_t tgamma_inverse_taylor_series (std::float32_t); - std::float32_t tgamma_polynomial_approximation(std::float32_t); +// Here, we compute the tgamma function for float. +// This provides an example of a portable special function +// calculation using floating-point type definitions having +// specified widths from the proposed . - 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; - } +namespace xcmath_impl +{ + float tgamma_inverse_taylor_series (float); + float tgamma_polynomial_approximation(float); - 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); - } + float tgamma_inverse_taylor_series(float x) + { + // Implement a small-argument Taylor series for 1 / tgamma(x). + const float inverse_series_value + = ((((((( + 0.0072189432F + * x - 0.0096219715F) + * x - 0.0421977346F) + * x + 0.1665386114F) + * x - 0.0420026350F) + * x - 0.6558780715F) + * x + 0.5772156649F) + * x + 1.0F) + * x; + + return float(1.0F / inverse_series_value); } - namespace std + float tgamma_polynomial_approximation(float x) { - std::float32_t tgamma(std::float32_t); + // Implement an order-9 polynomial fit for gamma(1 + x). + const float polynomial_approximation_value + = (((((((( - 0.0235850272F + * x + 0.1405004023F) + * x - 0.3860871683F) + * x + 0.6721315341F) + * x - 0.8649108124F) + * x + 0.9539074630F) + * x - 0.9035083713F) + * x + 0.9887589417F) + * x - 0.5772069549F) + * x + 0.9999999703F; + + // Return the polynomial fit for gamma(x). + // One downward recursion is used here. + return float(polynomial_approximation_value / x); } +} - std::float32_t std::tgamma(std::float32_t x) - { - // Use a positive argument for the Gamma calculation. - const bool b_neg = (x < 0); +extern "C" +float tgammaf(float x) +{ + // Use a positive argument for the Gamma calculation. + const bool b_neg = (x < 0); - x = ((!b_neg) ? x : -x); + 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 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 xcmath::euler; + // Check if the argument is smaller than epsilon(). + if(x < std::numeric_limits::epsilon()) + { + using xcmath_impl::euler; - return ((!b_neg) ? (FLOAT32_C(+1.0) / x) - euler() - : (FLOAT32_C(-1.0) / x) - euler()); - } + return ((!b_neg) ? (+1.0F / x) - euler() + : (-1.0F / x) - euler()); + } - // Check for overflow. - if(x > FLOAT32_C(35.04)) - { - return std::numeric_limits::infinity(); - } + // Check for overflow. + if(x > 35.04F) + { + return std::numeric_limits::infinity(); + } - // Check if the argument is very close to +1 or +2? - if(b_neg == false) - { - using xcmath::near_integer; + // Check if the argument is very close to +1 or +2? + if(!b_neg) + { + using 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)); + 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); - } + if(is_near_one || is_near_two) + { + return 1.0F; } + } - // 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)); + // 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(::floorf(x)); - x -= n_recur; + 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)) ? detail::tgamma_inverse_taylor_series(x) - : detail::tgamma_polynomial_approximation(x)); + // Obtain an approximation of tgamma(x), where x has + // perhaps been negated and/or scaled to a lower value. + float gamma_value = ((x < 0.1F) ? xcmath_impl::tgamma_inverse_taylor_series(x) + : 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; + // 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; - } + ++x; + } - // Return (and possibly reflect) the result. - if(false == b_neg) - { - return gamma_value; - } - else - { - using xcmath::pi; + // Return (and possibly reflect) the result. + if(!b_neg) + { + return gamma_value; + } + else + { + using xcmath_impl::pi; - const std::float32_t sin_pi_x = std::sin(pi() * x); + using std::sin; - return -pi() / ((x * gamma_value) * sin_pi_x); - } - } + const float sin_pi_x = sin(pi() * x); -#endif + return -pi() / ((x * gamma_value) * sin_pi_x); + } +} diff --git a/examples/chapter12_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp b/examples/chapter12_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp new file mode 100644 index 000000000..715bcab0b --- /dev/null +++ b/examples/chapter12_04/src/util/STL/impl/cmath_impl_hyperbolic.cpp @@ -0,0 +1,95 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 "xcmath_impl.h" + +#if defined(__GNUC__) && defined(__AVR__) +extern "C" float asinhf(float x); +extern "C" float acoshf(float x); +extern "C" float atanhf(float x); +#endif + +// Here, we implement naive computations of the inverse hyperbolic +// trigonometric functions asinh, acosh, and atanh for float. +// 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. + +extern "C" +float asinhf(float x) +{ + // Implement a naive hyperbolic arc-sine function. + + using std::log; + using std::sqrt; + + return log(x + sqrt((x * x) + 1.0F)); +} + +extern "C" +float acoshf(float x) +{ + const float x_minus_one = x - 1.0F; + + if(x_minus_one < -std::numeric_limits::epsilon()) + { + return std::numeric_limits::quiet_NaN(); + } + else if(x_minus_one < std::numeric_limits::epsilon()) + { + return 1.0F; + } + else + { + // Implement a naive hyperbolic arc-cosine function. + + using std::log; + using std::sqrt; + + const float xp = (x + 1.0F); + const float xm = (x - 1.0F); + + return log(x + sqrt(xm * xp)); + } +} + +extern "C" +float atanhf(float x) +{ + const bool is_neg = (x < 0.0F); + + const float xx = ((!is_neg) ? x : -x); + + if(xx > 1.0F) + { + return std::numeric_limits::quiet_NaN(); + } + + float result; + + if(xx < 1.0F) + { + // Implement a naive hyperbolic arc-tangent function. + const float xp = (xx + 1.0F); + const float xm = (1.0F - xx); + + using std::log; + + result = (float) (log(xp) - log(xm)) / 2.0F; + } + else + { + result = std::numeric_limits::infinity(); + } + + return ((!is_neg) ? result : -result); +} diff --git a/examples/chapter12_04/src/util/STL/impl/ptr_traits.h b/examples/chapter12_04/src/util/STL/impl/ptr_traits.h new file mode 100644 index 000000000..eb3ad05fa --- /dev/null +++ b/examples/chapter12_04/src/util/STL/impl/ptr_traits.h @@ -0,0 +1,185 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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_ + + #include + + 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/chapter12_04/src/util/STL/impl/stl_local_constexpr.h b/examples/chapter12_04/src/util/STL/impl/stl_local_constexpr.h index ec4112078..b010f2cfa 100644 --- a/examples/chapter12_04/src/util/STL/impl/stl_local_constexpr.h +++ b/examples/chapter12_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/chapter12_04/src/util/STL/impl/stl_local_noexcept.h b/examples/chapter12_04/src/util/STL/impl/stl_local_noexcept.h index 2f2c95fd2..6ea9125da 100644 --- a/examples/chapter12_04/src/util/STL/impl/stl_local_noexcept.h +++ b/examples/chapter12_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/chapter12_04/src/util/STL/impl/xcmath_impl.h b/examples/chapter12_04/src/util/STL/impl/xcmath_impl.h index 4a78b81c1..1120d94ff 100644 --- a/examples/chapter12_04/src/util/STL/impl/xcmath_impl.h +++ b/examples/chapter12_04/src/util/STL/impl/xcmath_impl.h @@ -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) @@ -12,38 +12,38 @@ #include #include - namespace xcmath + namespace xcmath_impl { + + template + bool near_integer(const float_type& x, const std::uint_least8_t n) + { + const float_type n_eps = static_cast( (std::max)(std::uint_least8_t(2U), std::uint_least8_t(n + 1U)) + * std::numeric_limits::epsilon()); + + const float_type n_minus_n_eps = static_cast(n) - n_eps; + const float_type n_plus_n_eps = static_cast(n) + n_eps; + + return ((x > n_minus_n_eps) && (x < n_plus_n_eps)); + } + + template + constexpr float_type pi() { - template - bool near_integer(const float_type& x, const std::uint_least8_t n) - { - const float_type n_eps = static_cast( (std::max)(std::uint_least8_t(2U), std::uint_least8_t(n + 1U)) - * std::numeric_limits::epsilon()); - - const float_type n_minus_n_eps = static_cast(n) - n_eps; - const float_type n_plus_n_eps = static_cast(n) + n_eps; - - return ((x > n_minus_n_eps) && (x < n_plus_n_eps)); - } - - template - const float_type pi() - { - return static_cast(FLOATMAX_C(3.1415926535897932384626433832795028841972)); - } - - template - const float_type ln_two() - { - return static_cast(FLOATMAX_C(0.6931471805599453094172321214581765680755)); - } - - template - const float_type euler() - { - return static_cast(FLOATMAX_C(0.5772156649015328606065120900824024310422)); - } + return static_cast(3.1415926535897932384626433832795028841972L); + } + + template + constexpr float_type ln_two() + { + return static_cast(0.6931471805599453094172321214581765680755L); + } + template + constexpr float_type euler() + { + return static_cast(0.5772156649015328606065120900824024310422L); } + } // namespace xcmath_impl + #endif // XCMATH_IMPL_2014_01_11_H_ diff --git a/examples/chapter12_04/src/util/STL/initializer_list b/examples/chapter12_04/src/util/STL/initializer_list index 46cd17298..6b993ed2c 100644 --- a/examples/chapter12_04/src/util/STL/initializer_list +++ b/examples/chapter12_04/src/util/STL/initializer_list @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +// Copyright Christopher Kormanyos 2012 - 2019. // 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,17 +8,13 @@ #ifndef INITIALIZER_LIST_2012_02_14_H_ #define INITIALIZER_LIST_2012_02_14_H_ - #if defined(__GNUC__) - #pragma GCC system_header - #endif - #include #include #include #include - // Implement some of std::initializer_list for compilers that do not yet support it. + // Implement std::initializer_list for compilers that do not yet support it. // See ISO/IEC 14882:2011 Chapter 18.9. namespace std @@ -34,31 +30,36 @@ typedef const T* iterator; typedef const T* const_iterator; - STL_LOCAL_CONSTEXPR initializer_list() STL_LOCAL_NOEXCEPT : data (nullptr), - length(0U) { } + STL_LOCAL_CONSTEXPR initializer_list() STL_LOCAL_NOEXCEPT + : my_elems (nullptr), + my_length(0U) { } - STL_LOCAL_CONSTEXPR size_type size() const STL_LOCAL_NOEXCEPT { return length; } + STL_LOCAL_CONSTEXPR initializer_list(iterator it_first, + iterator it_last) STL_LOCAL_NOEXCEPT + : my_elems (it_first), + my_length (size_type(it_last - it_first)) { } - STL_LOCAL_CONSTEXPR const_iterator begin() const STL_LOCAL_NOEXCEPT { return data; } - STL_LOCAL_CONSTEXPR const_iterator end () const STL_LOCAL_NOEXCEPT { return data + length; } + STL_LOCAL_CONSTEXPR size_type size() const STL_LOCAL_NOEXCEPT { return my_length; } - private: - iterator data; - size_type length; + STL_LOCAL_CONSTEXPR iterator begin() const STL_LOCAL_NOEXCEPT { return my_elems; } + STL_LOCAL_CONSTEXPR iterator end () const STL_LOCAL_NOEXCEPT { return my_elems + my_length; } - STL_LOCAL_CONSTEXPR initializer_list(const_iterator it, size_type len) : data (it), - length(len) { } + private: + iterator my_elems; + size_type my_length; }; // Non-member versions of begin and end of initializer_list. template - STL_LOCAL_CONSTEXPR typename initializer_list::const_iterator begin(initializer_list lst) + STL_LOCAL_CONSTEXPR + typename initializer_list::iterator begin(initializer_list lst) STL_LOCAL_NOEXCEPT { return lst.begin(); } template - STL_LOCAL_CONSTEXPR typename initializer_list::const_iterator end(initializer_list lst) + STL_LOCAL_CONSTEXPR + typename initializer_list::iterator end(initializer_list lst) STL_LOCAL_NOEXCEPT { return lst.end(); } @@ -66,19 +67,23 @@ // Namespace std inline versions of rbegin and rend of initializer_list. // These are specified in C++14. template - STL_LOCAL_CONSTEXPR typename initializer_list::const_iterator rbegin(initializer_list lst) + STL_LOCAL_CONSTEXPR + typename initializer_list::iterator rbegin(initializer_list lst) STL_LOCAL_NOEXCEPT { - typedef std::reverse_iterator::const_iterator> reverse_iterator_type; + using local_reverse_iterator_type = + std::reverse_iterator::iterator>; - return reverse_iterator_type(lst.end()); + return local_reverse_iterator_type(lst.end()); } template - STL_LOCAL_CONSTEXPR typename initializer_list::const_iterator rend(initializer_list lst) + STL_LOCAL_CONSTEXPR + typename initializer_list::iterator rend(initializer_list lst) STL_LOCAL_NOEXCEPT { - typedef std::reverse_iterator::const_iterator> reverse_iterator_type; + using local_reverse_iterator_type = + std::reverse_iterator::iterator>; - return reverse_iterator_type(lst.begin()); + return local_reverse_iterator_type(lst.begin()); } } diff --git a/examples/chapter12_04/src/util/STL/iterator b/examples/chapter12_04/src/util/STL/iterator index ae2ae4760..b21b81899 100644 --- a/examples/chapter12_04/src/util/STL/iterator +++ b/examples/chapter12_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,57 +85,59 @@ 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 - typename iterator_traits::difference_type distance(input_iterator first, input_iterator last) + STL_LOCAL_CONSTEXPR_ALGORITHMS + typename iterator_traits::difference_type distance(input_iterator first, + input_iterator last) { typedef typename iterator_traits::difference_type distance_type; @@ -152,32 +153,43 @@ return the_distance; } + template + STL_LOCAL_CONSTEXPR_ALGORITHMS + void advance(input_iterator& it, distance_type n) + { + for(distance_type i = distance_type(0); i != n; ++i, ++it) + { + ; + } + } + // 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/chapter12_04/src/util/STL/limits b/examples/chapter12_04/src/util/STL/limits index 367a2fb1e..15bf177a3 100644 --- a/examples/chapter12_04/src/util/STL/limits +++ b/examples/chapter12_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/chapter12_04/src/util/STL/memory b/examples/chapter12_04/src/util/STL/memory index 31d974411..92bf3cb6f 100644 --- a/examples/chapter12_04/src/util/STL/memory +++ b/examples/chapter12_04/src/util/STL/memory @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2016. +/////////////////////////////////////////////////////////////////////////////// +// 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); } @@ -188,6 +172,108 @@ void deallocate(pointer, size_type) { } }; + + namespace detail + { + template + struct addr_impl_ref + { + T& my_v; + + inline addr_impl_ref(T& v): my_v(v) { } + + inline operator T& () const + { + return my_v; + } + + private: + addr_impl_ref& operator=(const addr_impl_ref&); + }; + + template + struct addressof_impl + { + static inline T* f(T& v, long) + { + return reinterpret_cast(&const_cast(reinterpret_cast(v))); + } + + static inline T* f(T* v, int) + { + return v; + } + }; + } + + template + T* addressof(T& v) + { + 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/chapter12_04/src/util/STL/random b/examples/chapter12_04/src/util/STL/random new file mode 100644 index 000000000..0da085c31 --- /dev/null +++ b/examples/chapter12_04/src/util/STL/random @@ -0,0 +1,1719 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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) +// + +#ifndef RANDOM_2018_06_10_ + #define RANDOM_2018_06_10_ + + #include + #include + #include + #include + #include + #include + + // Implement some of for compilers that do not yet support it. + + extern "C" unsigned int my_hardware_random_device_generator(); + extern "C" unsigned char my_hardware_random_device_entropy (); + + 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 + { + 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) + { + return static_cast((_Tp2(ParamA) * rnd__x + ParamC) % ParamM); + } + }; + + // 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; + + T rnd__t1 = ParamA * (rnd__x % rnd__seed_sequence); + T rnd__t2 = rnd__long_lag_r * (rnd__x / rnd__seed_sequence); + + if (rnd__t1 >= rnd__t2) + { + rnd__x = rnd__t1 - rnd__t2; + } + else + { + rnd__x = ParamM - rnd__t2 + rnd__t1; + } + } + + if(ParamC != 0) + { + const T rnd__value_d = ParamM - rnd__x; + + if (rnd__value_d > ParamC) + { + rnd__x += ParamC; + } + else + { + rnd__x = ParamC - rnd__value_d; + } + } + + return rnd__x; + } + }; + + // 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; + + if (ParamM) + { + rnd__res %= ParamM; + } + + return rnd__res; + } + }; + + 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; + } + + return rnd__result; + } + + } } // namespace std::rnd__detail + + namespace std { + + // 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. + + template + class linear_congruential_engine + { + private: + static_assert(std::is_unsigned::value, + "Error: result_type must be an unsigned integral type"); + + static_assert(ParamM == 0u || (ParamA < ParamM && ParamC < ParamM), + "Error: template argument substituting ParamM out of bounds"); + + 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; + } + + return rnd__xi; + } + + void discard(unsigned long long rnd__z) + { + for (; rnd__z != 0ULL; --rnd__z) + { + (*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(); + } + + 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(); + } + + void discard(unsigned long long rnd__z) + { + for(; rnd__z != 0ULL; --rnd__z) + { + (*this)(); + } + } + + result_type operator()(); + + 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(); + } + + 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() + { + 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; + } + + 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/chapter12_04/src/util/STL/ratio b/examples/chapter12_04/src/util/STL/ratio index 9ab68582e..bcfe973a9 100644 --- a/examples/chapter12_04/src/util/STL/ratio +++ b/examples/chapter12_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/chapter12_04/src/util/STL/span b/examples/chapter12_04/src/util/STL/span new file mode 100644 index 000000000..1c5d121e3 --- /dev/null +++ b/examples/chapter12_04/src/util/STL/span @@ -0,0 +1,496 @@ +// This is a significant simplification of an existing work: +// Comments from the original work follow. + +// This is an implementation of std::span from P0122R7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0122r7.pdf + +/////////////////////////////////////////////////////////////////////////////// +// Copyright Tristan Brindle 2018. +// Copyright Christopher Kormanyos 2019 - 2024. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file ../../LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef SPAN_2019_07_27_ + #define SPAN_2019_07_27_ + + #include + #include + #include + + #include + #include + + namespace std { + + using byte = unsigned char; + + STL_LOCAL_CONSTEXPR std::size_t dynamic_extent = + static_cast((std::numeric_limits::max)()); + + template + class span; + + namespace detail { + + template + struct span_storage + { + STL_LOCAL_CONSTEXPR span_storage() STL_LOCAL_NOEXCEPT + : ptr(nullptr) { } + + STL_LOCAL_CONSTEXPR span_storage(E* ptr_in, std::ptrdiff_t) STL_LOCAL_NOEXCEPT + : ptr(ptr_in) { } + + E* ptr; + static STL_LOCAL_CONSTEXPR std::ptrdiff_t size = S; + }; + + template + struct span_storage + { + STL_LOCAL_CONSTEXPR span_storage() STL_LOCAL_NOEXCEPT + : ptr (nullptr), + size(0U) { } + + STL_LOCAL_CONSTEXPR span_storage(E* ptr_in, std::ptrdiff_t size_in) STL_LOCAL_NOEXCEPT + : ptr (ptr_in), + size(size_in) { } + + E* ptr; + std::ptrdiff_t size; + }; + + // Reimplementation of C++17 std::size() and std::data() + template + STL_LOCAL_CONSTEXPR auto size(const C& c) -> decltype(c.size()) + { + return c.size(); + } + + template + STL_LOCAL_CONSTEXPR std::size_t size(const T (&)[N]) STL_LOCAL_NOEXCEPT + { + return N; + } + + template + STL_LOCAL_CONSTEXPR auto data(C& c) -> decltype(c.data()) + { + return c.data(); + } + + template + STL_LOCAL_CONSTEXPR auto data(const C& c) -> decltype(c.data()) + { + return c.data(); + } + + template + STL_LOCAL_CONSTEXPR T* data(T (&array)[N]) STL_LOCAL_NOEXCEPT + { + return array; + } + + template + STL_LOCAL_CONSTEXPR const E* data(std::initializer_list il) STL_LOCAL_NOEXCEPT + { + return il.begin(); + } + } + + template + class span + { + private: + using storage_type = detail::span_storage; + + public: + using element_type = ElementType; + using value_type = typename std::remove_cv::type; + using index_type = std::ptrdiff_t; + using difference_type = std::ptrdiff_t; + using pointer = ElementType*; + using reference = ElementType&; + using iterator = pointer; + using const_iterator = const ElementType*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + static STL_LOCAL_CONSTEXPR index_type extent = Extent; + + // [span.cons], span constructors, copy, assignment, and destructor + template::type = 0> + STL_LOCAL_CONSTEXPR span() STL_LOCAL_NOEXCEPT { } + + STL_LOCAL_CONSTEXPR span(pointer ptr, index_type count) + : storage_(ptr, count) { } + + STL_LOCAL_CONSTEXPR span(pointer first_elem, pointer last_elem) + : storage_(first_elem, last_elem - first_elem) { } + + template + STL_LOCAL_CONSTEXPR span(element_type(&arr)[N]) STL_LOCAL_NOEXCEPT + : storage_(arr, N) { } + + template + STL_LOCAL_CONSTEXPR span(const std::array& arr) STL_LOCAL_NOEXCEPT + : storage_(arr.data(), N) { } + + template + STL_LOCAL_CONSTEXPR span(Container& cont) + : storage_(detail::data(cont), detail::size(cont)) { } + + template + STL_LOCAL_CONSTEXPR span(const Container& cont) + : storage_(detail::data(cont), detail::size(cont)) { } + + STL_LOCAL_CONSTEXPR span(const span& other) STL_LOCAL_NOEXCEPT = default; + + template::value = 0> + STL_LOCAL_CONSTEXPR span(const span& other) STL_LOCAL_NOEXCEPT + : storage_(other.data(), other.size()) { } + + ~span() STL_LOCAL_NOEXCEPT = default; + + span& operator=(const span& other) STL_LOCAL_NOEXCEPT = default; + + // [span.sub], span subviews + template + STL_LOCAL_CONSTEXPR span first() const + { + return {data(), Count}; + } + + template + STL_LOCAL_CONSTEXPR span last() const + { + return {data() + (size() - Count), Count}; + } + + template + using subspan_return_t = + span; + + template + STL_LOCAL_CONSTEXPR subspan_return_t subspan() const + { + return {data() + Offset, + Count != dynamic_extent + ? Count + : (Extent != dynamic_extent ? Extent - Offset + : size() - Offset)}; + } + + STL_LOCAL_CONSTEXPR span + first(index_type count) const + { + return {data(), count}; + } + + STL_LOCAL_CONSTEXPR span + last(index_type count) const + { + return {data() + (size() - count), count}; + } + + STL_LOCAL_CONSTEXPR span + subspan(index_type offset, index_type count = dynamic_extent) const + { + return {data() + offset, + count == dynamic_extent ? size() - offset : count}; + } + + // [span.obs], span observers + STL_LOCAL_CONSTEXPR index_type size() const STL_LOCAL_NOEXCEPT { return storage_.size; } + + STL_LOCAL_CONSTEXPR index_type size_bytes() const STL_LOCAL_NOEXCEPT + { + return size() * sizeof(element_type); + } + + STL_LOCAL_CONSTEXPR bool empty() const STL_LOCAL_NOEXCEPT { return size() == 0; } + + // [span.elem], span element access + STL_LOCAL_CONSTEXPR reference operator[](index_type idx) const + { + return *(data() + idx); + } + + // Extension: not in P0122 + reference at(index_type idx) const + { + return this->operator[](idx); + } + + STL_LOCAL_CONSTEXPR reference front() const + { + return *data(); + } + + STL_LOCAL_CONSTEXPR reference back() const + { + return *(data() + (size() - 1)); + } + + STL_LOCAL_CONSTEXPR pointer data() const STL_LOCAL_NOEXCEPT { return storage_.ptr; } + + // [span.iterators], span iterator support + STL_LOCAL_CONSTEXPR iterator begin() const STL_LOCAL_NOEXCEPT { return data(); } + + STL_LOCAL_CONSTEXPR iterator end() const STL_LOCAL_NOEXCEPT { return data() + size(); } + + STL_LOCAL_CONSTEXPR const_iterator cbegin() const STL_LOCAL_NOEXCEPT { return begin(); } + + STL_LOCAL_CONSTEXPR const_iterator cend() const STL_LOCAL_NOEXCEPT { return end(); } + + STL_LOCAL_CONSTEXPR reverse_iterator rbegin() const STL_LOCAL_NOEXCEPT + { + return reverse_iterator(end()); + } + + STL_LOCAL_CONSTEXPR reverse_iterator rend() const STL_LOCAL_NOEXCEPT + { + return reverse_iterator(begin()); + } + + STL_LOCAL_CONSTEXPR const_reverse_iterator crbegin() const STL_LOCAL_NOEXCEPT + { + return const_reverse_iterator(cend()); + } + + STL_LOCAL_CONSTEXPR const_reverse_iterator crend() const STL_LOCAL_NOEXCEPT + { + return const_reverse_iterator(cbegin()); + } + + private: + storage_type storage_{}; + }; + + template + STL_LOCAL_CONSTEXPR span + make_span(span s) STL_LOCAL_NOEXCEPT + { + return s; + } + + template + STL_LOCAL_CONSTEXPR span make_span(T (&arr)[N]) STL_LOCAL_NOEXCEPT + { + return {arr}; + } + + template + STL_LOCAL_CONSTEXPR span make_span(std::array& arr) STL_LOCAL_NOEXCEPT + { + return {arr}; + } + + template + STL_LOCAL_CONSTEXPR span + make_span(const std::array& arr) STL_LOCAL_NOEXCEPT + { + return {arr}; + } + + template + STL_LOCAL_CONSTEXPR span make_span(Container& cont) + { + return {cont}; + } + + template + STL_LOCAL_CONSTEXPR span + make_span(const Container& cont) + { + return {cont}; + } + + // Comparison operators + // Implementation note: the implementations of == and < are equivalent to + // 4-legged std::equal and std::lexicographical_compare respectively + + template + bool operator==(span lhs, span rhs) + { + if (lhs.size() != rhs.size()) + { + return false; + } + + for (std::ptrdiff_t i = 0; i < lhs.size(); i++) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + + return true; + } + + template + bool operator!=(span lhs, span rhs) + { + return !(lhs == rhs); + } + + template + bool operator<(span lhs, span rhs) + { + // No std::min to avoid dragging in + const std::ptrdiff_t size = + lhs.size() < rhs.size() ? lhs.size() : rhs.size(); + + for (std::ptrdiff_t i = 0; i < size; i++) + { + if (lhs[i] < rhs[i]) + { + return true; + } + + if (lhs[i] > rhs[i]) + { + return false; + } + } + + return lhs.size() < rhs.size(); + } + + template + bool operator<=(span lhs, span rhs) + { + return !(rhs < lhs); + } + + template + bool operator>(span lhs, span rhs) + { + return rhs < lhs; + } + + template + bool operator>=(span lhs, span rhs) + { + return !(lhs < rhs); + } + + template + span(sizeof(ElementType)) * Extent))> + as_bytes(span s) STL_LOCAL_NOEXCEPT + { + return {reinterpret_cast(s.data()), s.size_bytes()}; + } + + template::value, int>::type = 0> + span(sizeof(ElementType)) * Extent))> + as_writable_bytes(span s) STL_LOCAL_NOEXCEPT + { + return {reinterpret_cast(s.data()), s.size_bytes()}; + } + + // Extension: nonmember subview operations + + template + STL_LOCAL_CONSTEXPR auto first(T& t) + -> decltype(make_span(t).template first()) + { + return make_span(t).template first(); + } + + template + STL_LOCAL_CONSTEXPR auto last(T& t) + -> decltype(make_span(t).template last()) + { + return make_span(t).template last(); + } + + template + STL_LOCAL_CONSTEXPR auto subspan(T& t) + -> decltype(make_span(t).template subspan()) + { + return make_span(t).template subspan(); + } + + template + STL_LOCAL_CONSTEXPR auto first(T& t, std::ptrdiff_t count) + -> decltype(make_span(t).first(count)) + { + return make_span(t).first(count); + } + + template + STL_LOCAL_CONSTEXPR + auto last(T& t, std::ptrdiff_t count) + -> decltype(make_span(t).last(count)) + { + return make_span(t).last(count); + } + + template + STL_LOCAL_CONSTEXPR + auto subspan(T& t, std::ptrdiff_t offset, + std::ptrdiff_t count = dynamic_extent) + -> decltype(make_span(t).subspan(offset, count)) + { + return make_span(t).subspan(offset, count); + } + + } // namespace std + + // Extension: support for C++17 structured bindings + + namespace std { + + template + STL_LOCAL_CONSTEXPR auto get(span s) -> decltype(s[N]) + { + return s[N]; + } + + } // namespace std + + namespace std { + + template + class tuple_size> + : public integral_constant { }; + + template + class tuple_size>; // not defined + + template + class tuple_element> + { + public: + using type = E; + }; + + } // end namespace std + +#endif // SPAN_2019_07_27_ diff --git a/examples/chapter12_04/src/util/STL/stdexcept b/examples/chapter12_04/src/util/STL/stdexcept new file mode 100644 index 000000000..5e7a8c527 --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/STL/stdfloat b/examples/chapter12_04/src/util/STL/stdfloat new file mode 100644 index 000000000..3b5e46ad7 --- /dev/null +++ b/examples/chapter12_04/src/util/STL/stdfloat @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. +// 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 STDFLOAT_2024_07_12 + #define STDFLOAT_2024_07_12 + + #if defined(__GNUC__) + #pragma GCC system_header + #endif + + #include + + namespace std + { + using float32_t = float; + #define __STDCPP_FLOAT32_T__ 1 + + #if (defined(__GNUC__) && defined(__AVR__)) + + #if(__GNUC__ >= 12) + using float64_t = long double; + #define __STDCPP_FLOAT64_T__ 1 + #endif + + #elif (defined(__GNUC__) && defined(__RL78__)) + + using float64_t = long double; + #define __STDCPP_FLOAT64_T__ 1 + + #else + + using float64_t = double; + #define __STDCPP_FLOAT64_T__ 1 + + #endif + } + + static_assert((std::numeric_limits::digits == 24), "Error: Incorrect float32_t type definition"); + static_assert((std::numeric_limits::digits == 53), "Error: Incorrect float64_t type definition"); + +#endif // STDFLOAT_2024_07_12 diff --git a/examples/chapter12_04/src/util/STL/string b/examples/chapter12_04/src/util/STL/string index f3d4e00d9..2bda595ba 100644 --- a/examples/chapter12_04/src/util/STL/string +++ b/examples/chapter12_04/src/util/STL/string @@ -13,11 +13,18 @@ #endif #include + #include namespace std { 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/chapter12_04/src/util/STL/time.h b/examples/chapter12_04/src/util/STL/time.h index bcd72845c..0bc1d8e84 100644 --- a/examples/chapter12_04/src/util/STL/time.h +++ b/examples/chapter12_04/src/util/STL/time.h @@ -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) diff --git a/examples/chapter12_04/src/util/STL/tuple b/examples/chapter12_04/src/util/STL/tuple index 585786312..14798e7be 100644 --- a/examples/chapter12_04/src/util/STL/tuple +++ b/examples/chapter12_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 @@ -63,9 +63,24 @@ typename T7 = xtuple_helper::xnothing, typename T8 = xtuple_helper::xnothing, typename T9 = xtuple_helper::xnothing, - typename T10 = xtuple_helper::xnothing> + typename T10 = xtuple_helper::xnothing, + 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 @@ -74,59 +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()) : t0 (p0), - t1 (p1), - t2 (p2), - t3 (p3), - t4 (p4), - t5 (p5), - t6 (p6), - t7 (p7), - t8 (p8), - t9 (p9), - t10(p10) { } - - 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) { } + 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()) { } - - ~tuple() { } + constexpr tuple(const std::pair& p) : t0 (p.first), + t1 (p.second) { } + + ~tuple() = default; template - tuple& operator=(const tuple& t) + typename U10, + typename U11> + 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); + 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); @@ -171,51 +217,80 @@ t8 = T8 (); t9 = T9 (); t10 = T10(); + t11 = T11(); + 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; + 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; - - 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; + 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; + } }; } @@ -224,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); @@ -244,6 +319,7 @@ MAKE_XTUPLE_GET_HELPER(8); MAKE_XTUPLE_GET_HELPER(9); MAKE_XTUPLE_GET_HELPER(10); + MAKE_XTUPLE_GET_HELPER(11); template class xtuple_elem_size_helper { public: static STL_LOCAL_CONSTEXPR std::size_t value = 1U; }; template<> class xtuple_elem_size_helper { public: static STL_LOCAL_CONSTEXPR std::size_t value = 0U; }; @@ -252,71 +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; + 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 + 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 + constexpr const typename xtuple_helper::xget >::xelem_type& get(const tuple& t) { return xtuple_helper::xget >::get_const(t); } template @@ -354,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 @@ -366,6 +447,136 @@ template class tuple_size : public std::integral_constant::value> { }; + template + constexpr tuple make_tuple(const T0& p0 = T0 ()) + { return tuple(p0); } + + template + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 ()) + { return tuple(p0, p1); } + + template + constexpr tuple make_tuple(const T0& p0 = T0 (), + const T1& p1 = T1 (), + const T2& p2 = T2 ()) + { return tuple(p0, p1, p2); } + + template + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 { - typedef typename tuple::tuple_type tuple_type; + template + constexpr ignore_t& operator=(T&&) noexcept { return *this; } - return tuple_type(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + 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...}; } } diff --git a/examples/chapter12_04/src/util/STL/type_traits b/examples/chapter12_04/src/util/STL/type_traits index c9769cfc2..7c9d8caa4 100644 --- a/examples/chapter12_04/src/util/STL/type_traits +++ b/examples/chapter12_04/src/util/STL/type_traits @@ -1,5 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +/////////////////////////////////////////////////////////////////////////////// +// 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) @@ -8,18 +8,8 @@ #ifndef TYPE_TRAITS_2013_09_01_ #define TYPE_TRAITS_2013_09_01_ - #if defined(_MSC_VER) - #include - #include - typedef ::int16_t char16_t; - typedef ::int32_t char32_t; - #endif // _MSC_VER - #include - #include - - #include - #include + #include // Implement some of for compilers that do not yet support it. @@ -31,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; } @@ -73,15 +63,39 @@ namespace std { template + typename value_type = void> struct enable_if { }; - template - struct enable_if + template + struct enable_if + { + typedef value_type type; + }; + + template + using enable_if_t = typename enable_if::type; + + template + struct conditional { - typedef the_value_type type; + typedef true_type type; }; + template + struct conditional + { + typedef false_type type; + }; + + template + using conditional_t = typename conditional::type; + template struct is_same : false_type { }; @@ -113,8 +127,6 @@ template struct is_volatile : std::false_type { }; template struct is_volatile : std::true_type { }; - template struct is_signed : std::integral_constant ::is_signed == true )> { }; - template struct is_unsigned : std::integral_constant ::is_signed == false)> { }; template struct is_void : std::integral_constant ::type>::value> { }; template struct is_null_pointer : std::integral_constant ::type>::value> { }; template struct is_integral : traits_helper::is_integral ::type> { }; @@ -128,6 +140,365 @@ template struct is_array : std::true_type {}; 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; + + template + using remove_reference_t = typename remove_reference::type; + + template + struct remove_cvref + { + typedef std::remove_cv_t> type; + }; + + 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 + { + template::value> + struct is_unsigned : std::integral_constant { }; + + template + struct is_unsigned : std::false_type { }; + + template::value> + struct is_signed : std::integral_constant { }; + + template + struct is_signed : std::false_type { }; + } + + namespace std + { + template struct is_unsigned : traits_helper::is_unsigned::type { }; + template struct is_signed : traits_helper::is_signed ::type { }; + } + + namespace traits_helper + { + template + struct type_identity { using type = T; }; + + template + auto try_add_lvalue_reference(int) -> type_identity; + + template + auto try_add_lvalue_reference(...) -> type_identity; + + template + auto try_add_rvalue_reference(int) -> type_identity; + + 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 + { + template + struct add_lvalue_reference : decltype(traits_helper::try_add_lvalue_reference(0)) { }; + + template + struct add_rvalue_reference : decltype(traits_helper::try_add_rvalue_reference(0)) { }; + + 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/chapter12_04/src/util/STL/utility b/examples/chapter12_04/src/util/STL/utility index 09d5e04a8..376d858c5 100644 --- a/examples/chapter12_04/src/util/STL/utility +++ b/examples/chapter12_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) @@ -9,11 +9,30 @@ #define UTILITY_2010_02_23_ #include - #include #include + #include // Implement some of for compilers that do not yet support it. + namespace std + { + // Forward declaration of std::identity, which is implemented in . + template + struct identity; + + template + constexpr T&& forward(remove_reference_t& arg) STL_LOCAL_NOEXCEPT + { + return static_cast(arg); + } + + template + constexpr T&& forward(remove_reference_t&& arg) STL_LOCAL_NOEXCEPT + { + return static_cast(arg); + } + } + namespace std { 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; + } }; } @@ -152,13 +193,13 @@ template bool operator<=(const std::pair& left, const std::pair& right) { - return ((right < left) == false); + return (!(right < left)); } template bool operator>=(const std::pair& left, const std::pair& right) { - return ((left < right) == false); + return (!(left < right)); } template @@ -168,4 +209,117 @@ } } + namespace std + { + template + struct integer_sequence; + } + + namespace xinteger_sequence_helper + { + template + struct repeat; + + template + struct repeat, _Extra...> + { + typedef std::integer_sequence type; + }; + + template struct parity; + template struct make:parity::template pmake { }; + + template <> struct make<0> { typedef std::integer_sequence type; }; + template <> struct make<1> { typedef std::integer_sequence type; }; + template <> struct make<2> { typedef std::integer_sequence type; }; + template <> struct make<3> { typedef std::integer_sequence type; }; + template <> struct make<4> { typedef std::integer_sequence type; }; + template <> struct make<5> { typedef std::integer_sequence type; }; + template <> struct make<6> { typedef std::integer_sequence type; }; + template <> struct make<7> { typedef std::integer_sequence type; }; + + template <> struct parity<0> { template struct pmake:repeat::type> {}; }; + template <> struct parity<1> { template struct pmake:repeat::type, N - 1> {}; }; + template <> struct parity<2> { template struct pmake:repeat::type, N - 2, N - 1> {}; }; + template <> struct parity<3> { template struct pmake:repeat::type, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<4> { template struct pmake:repeat::type, N - 4, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<5> { template struct pmake:repeat::type, N - 5, N - 4, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<6> { template struct pmake:repeat::type, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; }; + template <> struct parity<7> { template struct pmake:repeat::type, N - 7, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; }; + + template + struct convert + { + template + struct result; + + template + struct result > + { + typedef std::integer_sequence type; + }; + }; + + template + struct convert + { + template + struct result + { + typedef U type; + }; + }; + + template + using make_integer_sequence_unchecked = + typename convert::template result::type>::type; + + template + struct make_integer_sequence + { + static_assert(std::is_integral::value, + "std::make_integer_sequence can only be instantiated with an integral type"); + static_assert(0 <= N,"std::make_integer_sequence input shall not be negative"); + + typedef make_integer_sequence_unchecked type; + }; + } // namespace xinteger_sequence_helper + + namespace std + { + template + struct integer_sequence + { + typedef T value_type; + static_assert( + std::is_integral::value, + "std::integer_sequence can only be instantiated with an integral type" ); + + static std::size_t size() + { + return (sizeof...(N)); + } + }; + + template + using index_sequence = integer_sequence; + + template + using make_integer_sequence = typename xinteger_sequence_helper::make_integer_sequence::type; + + template + using make_index_sequence = make_integer_sequence; + + template + using index_sequence_for = make_index_sequence; + } + #endif // UTILITY_2010_02_23_ diff --git a/examples/chapter12_04/src/util/STL/vector b/examples/chapter12_04/src/util/STL/vector index 5b4604980..fe7c25c9e 100644 --- a/examples/chapter12_04/src/util/STL/vector +++ b/examples/chapter12_04/src/util/STL/vector @@ -20,7 +20,7 @@ namespace std { template > + typename alloc = std::allocator> class vector { public: @@ -37,9 +37,9 @@ typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - vector() : my_first(iterator(0U)), - my_last (iterator(0U)), - my_end (iterator(0U)) { } + vector() : my_first(nullptr), + my_last (nullptr), + my_end (nullptr) { } explicit vector(size_type count) : my_first(allocator_type().allocate(count)), my_last (my_first + count), @@ -222,7 +222,8 @@ if(capacity() <= the_size) { const size_type count = the_size * 2U; - reserve((std::max)(count, 4U)); + + reserve((std::max)(count, size_type(4U))); } *my_last = value; @@ -240,8 +241,6 @@ iterator my_first; // begin() iterator my_last; // end() iterator my_end; // capacity() - - static allocator_type get_allocator() { return allocator_type(); } }; } diff --git a/examples/chapter12_04/src/util/STL/version b/examples/chapter12_04/src/util/STL/version new file mode 100644 index 000000000..5ba3311be --- /dev/null +++ b/examples/chapter12_04/src/util/STL/version @@ -0,0 +1,16 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 VERSION_2024_06_29 + #define VERSION_2024_06_29 + + // Implement some of for compilers that do not yet support it. + // In this particular case, simply include the standard ISO header. + + #include + +#endif // VERSION_2024_06_29 diff --git a/examples/chapter12_04/src/util/STL_C++XX_stdfloat/cstdfloat b/examples/chapter12_04/src/util/STL_C++XX_stdfloat/cstdfloat index ece28d13a..c060f0845 100644 --- a/examples/chapter12_04/src/util/STL_C++XX_stdfloat/cstdfloat +++ b/examples/chapter12_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 @@ -30,7 +30,7 @@ using ::float_fast16_t; using ::float_least16_t; - static_assert( (std::numeric_limits::is_iec559 == true) + static_assert( std::numeric_limits::is_iec559 && (std::numeric_limits::radix == 2) && (std::numeric_limits::digits == 11) && (std::numeric_limits::max_exponent == 16), @@ -42,7 +42,7 @@ using ::float_fast32_t; using ::float_least32_t; - static_assert( (std::numeric_limits::is_iec559 == true) + static_assert( std::numeric_limits::is_iec559 && (std::numeric_limits::radix == 2) && (std::numeric_limits::digits == 24) && (std::numeric_limits::max_exponent == 128), @@ -54,7 +54,7 @@ using ::float_fast64_t; using ::float_least64_t; - static_assert( (std::numeric_limits::is_iec559 == true) + static_assert( std::numeric_limits::is_iec559 && (std::numeric_limits::radix == 2) && (std::numeric_limits::digits == 53) && (std::numeric_limits::max_exponent == 1024), @@ -66,7 +66,7 @@ using ::float_fast80_t; using ::float_least80_t; - static_assert( (std::numeric_limits::is_iec559 == true) + static_assert( std::numeric_limits::is_iec559 && (std::numeric_limits::radix == 2) && (std::numeric_limits::digits == 64) && (std::numeric_limits::max_exponent == 16384), @@ -78,7 +78,7 @@ using ::float_fast128_t; using ::float_least128_t; - static_assert( (std::numeric_limits::is_iec559 == true) + static_assert( std::numeric_limits::is_iec559 && (std::numeric_limits::radix == 2) && (std::numeric_limits::digits == 113) && (std::numeric_limits::max_exponent == 16384), diff --git a/examples/chapter12_04/src/util/memory/util_factory.h b/examples/chapter12_04/src/util/memory/util_factory.h index 16a19b2bf..782475ea5 100644 --- a/examples/chapter12_04/src/util/memory/util_factory.h +++ b/examples/chapter12_04/src/util/memory/util_factory.h @@ -1,71 +1,81 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. +// Copyright Christopher Kormanyos 2007 - 2025. // 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_FACTORY_2012_02_19_H_ - #define _UTIL_FACTORY_2012_02_19_H_ +#ifndef UTIL_FACTORY_2012_02_19_H + #define UTIL_FACTORY_2012_02_19_H + #include + #include #include - #include namespace util { - class factory_product : private util::noncopyable + class factory_product { public: virtual ~factory_product() { } - virtual void init() = 0; + virtual auto init() -> void = 0; protected: factory_product() { } }; template > + typename AllocatorType = std::allocator> class factory { public: - typedef T value_type; - typedef T* pointer_type; - typedef alloc allocator_type; + using value_type = T; + using pointer_type = T*; + using allocator_type = AllocatorType; - static pointer_type make() + static auto make() -> pointer_type { pointer_type p = new(allocate()) value_type(); + static_cast(p)->init(); + return p; } template - static pointer_type make(parameters... params) + static auto make(parameters... params) -> pointer_type { pointer_type p = new(allocate()) value_type(params...); + static_cast(p)->init(); + return p; } private: - static void* allocate() + static auto allocate() -> void* { - return allocator_type().allocate(1U, nullptr); + return allocator_type().allocate( std::size_t { UINT8_C(1) } ); } }; } -#endif // _UTIL_FACTORY_2012_02_19_H_ +#endif // UTIL_FACTORY_2012_02_19_H /* + +// See also link at GodBolt: https://godbolt.org/z/WrTTa8Eq9 + #include +#include + class something : public util::factory_product { public: - something() { } - virtual ~something() { } + something() = default; + virtual ~something() = default; private: virtual void init() { } @@ -74,18 +84,31 @@ class something : public util::factory_product class another : public util::factory_product { public: - another(const int m, const int n) : my_m(m), - my_n(n) { } + explicit another(const int m = 0, const int n = 0) + : my_m(m), + my_n(n) { } + + ~another() override = default; - virtual ~another() { } + auto get_m() const -> int { return my_m; } + auto get_n() const -> int { return my_n; } private: - const int my_m; - const int my_n; + const int my_m { }; + const int my_n { }; - virtual void init() { } + auto init() -> void override { } }; -something* p_something = util::factory::make(); -another* p_another = util::factory::make(123, 456); +auto main() -> int +{ + something* p_something = util::factory::make(); + another* p_another = util::factory::make(123, 456); + + std::cout << p_another->get_n() << '\n'; + std::cout << p_another->get_m() << std::endl; + + delete p_something; + delete p_another; +} */ diff --git a/examples/chapter12_04/src/util/memory/util_placed_pointer.h b/examples/chapter12_04/src/util/memory/util_placed_pointer.h index b1274cfc6..bc933ca3b 100644 --- a/examples/chapter12_04/src/util/memory/util_placed_pointer.h +++ b/examples/chapter12_04/src/util/memory/util_placed_pointer.h @@ -1,15 +1,16 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef _UTIL_PLACED_PTR_2010_02_23_H_ - #define _UTIL_PLACED_PTR_2010_02_23_H_ +#ifndef UTIL_PLACED_PTR_2010_02_23_H_ + #define UTIL_PLACED_PTR_2010_02_23_H_ #include #include + #include namespace util @@ -50,4 +51,4 @@ }; } -#endif // _UTIL_PLACED_PTR_2010_02_23_H_ +#endif // UTIL_PLACED_PTR_2010_02_23_H_ diff --git a/examples/chapter12_04/src/util/memory/util_ring_allocator.h b/examples/chapter12_04/src/util/memory/util_ring_allocator.h index 68ac2e0a2..7a3a48ef1 100644 --- a/examples/chapter12_04/src/util/memory/util_ring_allocator.h +++ b/examples/chapter12_04/src/util/memory/util_ring_allocator.h @@ -1,256 +1,170 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2015. +// 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_RING_ALLOCATOR_2010_02_23_H_ - #define _UTIL_RING_ALLOCATOR_2010_02_23_H_ +#ifndef UTIL_RING_ALLOCATOR_2010_02_23_H + #define UTIL_RING_ALLOCATOR_2010_02_23_H + + #include #include #include #include - #include - namespace util { class ring_allocator_base { public: - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; - virtual ~ring_allocator_base(); + virtual ~ring_allocator_base() = default; protected: - ring_allocator_base() throw() { } - - ring_allocator_base(const ring_allocator_base&) throw() { } + ring_allocator_base() noexcept = default; - // The ring allocator's default buffer size. - static const size_type buffer_size = 64U; + ring_allocator_base(const ring_allocator_base&) noexcept = default; // The ring allocator's buffer type. struct buffer_type { - std::uint8_t data[buffer_size]; + static constexpr size_type size = 64U; + + std::uint8_t data[size]; + + buffer_type() noexcept : data() { } }; // The ring allocator's memory allocation. - template - static void* do_allocate(const size_type size) + template + static auto do_allocate(size_type chunk_size) -> void* { ALIGNAS(16) static buffer_type buffer; + static std::uint8_t* get_ptr = buffer.data; // Get the newly allocated pointer. std::uint8_t* p = get_ptr; // 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; + // Be sure to handle the buffer alignment. + + const std::uint_fast8_t misaligned_amount(chunk_size % buffer_alignment); + + if(misaligned_amount != UINT8_C(0)) + { + chunk_size += size_type(buffer_alignment - misaligned_amount); + } - get_ptr += buffer_increment; + get_ptr += chunk_size; // Does this attempted allocation overflow the capacity of the buffer? - const bool is_overflow = (get_ptr >= (buffer.data + buffer_size)); + const bool is_overflow = (get_ptr >= (buffer.data + buffer_type::size)); if(is_overflow) { // The buffer has overflowed. - // Check if the requested size fits in the buffer. - if(buffer_increment <= buffer_size) - { - // The requested size fits in the buffer. - - // Reset the allocated pointer to the bottom of the buffer - // and increment the next get-pointer. - p = buffer.data; - get_ptr = buffer.data + buffer_increment; - } - else - { - // The requested size exceeds the capacity of the buffer. - - // Set the return value of the failed allocation to nullptr - // and reset the get-pointer to its value before the allocation - // attempt. - p = nullptr; - get_ptr = get_ptr - buffer_increment; - } + // Reset the allocated pointer to the bottom of the buffer + // and increment the next get-pointer. + p = &buffer.data[0U]; + get_ptr = &buffer.data[chunk_size]; } return static_cast(p); } - - private: - ring_allocator_base& operator=(const ring_allocator_base&); }; - ring_allocator_base::~ring_allocator_base() { } - // Global comparison operators (required by the standard). - inline bool operator==(const ring_allocator_base&, - const ring_allocator_base&) throw() + inline auto operator==(const ring_allocator_base&, + const ring_allocator_base&) noexcept -> bool { return true; } - inline bool operator!=(const ring_allocator_base&, - const ring_allocator_base&) throw() + inline auto operator!=(const ring_allocator_base&, + const ring_allocator_base&) noexcept -> bool { return false; } template + const std::uint_fast8_t buffer_alignment = UINT8_C(16)> class ring_allocator; - template - class ring_allocator : public ring_allocator_base + template + class ring_allocator : public ring_allocator_base { public: - typedef void value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; + using value_type = void; + using pointer = value_type*; + using const_pointer = const value_type*; template - struct rebind { typedef ring_allocator other; }; + struct rebind + { + using other = ring_allocator; + }; }; template + const std::uint_fast8_t buffer_alignment> class ring_allocator : public ring_allocator_base { public: - static_assert(sizeof(T) <= buffer_size, + static_assert(sizeof(T) <= buffer_type::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; - typedef value_type& reference; - typedef const value_type& const_reference; + using value_type = T; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; - ring_allocator() throw() { } + ring_allocator() noexcept = default; - ring_allocator(const ring_allocator&) throw() : ring_allocator_base(ring_allocator()) { } + ring_allocator(const ring_allocator&) noexcept : ring_allocator_base(ring_allocator()) { } template - ring_allocator(const ring_allocator&) throw() { } + ring_allocator(const ring_allocator&) noexcept { } template - struct rebind { typedef ring_allocator other; }; + struct rebind + { + using other = ring_allocator; + }; - size_type max_size() const throw() + auto max_size() const noexcept -> size_type { - return buffer_size / sizeof(value_type); + return buffer_type::size / sizeof(value_type); } - pointer address( reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } + auto address( reference x) const -> pointer { return &x; } + auto address(const_reference x) const -> const_pointer { return &x; } - pointer allocate(size_type count, - typename ring_allocator::const_pointer = nullptr) + auto allocate(size_type count, + typename ring_allocator::const_pointer = nullptr) -> pointer { 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); } - void construct(pointer p, const value_type& x) + auto construct(pointer p, const value_type& x) noexcept -> void { new(static_cast(p)) value_type(x); } - void destroy(pointer p) { p->~value_type(); } + auto destroy(pointer p) noexcept -> void { p->~value_type(); } - void deallocate(pointer, size_type) { } + auto deallocate(pointer, size_type) noexcept -> void { } }; } -#endif // _UTIL_RING_ALLOCATOR_2010_02_23_H_ - -/* -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. -// 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) -// - -#if defined(_MSC_VER) -#include -#endif -#include -#include -#include -#include -#include -#include - -namespace app -{ - namespace led - { - void task_init(); - void task_func(); - } -} - -namespace -{ - typedef util::timer timer_type; - - timer_type app_led_timer(timer_type::seconds(1U)); -} - -void app::led::task_init() -{ - mcal::led::led0.toggle(); -} - -std::uint8_t counter; - -typedef util::ring_allocator allocator_type; -typedef std::vector vector_type; - -vector_type v; - -void app::led::task_func() -{ - if(app_led_timer.timeout()) - { - v.clear(); - - v.push_back(counter + UINT8_C(0)); - v.push_back(counter + UINT8_C(1)); - v.push_back(counter + UINT8_C(2)); - - const bool vector_size_is_ok = (v.size() == vector_type::size_type(3U)); - const bool vector_content_is_ok = (std::accumulate(v.cbegin(), v.cend(), std::uint8_t(0U)) == std::uint8_t(std::uint8_t(counter * UINT8_C(3)) + UINT8_C(3))); - - counter += std::uint8_t(v.size()); - - if(vector_size_is_ok && vector_content_is_ok) - { - app_led_timer.start_interval(timer_type::seconds(1U)); - - mcal::led::led0.toggle(); - - #if defined(_MSC_VER) - std::cout << unsigned(counter) << std::endl; - #endif - } - } -} -*/ +#endif // UTIL_RING_ALLOCATOR_2010_02_23_H diff --git a/examples/chapter12_04/src/util/memory/util_static_allocator.h b/examples/chapter12_04/src/util/memory/util_static_allocator.h index f4d492443..62b83e148 100644 --- a/examples/chapter12_04/src/util/memory/util_static_allocator.h +++ b/examples/chapter12_04/src/util/memory/util_static_allocator.h @@ -1,16 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2015. +// 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) // -#ifndef _UTIL_STATIC_ALLOCATOR_2010_02_23_H_ - #define _UTIL_STATIC_ALLOCATOR_2010_02_23_H_ +#ifndef UTIL_STATIC_ALLOCATOR_2010_02_23_H_ + #define UTIL_STATIC_ALLOCATOR_2010_02_23_H_ #include #include #include + #include namespace util @@ -20,135 +21,142 @@ public: typedef std::size_t size_type; - virtual ~static_allocator_base(); + virtual ~static_allocator_base() = default; protected: - static_allocator_base() throw() { } - - static_allocator_base(const static_allocator_base&) throw() { } + static_allocator_base() noexcept = default; - // The static allocator's default buffer size. - static const size_type buffer_size = 32U; + static_allocator_base(const static_allocator_base&) noexcept = default; // The static allocator's buffer type. struct buffer_type { - std::uint8_t data[buffer_size]; + static constexpr size_type size = 640U; + + std::uint8_t data[size]; + + buffer_type() noexcept : data() { } }; // The static allocator's memory allocation. - template - static void* do_allocate(const size_type size, + template + static void* do_allocate(size_type chunk_size, size_type& remaining, bool& is_overflow) { ALIGNAS(16) static buffer_type buffer; + static std::uint8_t* get_ptr = buffer.data; // Get the newly allocated pointer. std::uint8_t* p = get_ptr; // 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; + // Be sure to handle the buffer alignment. + + const std::uint_fast8_t misaligned_amount(chunk_size % buffer_alignment); - get_ptr += buffer_increment; + if(misaligned_amount != UINT8_C(0)) + { + chunk_size += size_type(buffer_alignment - misaligned_amount); + } + + get_ptr += chunk_size; // Does this attempted allocation overflow the capacity of the buffer? - is_overflow = (get_ptr >= (buffer.data + buffer_size)); + is_overflow = (get_ptr >= (buffer.data + buffer_type::size)); if(is_overflow) { - // The requested size exceeds the capacity of the buffer. - // In this design, however, there is no sensible error reaction. - - // Set the return value of the failed allocation to nullptr - // and reset the get-pointer to its value before the allocation - // attempt. - p = nullptr; - get_ptr = get_ptr - buffer_increment; + // The buffer has overflowed. + + // Reset the allocated pointer to the bottom of the buffer + // and increment the next get-pointer, even though this is + // the wrong behavior. + p = &buffer.data[0U]; + get_ptr = &buffer.data[chunk_size]; + remaining = 0U; + } + else + { + // Calculate the remaining memory in the buffer based on + // the value of the newly calculated get-pointer. + remaining = size_type(&buffer.data[buffer_type::size] - get_ptr); } - - // Calculate the remaining memory in the buffer based on - // the value of the newly calculated get-pointer. - remaining = size_type(&buffer.data[buffer_size] - get_ptr); return static_cast(p); } - - private: - static_allocator_base& operator=(const static_allocator_base&); }; - static_allocator_base::~static_allocator_base() { } - // Global comparison operators (required by the standard). inline bool operator==(const static_allocator_base&, - const static_allocator_base&) throw() + const static_allocator_base&) noexcept { return true; } inline bool operator!=(const static_allocator_base&, - const static_allocator_base&) throw() + const static_allocator_base&) noexcept { return false; } template + const std::uint_fast8_t buffer_alignment = UINT8_C(16)> class static_allocator; - template - class static_allocator : public static_allocator_base + template + class static_allocator : public static_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 void value_type; typedef value_type* pointer; typedef const value_type* const_pointer; template - struct rebind { typedef static_allocator other; }; + struct rebind + { + using other = static_allocator; + }; }; template + const std::uint_fast8_t buffer_alignment> class static_allocator : public static_allocator_base { public: + static_assert(sizeof(T) <= buffer_type::size, + "The size of the allocation object can not exceed the buffer size."); + typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; - typedef std::ptrdiff_t difference_type; - static_allocator() throw() { } + static_allocator() noexcept = default; - static_allocator(const static_allocator&) throw() : static_allocator_base(static_allocator()) { } + static_allocator(const static_allocator&) noexcept : static_allocator_base(static_allocator()) { } template - static_allocator(const static_allocator&) throw() { } + static_allocator(const static_allocator&) noexcept { } template - struct rebind { typedef static_allocator other; }; + struct rebind + { + using other = static_allocator; + }; - size_type max_size() const throw() + size_type max_size() const noexcept { size_type remaining; bool is_overflow; - void* p = do_allocate(size_type(0U), - remaining, - is_overflow); + void* p = do_allocate(size_type(0U), + remaining, + is_overflow); + static_cast(p); static_cast(is_overflow); return remaining / sizeof(value_type); @@ -158,16 +166,16 @@ const_pointer address(const_reference x) const { return &x; } pointer allocate(size_type count, - typename static_allocator::const_pointer = nullptr) + typename static_allocator::const_pointer = nullptr) { const size_type chunk_size = count * sizeof(value_type); size_type remaining; bool is_overflow; - void* p = do_allocate(chunk_size, - remaining, - is_overflow); + void* p = do_allocate(chunk_size, + remaining, + is_overflow); static_cast(remaining); static_cast(is_overflow); @@ -175,15 +183,15 @@ return static_cast(p); } - void construct(pointer p, const value_type& x) + void construct(pointer p, const value_type& x) noexcept { new(static_cast(p)) value_type(x); } - void destroy(pointer p) { p->~value_type(); } + void destroy(pointer p) noexcept { p->~value_type(); } - void deallocate(pointer, size_type) { } + void deallocate(pointer, size_type) noexcept { } }; } -#endif // _UTIL_STATIC_ALLOCATOR_2010_02_23_H_ +#endif // UTIL_STATIC_ALLOCATOR_2010_02_23_H_ diff --git a/examples/chapter12_04/src/util/utility/util_alignas.h b/examples/chapter12_04/src/util/utility/util_alignas.h index 0cd13a5a7..c933895fc 100644 --- a/examples/chapter12_04/src/util/utility/util_alignas.h +++ b/examples/chapter12_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/chapter12_04/src/util/utility/util_attribute.h b/examples/chapter12_04/src/util/utility/util_attribute.h new file mode 100644 index 000000000..34175b3be --- /dev/null +++ b/examples/chapter12_04/src/util/utility/util_attribute.h @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2025. +// 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_ATTRIBUTE_2025_08_09_H + #define UTIL_ATTRIBUTE_2025_08_09_H + + #if defined(ATTRIBUTE) + #undef ATTRIBUTE + #endif + + #if defined(_MSC_VER) + #define ATTRIBUTE(...) + #else + #define ATTRIBUTE(...) __attribute__((__VA_ARGS__)) + #endif + +#endif // UTIL_ATTRIBUTE_2025_08_09_H diff --git a/examples/chapter12_04/src/util/utility/util_baselexical_cast.h b/examples/chapter12_04/src/util/utility/util_baselexical_cast.h new file mode 100644 index 000000000..16f64a655 --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/utility/util_bit_mask.h b/examples/chapter12_04/src/util/utility/util_bit_mask.h index 38994d994..446bf4a8e 100644 --- a/examples/chapter12_04/src/util/utility/util_bit_mask.h +++ b/examples/chapter12_04/src/util/utility/util_bit_mask.h @@ -1,74 +1,100 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef UTIL_BIT_MASK_2010_06_13_H_ - #define UTIL_BIT_MASK_2010_06_13_H_ +#ifndef UTIL_BIT_MASK_2010_06_13_H + #define UTIL_BIT_MASK_2010_06_13_H #include namespace util { template + const unsigned BitPos, + const unsigned BitCnt> struct bit_mask_multi_value { + private: + // This bit mask contains bit_cnt continuous bits starting at bit_pos. + + static constexpr unsigned bit_pos = BitPos; + static constexpr unsigned bit_cnt = BitCnt; + // Ensure that the data_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the data_type of the bit_mask template must be an integer type"); // Ensure that the data_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the data_type of the bit_mask template must be unsigned"); // Ensure that the requested bit mask is in range. - static_assert((bit_pos + bit_cnt) <= unsigned(std::numeric_limits::digits), + static_assert((bit_pos + bit_cnt) <= unsigned { std::numeric_limits::digits }, "the requested bit_mask value exceeds the maximum value of the data_type"); - static const data_type value = static_cast(static_cast(static_cast(~static_cast(0U)) >> (std::numeric_limits::digits - (bit_cnt + 1U))) << bit_pos); + public: + static constexpr data_type value = + static_cast + ( + static_cast + ( + static_cast(~static_cast(0U)) >> static_cast(static_cast(std::numeric_limits::digits) - (bit_cnt + 1U)) + ) << bit_pos + ); }; template - struct bit_mask_multi_value + const unsigned BitPos> + struct bit_mask_multi_value { + private: + // This bit mask contains one bit at bit_pos. + + static constexpr unsigned bit_pos = BitPos; + // Ensure that the data_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the data_type of the bit_mask template must be an integer type"); // Ensure that the data_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the data_type of the bit_mask template must be unsigned"); // Ensure that the requested bit mask is in range. static_assert((bit_pos + 1) <= unsigned(std::numeric_limits::digits), "the requested bit_mask value exceeds the maximum value of the data_type"); - static const data_type value = static_cast(static_cast(1U) << bit_pos); + public: + static constexpr data_type value = static_cast(static_cast(1U) << bit_pos); }; template + const unsigned BitPos> struct bit_mask_single_value { + private: + // This bit mask contains one bit at bit_pos. + + static constexpr unsigned bit_pos = BitPos; + // Ensure that the data_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the data_type of the bit_mask template must be an integer type"); // Ensure that the data_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the data_type of the bit_mask template must be unsigned"); // Ensure that the requested bit mask is in range. static_assert((bit_pos + 1) <= unsigned(std::numeric_limits::digits), "the requested bit_mask value exceeds the maximum value of the data_type"); + public: static const data_type value = static_cast(static_cast(1U) << bit_pos); }; } -#endif // UTIL_BIT_MASK_2010_06_13_H_ +#endif // UTIL_BIT_MASK_2010_06_13_H diff --git a/examples/chapter12_04/src/util/utility/util_circular_buffer.h b/examples/chapter12_04/src/util/utility/util_circular_buffer.h deleted file mode 100644 index e00c7bcda..000000000 --- a/examples/chapter12_04/src/util/utility/util_circular_buffer.h +++ /dev/null @@ -1,298 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 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) -// - -#ifndef UTIL_CIRCULAR_BUFFER_2007_11_22_H_ - #define UTIL_CIRCULAR_BUFFER_2007_11_22_H_ - - #include - #include - - namespace util - { - // TBD: We need to define a custom iterator class in order - // to provide proper iterator support for circular_buffer. - - template - class circular_buffer - { - public: - typedef T value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef std::size_t size_type; - typedef value_type& reference; - typedef const value_type& const_reference; - - circular_buffer( - const T& value = value_type(), - const size_type count = size_type(0U)) - : in_ptr (buffer), - out_ptr(buffer) - { - const size_type the_count = - (std::min)(N, count); - - std::fill(in_ptr, - in_ptr + the_count, - value); - - in_ptr += the_count; - } - - circular_buffer(const circular_buffer& other) - : in_ptr (other.in_ptr), - out_ptr(other.out_ptr) - { - std::copy(other.buffer, - other.buffer + N, - buffer); - } - - circular_buffer& operator=( - const circular_buffer& other) - { - if(this != &other) - { - in_ptr (other.in_ptr); - out_ptr (other.out_ptr); - std::copy(other.buffer, - other.buffer + N, - buffer); - } - - return *this; - } - - size_type capacity() const { return N; } - - bool empty() const - { - return (in_ptr == out_ptr); - } - - size_type size() const - { - const bool is_wrap = (in_ptr < out_ptr); - - return size_type((is_wrap == false) - ? size_type(in_ptr - out_ptr) - : N - size_type(out_ptr - in_ptr)); - } - - void clear() - { - in_ptr = buffer; - out_ptr = buffer; - } - - void in(const value_type value) - { - if(in_ptr >= (buffer + N)) - { - in_ptr = buffer; - } - - *in_ptr = value; - - ++in_ptr; - } - - value_type out() - { - if(out_ptr >= (buffer + N)) - { - out_ptr = buffer; - } - - const value_type value = *out_ptr; - - ++out_ptr; - - return value; - } - - reference front() - { - return ((out_ptr >= (buffer + N)) - ? buffer[N - 1U] - : *out_ptr); - } - - const_reference front() const - { - return ((out_ptr >= (buffer + N)) - ? buffer[N - 1U] - : *out_ptr); - } - - reference back() - { - return ((in_ptr >= (buffer + N)) - ? buffer[N - 1U] - : *in_ptr); - } - - const_reference back() const - { - return ((in_ptr >= (buffer + N)) - ? buffer[N - 1U] - : *in_ptr); - } - - private: - value_type buffer[N]; - pointer in_ptr; - pointer out_ptr; - }; - - template - class circular_buffer - { - public: - typedef T value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef std::size_t size_type; - typedef value_type& reference; - typedef const value_type& const_reference; - - circular_buffer( - const T& value = value_type(), - const size_type count = size_type(0U)) - { - if(count > size_type(0U)) - { - data = value; - has_data = true; - } - else - { - data = value_type(); - - has_data = false; - } - } - - circular_buffer(const circular_buffer& other) - : data (other.data), - has_data(other.has_data) - { - } - - circular_buffer& operator=( - const circular_buffer& other) - { - if(this != &other) - { - data = other.data; - - has_data = other.has_data; - } - - return *this; - } - - size_type capacity() const { return size_type(1U); } - - bool empty() const - { - return (has_data == false); - } - - size_type size() const - { - return size_type(has_data ? 1U : 0U); - } - - void clear() - { - has_data = false; - } - - void in(const value_type value) - { - has_data = true; - - data = value; - } - - value_type out() - { - has_data = false; - - return data; - } - - reference front() - { - return data; - } - - const_reference front() const - { - return data; - } - - reference back() - { - return data; - } - - const_reference back() const - { - return data; - } - - private: - value_type data; - bool has_data; - }; - } - - /* - #include - - void do_something(); - - void do_something() - { - typedef util::circular_buffer circular_buffer_type; - - circular_buffer_type data; - circular_buffer_type::size_type size; - circular_buffer_type::value_type value; - - data.in(1U); - size = data.size(); - data.in(2U); - size = data.size(); - data.in(3U); - size = data.size(); - - value = data.out(); - size = data.size(); - value = data.out(); - size = data.size(); - value = data.out(); - size = data.size(); - - data.in(101U); - size = data.size(); - data.in(102U); - size = data.size(); - - value = data.out(); - size = data.size(); - value = data.out(); - size = data.size(); - - volatile unsigned debug = 0U; - } - */ - -#endif // UTIL_CIRCULAR_BUFFER_2007_11_22_H_ diff --git a/examples/chapter12_04/src/util/utility/util_communication.h b/examples/chapter12_04/src/util/utility/util_communication.h index 9645793d1..e8981ff55 100644 --- a/examples/chapter12_04/src/util/utility/util_communication.h +++ b/examples/chapter12_04/src/util/utility/util_communication.h @@ -1,112 +1,127 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2015. +// 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_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 #include - #include namespace util { - class communication_base + class communication_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) { public: - typedef std::size_t size_type; + virtual ~communication_base() = default; + + virtual auto recv(std::uint8_t& byte_to_recv) -> bool = 0; - virtual ~communication_base() { } + virtual auto select() -> void = 0; + virtual auto deselect() -> void = 0; - virtual bool send (const std::uint8_t byte_to_send) = 0; - virtual bool recv (std::uint8_t& byte_to_recv) = 0; - virtual size_type recv_ready() const = 0; - virtual bool idle () const = 0; + 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; + bool send_result { true }; // NOLINT(altera-id-dependent-backward-branch) - while(first != last) + while((first != last) && send_result) // NOLINT(altera-id-dependent-backward-branch) { - typedef typename - std::iterator_traits::value_type - send_value_type; - - const send_value_type value(*first); + using send_value_type = typename std::iterator_traits::value_type; - send_result &= send(std::uint8_t(value)); - - ++first; + send_result = (this->send(static_cast(send_value_type(*first++))) && send_result); } return send_result; } - template - bool recv_n(recv_iterator_type first, - size_type count) - { - const size_type count_to_recv = (std::min)(count, recv_ready()); + virtual auto send(const std::uint8_t byte_to_send) noexcept -> bool = 0; - recv_iterator_type last = first + count_to_recv; + protected: + communication_base() = default; - bool recv_result = true; + private: + template + friend class communication_multi_channel; + }; - while(first != last) - { - std::uint8_t byte_to_recv; + class communication_buffer_depth_one_byte : public communication_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + public: + using buffer_type = std::uint8_t; - recv_result &= recv(byte_to_recv); + ~communication_buffer_depth_one_byte() override = default; - typedef typename - std::iterator_traits::value_type - recv_value_type; + protected: + buffer_type recv_buffer { }; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes) - *first = recv_value_type(byte_to_recv); + communication_buffer_depth_one_byte() = default; - ++first; - } + private: + auto recv(std::uint8_t& byte_to_recv) -> bool override + { + byte_to_recv = recv_buffer; - return recv_result; + return true; } + }; + + template + class communication_multi_channel : public communication_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + { + private: + static constexpr std::size_t channel_count = ChannelCount; + + public: + communication_multi_channel() = delete; - template - bool recv_n(recv_iterator_type first, recv_iterator_type last) + explicit communication_multi_channel(communication_base** p_com_channels) { - const size_type count_to_recv = size_type(std::distance(first, last)); + std::copy(p_com_channels, p_com_channels + channel_count, my_com_channels.begin()); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + + ~communication_multi_channel() override = default; - return recv_n(first, count_to_recv); + auto send(const std::uint8_t byte_to_send) noexcept -> bool override + { + return my_com_channels[my_index]->send(byte_to_send); } - protected: - communication_base() { } - }; + auto recv(std::uint8_t& byte_to_recv) -> bool override + { + return my_com_channels[my_index]->recv(byte_to_recv); + } - template - class communication : public communication_base - { - public: - typedef util::circular_buffer buffer_type; + auto select() -> void override { my_com_channels[my_index]->select(); } + auto deselect() -> void override { my_com_channels[my_index]->deselect(); } - virtual ~communication(); + auto select_channel(const std::size_t index) -> bool override + { + const bool select_channel_is_ok = (index < channel_count); - protected: - communication() : send_buffer(), - recv_buffer() { } + if(select_channel_is_ok) + { + my_index = index; + } - buffer_type send_buffer; - buffer_type recv_buffer; - }; + return select_channel_is_ok; + } - template - communication::~communication() { } - } + private: + std::array my_com_channels { }; // NOLINT(readability-identifier-naming) + std::size_t my_index { }; // NOLINT(readability-identifier-naming) + + static_assert(channel_count > 0U, "Error channel_count must be greater than zero."); + }; + } // namespace util -#endif // UTIL_COMMUNICATION_2012_05_31_H_ +#endif // UTIL_COMMUNICATION_2012_05_31_H diff --git a/examples/chapter12_04/src/util/utility/util_constexpr_algorithm_unsafe.h b/examples/chapter12_04/src/util/utility/util_constexpr_algorithm_unsafe.h new file mode 100644 index 000000000..529664934 --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/utility/util_constexpr_cmath_unsafe.h b/examples/chapter12_04/src/util/utility/util_constexpr_cmath_unsafe.h new file mode 100644 index 000000000..3223f52f9 --- /dev/null +++ b/examples/chapter12_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/chapter12_04/src/util/utility/util_countof.h b/examples/chapter12_04/src/util/utility/util_countof.h index d3a144dd4..1524259e0 100644 --- a/examples/chapter12_04/src/util/utility/util_countof.h +++ b/examples/chapter12_04/src/util/utility/util_countof.h @@ -1,46 +1,26 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014. +// Copyright Christopher Kormanyos 2014 - 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_COUNTOF_2014_09_29_H_ - #define UTIL_COUNTOF_2014_09_29_H_ +#ifndef UTIL_COUNTOF_2014_09_29_H + #define UTIL_COUNTOF_2014_09_29_H #include namespace util { - #if defined(__GNUC__) + template + inline constexpr auto countof(T(&c_array)[N]) -> std::size_t + { + static_assert(N > std::size_t(0U), "Error: util::countof requires an array size larger than zero."); - template - inline constexpr std::size_t countof(T(&c_array)[N]) - { - static_assert(N > std::size_t(0U), - "Sorry, util::countof requires an array size larger than zero."); + static_assert(sizeof(c_array[0U]) > std::size_t(0U), "Error: util::countof requires an element size larger than zero."); - static_assert(sizeof(c_array[0U]) > std::size_t(0U), - "Sorry, util::countof requires an element size larger than zero."); - - return sizeof(c_array) / sizeof(c_array[0U]); - } - - #else - - template - inline std::size_t countof(T(&c_array)[N]) - { - static_assert(N > std::size_t(0U), - "Sorry, util::countof requires an array size larger than zero."); - - static_assert(sizeof(c_array[0U]) > std::size_t(0U), - "Sorry, util::countof requires an element size larger than zero."); - - return sizeof(c_array) / sizeof(c_array[0U]); - } - - #endif + return sizeof(c_array) / sizeof(c_array[0U]); + } } -#endif // UTIL_COUNTOF_2014_09_29_H_ +#endif // UTIL_COUNTOF_2014_09_29_H diff --git a/examples/chapter12_04/src/util/utility/util_display.h b/examples/chapter12_04/src/util/utility/util_display.h new file mode 100644 index 000000000..b3176185f --- /dev/null +++ b/examples/chapter12_04/src/util/utility/util_display.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2019 - 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_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() -> bool = 0; + + virtual auto write(const char* pstr, + const std::uint_fast8_t length, + const std::uint_fast8_t line_index) -> bool = 0; + + virtual auto clear_line(const unsigned = static_cast(UINT8_C(0))) -> bool = 0; + + virtual auto set_line_index(const std::uint8_t) -> bool = 0; + + protected: + display_multiline_base() = default; + + using timer_type = util::timer; + + static auto blocking_delay(const typename timer_type::tick_type blocking_delay_value) -> void + { + timer_type::blocking_delay(blocking_delay_value); + } + }; + + } // namespace util + +#endif // UTIL_DISPLAY_2023_06_09_H diff --git a/examples/chapter12_04/src/util/utility/util_dynamic_array.h b/examples/chapter12_04/src/util/utility/util_dynamic_array.h index dd87a3072..9c9f18b97 100644 --- a/examples/chapter12_04/src/util/utility/util_dynamic_array.h +++ b/examples/chapter12_04/src/util/utility/util_dynamic_array.h @@ -1,278 +1,311 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +/////////////////////////////////////////////////////////////////////////////// +// 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() : N (0U), - elems(allocator_type().allocate(1U)) + if(elem_count > static_cast(UINT8_C(0))) { - elems[0U] = value_type(); - } + allocator_type my_a(a); - dynamic_array(size_type count) : N (count), - elems(allocator_type().allocate((std::max)(size_type(1U), N))) - { - if(N > size_type(0U)) - { - std::fill_n(begin(), N, value_type()); - } - else - { - elems[0U] = value_type(); - } - } + elems = std::allocator_traits::allocate(my_a, elem_count); - dynamic_array(size_type count, - const value_type& v, - const allocator_type& a = allocator_type()) : N (count), - elems(allocator_type(a).allocate((std::max)(size_type(1U), N))) - { - if(N > size_type(0U)) - { - std::fill_n(begin(), N, v); - } - else - { - elems[0U] = value_type(); - } - } + iterator it = begin(); - dynamic_array(const dynamic_array& other) : N (other.size()), - elems(allocator_type().allocate((std::max)(size_type(1U), N))) - { - if(N > size_type(0U)) + while(it != end()) { - std::copy(other.begin(), other.end(), begin()); - } - else - { - elems[0U] = value_type(); - } - } + std::allocator_traits::construct(my_a, it, v); - template - dynamic_array(input_iterator first, - input_iterator last, - const allocator_type& a = allocator_type()) : N (static_cast(std::distance(first, last))), - elems(allocator_type(a).allocate((std::max)(size_type(1U), N))) - { - if(N > size_type(0U)) - { - std::copy(first, last, begin()); - } - else - { - elems[0U] = value_type(); + ++it; } } + } - dynamic_array(std::initializer_list lst, - const allocator_type& a = allocator_type()) : N (lst.size()), - elems(allocator_type(a).allocate((std::max)(size_type(1U), N))) - { - if(N > size_type(0U)) - { - std::copy(lst.begin(), lst.end(), begin()); - } - else - { - elems[0U] = value_type(); - } - } + constexpr dynamic_array(const dynamic_array& other) + : elem_count(other.size()) + { + allocator_type my_a; - // Destructor. - ~dynamic_array() + if(elem_count > static_cast(UINT8_C(0))) { - // Destroy the elements and deallocate the range. - if(N > size_type(0U)) - { - for(pointer p = elems; p != (elems + size()); ++p) - { - allocator_type().destroy(p); - } - - allocator_type().deallocate(elems, N); - } - else - { - allocator_type().deallocate(elems, size_type(1U)); - } + elems = std::allocator_traits::allocate(my_a, elem_count); } - // Iterator members: - iterator begin () { return elems; } - iterator end () { return elems + N; } - const_iterator begin () const { return elems; } - const_iterator end () const { return elems + N; } - const_iterator cbegin () const { return elems; } - const_iterator cend () const { return elems + N; } - reverse_iterator rbegin () { return reverse_iterator(elems + N); } - reverse_iterator rend () { return reverse_iterator(elems); } - const_reverse_iterator rbegin () const { return const_reverse_iterator(elems + N); } - const_reverse_iterator rend () const { return const_reverse_iterator(elems); } - const_reverse_iterator crbegin() const { return const_reverse_iterator(elems + N); } - const_reverse_iterator crend () const { return const_reverse_iterator(elems); } - - // Size and capacity. - size_type size () const { return N; } - size_type max_size() const { return N; } - bool empty () const { return false; } - - // 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]; } - - reference back() { return ((N > size_type(0U)) ? elems[N - 1U] : elems[0U]); } - const_reference back() const { return ((N > size_type(0U)) ? elems[N - 1U] : elems[0U]); } - - reference at(const size_type i) { return ((i < N) ? elems[i] : elems[0U]); } - const_reference at(const size_type i) const { return ((i < N) ? elems[i] : elems[0U]); } - - // Element manipulation members. - void fill(const value_type& v) { std::fill_n(begin(), N, v); } - - void swap(dynamic_array& other) - { - const size_type count = (std::min)(N, other.size()); + std::copy(other.elems, other.elems + elem_count, elems); + } - std::swap_ranges(begin(), begin() + count, other.begin()); + 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); - if(count < N) - { - std::fill(begin() + count, end(), value_type()); - } + if(elem_count > static_cast(UINT8_C(0))) + { + elems = std::allocator_traits::allocate(my_a, elem_count); } - private: - const size_type N; - pointer elems; - - // dynamic_array can not be copied with operator=(). - dynamic_array& operator=(const dynamic_array&); - }; + std::copy(first, last, elems); + } - template - bool operator==(const dynamic_array& lhs, const dynamic_array& rhs) + constexpr dynamic_array(std::initializer_list lst, + const allocator_type& a = allocator_type()) + : elem_count(lst.size()) { - const bool sizes_are_equal = (lhs.size() == rhs.size()); + allocator_type my_a(a); - typedef typename dynamic_array::size_type size_type; + if(elem_count > static_cast(UINT8_C(0))) + { + elems = std::allocator_traits::allocate(my_a, elem_count); + } - const bool size_of_left_is_zero = (lhs.size() == size_type(0U)); + std::copy(lst.begin(), lst.end(), elems); + } - return (sizes_are_equal && (size_of_left_is_zero || std::equal(lhs.begin(), lhs.end(), rhs.begin()))); + // 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; } - template - bool operator<(const dynamic_array& lhs, const dynamic_array& rhs) + // Destructor. + virtual ~dynamic_array() // LCOV_EXCL_LINE { - typedef typename dynamic_array::size_type size_type; + using local_allocator_traits_type = std::allocator_traits; - const bool size_of_left_is_zero = (lhs.size() == size_type(0U)); + allocator_type my_a; - if(size_of_left_is_zero) - { - const bool size_of_right_is_zero = (rhs.size() == size_type(0U)); + // Destroy the elements and deallocate the range. + local_allocator_traits_type::deallocate(my_a, elems, elem_count); + } - return (size_of_right_is_zero ? false : true); - } - else + // Assignment operator. + constexpr auto operator=(const dynamic_array& other) -> dynamic_array& + { + if(this != &other) { - if(size_of_left_is_zero) - { - const bool size_of_right_is_zero = (rhs.size() == size_type(0U)); + std::copy(other.elems, + other.elems + (std::min)(elem_count, other.elem_count), + elems); + } - return (size_of_right_is_zero == false); - } - else - { - const size_type count = (std::min)(lhs.size(), rhs.size()); + return *this; + } - return std::lexicographical_compare(lhs.begin(), - lhs.begin() + count, - rhs.begin(), - rhs.begin() + count); - } - } + // Move assignment operator. + constexpr auto operator=(dynamic_array&& other) noexcept -> dynamic_array& + { + std::swap(elem_count, other.elem_count); + std::swap(elems, other.elems); + + return *this; } - template - bool operator!=(const dynamic_array& lhs, const dynamic_array& rhs) + // 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 { - return ((lhs == rhs) == false); + std::fill(begin(), begin() + elem_count, v); } - template - bool operator>(const dynamic_array& lhs, const dynamic_array& rhs) + constexpr auto swap(dynamic_array& other) noexcept -> void { - return (rhs < lhs); + if(this != &other) + { + std::swap(elems, other.elems); + std::swap(elem_count, other.elem_count); + } } - template - bool operator>=(const dynamic_array& lhs, const dynamic_array& rhs) + constexpr auto swap(dynamic_array&& other) noexcept -> void { - return ((lhs < rhs) == false); + elems = std::move(other.elems); + elem_count = std::move(other.elem_count); } - template - bool operator<=(const dynamic_array& lhs, const dynamic_array& rhs) + private: + size_type elem_count; // NOLINT(readability-identifier-naming) + pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) + }; + + template + auto operator==(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + bool left_and_right_are_equal = false; + + if(lhs.size() == rhs.size()) { - return ((rhs < lhs) == false); + using size_type = typename dynamic_array::size_type; + + const auto size_of_left_is_zero = (lhs.size() == static_cast(UINT8_C(0))); + + left_and_right_are_equal = + (size_of_left_is_zero || std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin())); } - template - void swap(dynamic_array& x, dynamic_array& y) + return left_and_right_are_equal; + } + + 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) { - x.swap(y); + 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 auto size_of_right_is_zero = (rhs.size() == static_cast(UINT8_C(0))); + + b_result = (!size_of_right_is_zero); + } + else + { + const size_type count = (std::min)(lhs.size(), rhs.size()); + + b_result= std::lexicographical_compare(lhs.cbegin(), + lhs.cbegin() + count, + rhs.cbegin(), + rhs.cbegin() + count); + } + } + + return b_result; } - /* - #include - #include + template + auto operator!=(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (!(lhs == rhs)); + } + + template + auto operator>(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (rhs < lhs); + } + + template + auto operator>=(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (!(lhs < rhs)); + } - typedef util::dynamic_array> dynamic_array_type; + template + auto operator<=(const dynamic_array& lhs, + const dynamic_array& rhs) -> bool + { + return (!(rhs < lhs)); + } - const dynamic_array_type a1( { 1, 2, 3 } ); - const dynamic_array_type a2( { 1, 2, 4 } ); + template + auto swap(dynamic_array& x, + dynamic_array& y) noexcept -> void + { + x.swap(y); + } - const bool b_test = (a1 < a2); - */ + } // namespace util -#endif // UTIL_DYNAMIC_ARRAY_2012_05_16_H_ +#endif // UTIL_DYNAMIC_ARRAY_2012_05_16_H diff --git a/examples/chapter12_04/src/util/utility/util_dynamic_bitset.h b/examples/chapter12_04/src/util/utility/util_dynamic_bitset.h new file mode 100644 index 000000000..684aebaea --- /dev/null +++ b/examples/chapter12_04/src/util/utility/util_dynamic_bitset.h @@ -0,0 +1,58 @@ +#ifndef UTIL_DYNAMIC_BITSET_2018_02_03_H_ + #define UTIL_DYNAMIC_BITSET_2018_02_03_H_ + + #include + #include + #include + + namespace util + { + template> + class dynamic_bitset + { + public: + using allocator_type = alloc; + + static const std::size_t my_elem_count = (my_bit_count / 8U) + (((my_bit_count % 8U) != 0U) ? 1U : 0U); + + dynamic_bitset() : my_memory(allocator_type().allocate(my_elem_count)) + { + std::fill(my_memory, + my_memory + my_elem_count, + UINT8_C(0)); + } + + ~dynamic_bitset() + { + std::allocator_traits::deallocate(allocator_type(), my_memory, my_elem_count); + } + + void set(const std::size_t i) + { + my_memory[i / 8U] |= (UINT8_C(1) << (i % 8U)); + } + + void flip(const std::size_t i) + { + my_memory[i / 8U] ^= (UINT8_C(1) << (i % 8U)); + } + + bool test(const std::size_t i) const + { + const std::uint8_t test_value = (my_memory[i / 8U] & (UINT8_C(1) << (i % 8U))); + + return (test_value != 0U); + } + + static std::size_t size() + { + return my_bit_count; + } + + private: + std::uint8_t* my_memory; + }; + } // namespace util + +#endif // UTIL_DYNAMIC_BITSET_2018_02_03_H_ diff --git a/examples/chapter12_04/src/util/utility/util_linear_interpolate.h b/examples/chapter12_04/src/util/utility/util_linear_interpolate.h index 93061476b..f154433a5 100644 --- a/examples/chapter12_04/src/util/utility/util_linear_interpolate.h +++ b/examples/chapter12_04/src/util/utility/util_linear_interpolate.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef UTIL_LINEAR_INTERPOLATE_2008_11_22_H_ - #define UTIL_LINEAR_INTERPOLATE_2008_11_22_H_ +#ifndef UTIL_LINEAR_INTERPOLATE_2008_11_22_H + #define UTIL_LINEAR_INTERPOLATE_2008_11_22_H #include @@ -15,18 +15,17 @@ template - y_type linear_interpolate(point_iterator pts_begin, - point_iterator pts_end, - const x_type& x, - const y_type& offset) + auto linear_interpolate(point_iterator pts_begin, + point_iterator pts_end, + const x_type& x, + const y_type& offset) -> y_type { if(pts_begin == pts_end) { // There are no data points to interpolate. return y_type(); } - else if( (x <= pts_begin->x) - || ((pts_begin + 1U) == pts_end)) + else if((x <= pts_begin->x) || ((pts_begin + 1U) == pts_end)) { // We are beneath the lower x-range or there // is only one data point to interpolate. @@ -58,4 +57,4 @@ } } -#endif // UTIL_LINEAR_INTERPOLATE_2008_11_22_H_ +#endif // UTIL_LINEAR_INTERPOLATE_2008_11_22_H diff --git a/examples/chapter12_04/src/util/utility/util_narrow_cast.h b/examples/chapter12_04/src/util/utility/util_narrow_cast.h new file mode 100644 index 000000000..6b4416a61 --- /dev/null +++ b/examples/chapter12_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 auto narrow_cast(U&& u) noexcept -> T + { + return static_cast(std::forward(u)); + } + } + +#endif // UTIL_NARROW_CAST_2020_09_24_H diff --git a/examples/chapter12_04/src/util/utility/util_noncopyable.h b/examples/chapter12_04/src/util/utility/util_noncopyable.h index c9d06dee5..8f45b4e99 100644 --- a/examples/chapter12_04/src/util/utility/util_noncopyable.h +++ b/examples/chapter12_04/src/util/utility/util_noncopyable.h @@ -1,46 +1,37 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +// 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: - - #if defined(__GNUC__) - constexpr noncopyable() = default; - ~noncopyable() = default; - #else - noncopyable() {} - ~noncopyable() {} - #endif - - private: - - #if defined(__GNUC__) - // Emphasize: The following members are private. - noncopyable(const noncopyable&) = delete; - noncopyable& operator=(const noncopyable&) = delete; - #else - // Emphasize: The following members are private. - noncopyable(const noncopyable&); - noncopyable& operator=(const noncopyable&); - #endif - }; - } - - typedef my_noncopyable_namespace::noncopyable 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/chapter12_04/src/util/utility/util_nothing.h b/examples/chapter12_04/src/util/utility/util_nothing.h index 5f0f8c5ff..a5ff0c506 100644 --- a/examples/chapter12_04/src/util/utility/util_nothing.h +++ b/examples/chapter12_04/src/util/utility/util_nothing.h @@ -1,30 +1,35 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +// 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_NOTHING_2010_06_13_H_ - #define UTIL_NOTHING_2010_06_13_H_ +#ifndef UTIL_NOTHING_2010_06_13_H + #define UTIL_NOTHING_2010_06_13_H namespace util { // This is a structure that is used to represent *nothing*. struct nothing final { - nothing() { } - nothing(const nothing&) { } - ~nothing() { } - nothing& operator=(const nothing&) { return *this; } + constexpr nothing() = default; + + constexpr nothing(const nothing&) { } + constexpr nothing(nothing&&) noexcept { } + + ~nothing() = default; + + constexpr auto operator=(const nothing&) -> nothing& { return *this; } + constexpr auto operator=(nothing&&) noexcept -> nothing& { return *this; } }; - inline bool operator==(const nothing&, const nothing&) { return true; } - inline bool operator!=(const nothing&, const nothing&) { return false; } - inline bool operator< (const nothing&, const nothing&) { return false; } - inline bool operator<=(const nothing&, const nothing&) { return false; } - inline bool operator> (const nothing&, const nothing&) { return false; } - inline bool operator>=(const nothing&, const nothing&) { return false; } + inline constexpr auto operator==(const nothing&, const nothing&) noexcept -> bool { return true; } + inline constexpr auto operator!=(const nothing&, const nothing&) noexcept -> bool { return false; } + inline constexpr auto operator< (const nothing&, const nothing&) noexcept -> bool { return false; } + inline constexpr auto operator<=(const nothing&, const nothing&) noexcept -> bool { return false; } + inline constexpr auto operator> (const nothing&, const nothing&) noexcept -> bool { return false; } + inline constexpr auto operator>=(const nothing&, const nothing&) noexcept -> bool { return false; } } -#endif // UTIL_NOTHING_2010_06_13_H_ +#endif // UTIL_NOTHING_2010_06_13_H diff --git a/examples/chapter12_04/src/util/utility/util_null_ptr_workaround.h b/examples/chapter12_04/src/util/utility/util_null_ptr_workaround.h deleted file mode 100644 index 87d8b7d8f..000000000 --- a/examples/chapter12_04/src/util/utility/util_null_ptr_workaround.h +++ /dev/null @@ -1,40 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2013. -// 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_NULL_PTR_WORKAROUND_2010_12_06_H_ - #define UTIL_NULL_PTR_WORKAROUND_2010_12_06_H_ - - // Provide a nullptr workaround for C++ compilers not yet supporting it. - - class nullptr_t - { - public: - template - operator T*() const { return static_cast(0U); } - - template - operator T C::*() const { return static_cast(0U); } - - private: - void operator&() const; - }; - - template inline bool operator==(const T* p, const nullptr_t&) { return (static_cast(0U) == p); } - template inline bool operator!=(const T* p, const nullptr_t&) { return (static_cast(0U) != p); } - - template inline bool operator==(T* p, const nullptr_t&) { return (static_cast(0U) == p); } - template inline bool operator!=(T* p, const nullptr_t&) { return (static_cast(0U) != p); } - - template inline bool operator==(const nullptr_t&, const T* p) { return (static_cast(0U) == p); } - template inline bool operator!=(const nullptr_t&, const T* p) { return (static_cast(0U) != p); } - - template inline bool operator==(const nullptr_t&, T* p) { return (static_cast(0U) == p); } - template inline bool operator!=(const nullptr_t&, T* p) { return (static_cast(0U) != p); } - - const nullptr_t nullptr = { }; - -#endif // UTIL_NULL_PTR_WORKAROUND_2010_12_06_H_ diff --git a/examples/chapter12_04/src/util/utility/util_point.h b/examples/chapter12_04/src/util/utility/util_point.h index 85cc2d65a..992fcecd0 100644 --- a/examples/chapter12_04/src/util/utility/util_point.h +++ b/examples/chapter12_04/src/util/utility/util_point.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +// 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_POINT_2008_11_22_H_ - #define UTIL_POINT_2008_11_22_H_ +#ifndef UTIL_POINT_2008_11_22_H + #define UTIL_POINT_2008_11_22_H namespace util { @@ -14,57 +14,62 @@ typename y_type = x_type> struct point { - x_type x; - y_type y; + x_type x { }; + y_type y { }; - point(const x_type& x0 = x_type(), - const y_type& y0 = y_type()) : x(x0), - y(y0) { } + explicit constexpr point(const x_type& x0 = x_type(), + const y_type& y0 = y_type()) : x { x0 }, + y { y0 } { } - point(const point& other) + constexpr point(const point& other) : x { other.x }, + y { other.y } { } + + constexpr point(point&& other) noexcept : x { other.x }, + y { other.y } { } + + ~point() = default; + + constexpr auto operator=(const point& other) -> point& { if(this != &other) { x = other.x; y = other.y; } - } - ~point() { } + return *this; + } - point& operator=(const point& other) + constexpr auto operator=(point&& other) noexcept -> point& { - if(this != &other) - { - x = other.x; - y = other.y; - } + x = other.x; + y = other.y; return *this; } - bool operator<(const point& other) const + constexpr auto operator<(const point& other) const -> bool { return (x < other.x); } }; template - bool operator==(const point& left, const point& right) + constexpr auto operator==(const point& left, const point& right) -> bool { return ( (left.x == right.x) && (left.y == right.y)); } template - bool operator!=(const point& left, const point& right) + constexpr auto operator!=(const point& left, const point& right) -> bool { return ( (left.x != right.x) || (left.y != right.y)); } template - bool operator<(const point& left, const point& right) + constexpr auto operator<(const point& left, const point& right) -> bool { return ((left.x < right.x) ? true @@ -74,22 +79,22 @@ } template - bool operator<=(const point& left, const point& right) + constexpr auto operator<=(const point& left, const point& right) -> bool { - return ((right < left) == false); + return (!(right < left)); } template - bool operator>(const point& left, const point& right) + constexpr auto operator>(const point& left, const point& right) -> bool { return (right < left); } template - bool operator>=(const point& left, const point& right) + constexpr auto operator>=(const point& left, const point& right) -> bool { - return ((left < right) == false); + return (!(left < right)); } - } + } // namespace util -#endif // UTIL_POINT_2008_11_22_H_ +#endif // UTIL_POINT_2008_11_22_H diff --git a/examples/chapter12_04/src/util/utility/util_stopwatch.h b/examples/chapter12_04/src/util/utility/util_stopwatch.h index a6f7951fa..a5cc101f0 100644 --- a/examples/chapter12_04/src/util/utility/util_stopwatch.h +++ b/examples/chapter12_04/src/util/utility/util_stopwatch.h @@ -1,12 +1,14 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014. +// Copyright Christopher Kormanyos 2014 - 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_STOPWATCH_2014_01_07_H_ - #define UTIL_STOPWATCH_2014_01_07_H_ +#ifndef UTIL_STOPWATCH_2014_01_07_H + #define UTIL_STOPWATCH_2014_01_07_H + + #include namespace util { @@ -14,17 +16,21 @@ class stopwatch final { public: - typedef typename clock_type::duration duration_type; + using duration_type = typename clock_type::duration; + + using time_point_type = typename clock_type::time_point; stopwatch() : my_start(clock_type::now()) { } - stopwatch(typename clock_type::time_point start) : my_start(start) { } + explicit stopwatch(time_point_type start) : my_start(start) { } stopwatch(const stopwatch& other) : my_start(other.my_start) { } - ~stopwatch() { } + stopwatch(stopwatch&& other) noexcept : my_start(other.my_start) { } - stopwatch& operator=(const stopwatch& other) + ~stopwatch() = default; + + auto operator=(const stopwatch& other) -> stopwatch& { if(this != &other) { @@ -34,18 +40,25 @@ return *this; } - duration_type elapsed() const + auto operator=(stopwatch&& other) noexcept -> stopwatch& + { + my_start = other.my_start; + + return *this; + } + + auto elapsed() const -> duration_type { return clock_type::now() - my_start; } - void reset() + auto reset() -> void { my_start = clock_type::now(); } private: - typename clock_type::time_point my_start; + time_point_type my_start; }; } @@ -53,4 +66,4 @@ // const auto elapsed = std::chrono::duration_cast(my_stopwatch.elapsed()).count(); // const auto elapsed = std::chrono::duration_cast>(my_stopwatch.elapsed()).count(); -#endif // UTIL_STOPWATCH_2014_01_07_H_ +#endif // UTIL_STOPWATCH_2014_01_07_H diff --git a/examples/chapter12_04/src/util/utility/util_swdm.h b/examples/chapter12_04/src/util/utility/util_swdm.h new file mode 100644 index 000000000..3e95bc48e --- /dev/null +++ b/examples/chapter12_04/src/util/utility/util_swdm.h @@ -0,0 +1,776 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info (AT) paland.com) +// 2014-2016, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// +// \brief Single Wire Debug Monitor +// This class is the single wire debug monitor, which allows easy inspecting and +// manipulating (setting) memory / variable data over a single wire/pin in embedded systems. +// NO DEPENDENCIES! NO UART! NO REQUIREMENTS! Just a 1 ms periodic tick is needed. That's all. +// +// SWDM uses a simple request/response protocol where the tester/PC is always the +// master generating the request and the device/board is the slave sending the response. +// The class below implements the SWDM slave. +// +// SWDM uses a service tick of 1ms, one bit is oversampled 4 times, which results +// in a baudrate of 250 bit/sec, every byte has a low start bit, a high stop bit and +// 8 data bits (LSB first). So a normal UART with 250 baud 8N1 can be used on the PC master side +// for transmission / reception. +// The line is used in half duplex bidirectional mode. It is high for idle / recessive levels +// and low when active / dominant. +// Use a resistor pulled-up open collector pin on the board site or set the pin as input +// on a high level in your custom set_line() function. +// +// Protocol: +// +// request: | 0x55 | mode | address | data | crc | +// +// 0x55 (1 byte) : +// Request sync byte +// +// mode (1 byte) : +// bit 0-3 : data length, 0: 1 byte, 2: 3 bytes ... 15: 16 bytes +// bit 4-5 : addr length, 0: 2 byte, 1: 3 byte, 2: 4 byte, 3: 8 byte +// bit 6 : 0: byte access, 1: type access valid for uint8, uint16, uint32 and uint64 data length +// bit 7 : 0: read data command, 1: write data command +// +// address (2 - 8 bytes) : +// Big-endian order, MSB - the most significant address byte is sent first +// +// data (0 - 16 bytes) : +// On read command, no data byte is transmitted, data field is skipped +// Byte access: The byte of the specified address is send first, ascending address order byte by byte +// Type access: MSB first, valid are 1,2,4 and 8 data bytes, the most significant data byte is sent first +// +// crc (1 byte) : +// One byte CRC, using CRC-8 (ITU-T), x^8 + x^2 + x + 1 polynomial +// CRC is build over mode, address and data bytes +// +// +// response: | 0xAA | data | crc | +// +// 0xAA (1 byte) : +// Response sync byte +// +// data (0 - 16 bytes) +// Requested data bytes of read command +// On write command no data is sent, the answer is | 0xAA | 0x00 | +// Byte access: The byte of the specified address is send first, ascending address order byte by byte +// Type access: MSB first, valid are 1, 2, 4 and 8 bytes, the most significant data byte is sent first +// +// crc (1 byte) : +// One byte CRC, using CRC-8 (ITU-T), x^8 + x^2 + x + 1 polynomial +// CRC is built over data bytes, in case of a write command, crc is 0x00 +// +// +// Usage: +// +// #include "swdm.h" +// +// Define (implement) the two low level line/pin access routines in your system +// or derive your own my_swdm class from swdm and define your access functions there. +// +// bool swdm::get_line() const +// { +// return the value of the according swdm interface line/pin +// } +// +// 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 configure the pin as input for high/idle levels +// and before setting the line to false/low it must be configured as an output. +// } +// +// Create a singleton instance of swdm: +// +// static swdm& get_swdm() +// { +// static swdm _swdm; +// return _swdm; +// } +// +// And call the swdm service routine with a rate of 1000 Hz: +// +// void system_tick_1ms() +// { +// get_swdm().service(); +// } +// +// +// \version +// 2014-09-17 0.10 Initial version, ideas +// 2014-09-23 0.80 Alpha version +// 2015-02-05 0.90 Beta version, code clean up +// 2015-02-25 0.91 Minor bug fixes, cleanup, more docu +// 2016-04-13 0.92 Bug fixes and tests by B. Hempelmann and C. Kormanyos +// 2016-04-17 1.00 Minor cleanups, first released version +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef UTIL_SWDM_2016_04_11_H +#define UTIL_SWDM_2016_04_11_H + +#if defined(__has_include) + #if(__has_include()) + #include + + #define UTIL_SWDM_HAS_USER_DEFINED_PORT + #endif +#endif + +#include + +#include + +#if !defined(UTIL_SWDM_HAS_USER_DEFINED_PORT) +class dummy_port +{ + public: + static constexpr auto set_direction_output() noexcept -> void { } + static constexpr auto set_direction_input () noexcept -> void { } + static constexpr auto set_pin_high () noexcept -> void { } + static constexpr auto set_pin_low () noexcept -> void { } + static constexpr auto read_input_value () noexcept -> bool { return false; } + static constexpr auto toggle_pin () noexcept -> void { } +}; + +namespace mcal { namespace debug { + +using debug_monitor_port_type = dummy_port; + +} // namespace debug +} // namespace mcal + +#endif + +// Defines the oversampling rate +// The effective baud rate is the service_tick_rate / SWD_OVERSAMPLING_COUNT +// For a service_tick_rate of 1 ms, the baud rate is 250 for 4 times oversampling +#define SWDM_SAMPLE_PERIOD UINT8_C(4) + +// Defines the position where the bit is detected as a constant valid bit. +// Should be at 50 to 75% of the SAMPLE period, 0 is the first sample position +#define SWDM_SAMPLE_VALID_POS UINT8_C(2) + +// Defines the number of consecutive high samples to detect a line idle condition +#define SWDM_SAMPLE_IDLE_COUNT UINT8_C(40) + +// Define this switch for 64 bit address support. If undefined, up to 32 bit addresses are supported +// #define SWDM_64_BIT_ADDRESS_SUPPORT + + +namespace util { + +class swdm : private util::noncopyable +{ +public: + // default ctor + swdm() : uart_state_ (rx_start_bit), + prot_state_ (rx_sync), + bit_detect_last_state_ (true), + bit_detect_sample_count_(UINT8_C(0)), + bit_detect_idle_count_ (UINT8_C(0)) + { + // set pin to idle / recessive value + set_line(true); + } + + // Service routine, MUST be called periodically with 1000 Hz (1 ms) + void service() + { + if( (uart_state_ == tx_data_bits) + || (uart_state_ == tx_start_bit) + || (uart_state_ == tx_stop_bit)) + { + // transmission + if(bit_detect_sample_count_ == UINT8_C(0)) + { + // bit period done + uart(true); + } + } + else + { + // reception + bool line = get_line(); + + // sync is done on every level change + if(line != bit_detect_last_state_) + { + // line level has changed, new bit cell started + bit_detect_last_state_ = line; + bit_detect_sample_count_ = UINT8_C(0); + } + else + { + // no level change + if((bit_detect_sample_count_ == SWDM_SAMPLE_VALID_POS) && + (bit_detect_idle_count_ < SWDM_SAMPLE_IDLE_COUNT)) + { + // valid bit detected + uart(line); + } + + // idle detection + bit_detect_idle_count_ = (line ? (bit_detect_idle_count_ + UINT8_C(1)) : UINT8_C(0)); + + if(bit_detect_idle_count_ >= SWDM_SAMPLE_IDLE_COUNT) + { + // line is idle, reset uart + bit_detect_idle_count_ = SWDM_SAMPLE_IDLE_COUNT; + uart_state_ = rx_start_bit; + } + } + } + + if(++bit_detect_sample_count_ == SWDM_SAMPLE_PERIOD) + { + bit_detect_sample_count_ = UINT8_C(0); + } + } + +protected: + // Line (pin) access function to get the actual line / pin state + // This function MUST be defined somewhere in your project or in your derived class + // \return The actual state of the swdm line / pin: true = high (idle/recessive), false = low (active/dominant) + virtual bool get_line() const + { + return mcal::debug::debug_monitor_port_type::read_input_value(); + } + + + // Line (pin) access function to set the actual line / pin state + // This function MUST be defined somewhere in your project + // \param value The new state of the swdm line / pin: true = high (idle/recessive), false = low (active/dominant) + virtual void set_line(const bool value) const + { + if(value) + { + mcal::debug::debug_monitor_port_type::set_direction_input(); + } + else + { + mcal::debug::debug_monitor_port_type::set_direction_output(); + mcal::debug::debug_monitor_port_type::set_pin_low(); + } + } + +private: + // Software UART, called by the service routine, when a valid bit is received or when a bit should be transmitted + // \param bit The value of the received bit + void uart(const bool bit) + { + switch(uart_state_) + { + case rx_start_bit: + if((!bit)) + { + // start bit detected + uart_data_bit_count_ = UINT8_C(0); + uart_state_ = rx_data_bits; + } + break; + + case rx_data_bits: + // LSB is transmitted first + uart_buffer_ = static_cast(std::uint_fast8_t(uart_buffer_ >> UINT8_C(1)) | std::uint_fast8_t(bit ? UINT8_C(0x80) : UINT8_C(0x00))); + + if(++uart_data_bit_count_ >= UINT8_C(8)) + { + uart_state_ = rx_stop_bit; + } + + break; + + case rx_stop_bit: + uart_state_ = rx_start_bit; + + if(bit) + { + // valid byte received, if no stop bit is detected, it's a framing error, discard data + uart_rx_full(uart_buffer_); + } + else + { + // framing error, discard data + prot_state_ = rx_sync; // reset the protocol state, because a byte error decays the whole command + } + + break; + + case tx_start_bit: + // send start bit + set_line(false); + + uart_data_bit_count_ = UINT8_C(0); + uart_state_ = tx_data_bits; + + break; + + case tx_data_bits: + // send data bits, LSB is first + set_line((uart_buffer_ & UINT8_C(0x01)) != UINT8_C(0)); + uart_buffer_ >>= UINT8_C(1); + + if(++uart_data_bit_count_ >= UINT8_C(8)) + { + uart_state_ = tx_stop_bit; + } + + break; + + case tx_stop_bit: + // send stop bit + set_line(true); + + uart_state_ = rx_start_bit; + + // byte transmission complete, inform protocol (transmitter empty) + uart_tx_empty(); + + break; + + default: + break; + } + } + + + // UART transmit function + // \param data The character to send + void uart_send(const std::uint_fast8_t data) + { + uart_buffer_ = std::uint8_t(data); + uart_state_ = tx_start_bit; + } + + // This function is called by the (software) UART when the receiver is full + // \param data The received character + void uart_rx_full(const std::uint_fast8_t data) + { + switch(prot_state_) + { + case rx_sync: + if(data == request_sync_field) + { + prot_state_ = rx_mode; + } + + break; + + case rx_mode: + prot_mode_ = data; + prot_idx_ = UINT8_C(0); + prot_crc_ = UINT8_C(0); + prot_state_ = rx_addr; + + crc8(data); + + break; + + case rx_addr: + { + prot_addr_[prot_idx_++] = data; + crc8(data); + + const std::uint_fast8_t addr_width = (prot_mode_ & UINT8_C(0x30)) >> UINT8_C(4); + + if( ((addr_width == UINT8_C(0)) && (prot_idx_ == UINT8_C(2))) // 16 bit address + || ((addr_width == UINT8_C(1)) && (prot_idx_ == UINT8_C(3))) // 24 bit address + || ((addr_width == UINT8_C(2)) && (prot_idx_ == UINT8_C(4))) // 32 bit address + #if defined(SWDM_64_BIT_ADDRESS_SUPPORT) + || ((addr_width == UINT8_C(3)) && (prot_idx_ == UINT8_C(8))) // 64 bit address + #endif + ) + { + prot_idx_ = UINT8_C(0); + prot_state_ = (((prot_mode_ & UINT8_C(0x80)) != UINT8_C(0))? rx_data : rx_crc); + } + + break; + } + + case rx_data: + prot_data_[prot_idx_++] = data; + crc8(data); + + if(prot_idx_ > (prot_mode_ & UINT8_C(0x0F))) + { + prot_state_ = rx_crc; + } + + break; + + case rx_crc: + if(data == prot_crc_) + { + // CRC correct - execute request + request(); + + // send response + prot_state_ = tx_sync; + + // start the transmission + uart_tx_empty(); + } + else + { + // CRC error - discard command, wait for next rx sync byte + prot_state_ = rx_sync; + } + + break; + + default: + prot_state_ = rx_sync; + break; + + case tx_sync: + case tx_data: + case tx_crc: + break; + } + } + + // This function is called by the (software) UART when the transmitter is empty + void uart_tx_empty() + { + switch(prot_state_) + { + case tx_sync: + prot_idx_ = UINT8_C(0); + prot_crc_ = UINT8_C(0); + prot_state_ = (((prot_mode_ & UINT8_C(0x80)) != UINT8_C(0)) ? tx_crc : tx_data); // skip data on write command + + uart_send(response_sync_field); + + break; + + case tx_data: + uart_send(prot_data_[prot_idx_]); + crc8(prot_data_[prot_idx_]); + + if(++prot_idx_ >= ((prot_mode_ & UINT8_C(0x0F)) + UINT8_C(1))) + { + prot_state_ = tx_crc; + } + + break; + + case tx_crc: + uart_send(prot_crc_); + prot_state_ = rx_sync; + + break; + + default: + prot_state_ = rx_sync; + break; + + case rx_sync: + case rx_mode: + case rx_addr: + case rx_data: + case rx_crc: + break; + } + } + + // Process and execute the received request + void request() + { + // get address width + std::uint_fast8_t addr_width; + + switch((prot_mode_ & UINT32_C(0x30)) >> UINT8_C(4)) + { + case UINT8_C(0): addr_width = UINT8_C(2); break; // 16 bit address + case UINT8_C(1): addr_width = UINT8_C(3); break; // 24 bit address + + default : + case UINT8_C(2): addr_width = UINT8_C(4); break; // 32 bit address + + #if defined(SWDM_64_BIT_ADDRESS_SUPPORT) + case UINT8_C(3): addr_width = UINT8_C(8); break; // 64 bit address + #endif + } + + #if defined(SWDM_64_BIT_ADDRESS_SUPPORT) + std::uint64_t addr = UINT64_C(0); + #else + std::uint32_t addr = UINT32_C(0); + #endif + + // assemble address + for(std::uint_fast8_t i = UINT8_C(0); i < addr_width; ++i) + { + addr <<= UINT8_C(8); + addr |= prot_addr_[i]; + } + + // data length + const std::uint_fast8_t data_length = (prot_mode_ & UINT8_C(0x0F)) + UINT8_C(1); + + if((prot_mode_ & UINT8_C(0x80)) != UINT8_C(0)) + { + // write command + if(prot_mode_ & UINT8_C(0x40)) + { + // write type access + switch(data_length) + { + case 1U: + *reinterpret_cast(addr) = prot_data_[0U]; + break; + + case 2U: + { + const std::uint16_t value = + (static_cast(prot_data_[0U]) << UINT8_C(8)) + | (static_cast(prot_data_[1U])); + + *reinterpret_cast(addr) = value; + + break; + } + + case 4U: + { + const std::uint32_t value = + (static_cast(prot_data_[0U]) << UINT8_C(24)) + | (static_cast(prot_data_[1U]) << UINT8_C(16)) + | (static_cast(prot_data_[2U]) << UINT8_C( 8)) + | (static_cast(prot_data_[3U])); + + *reinterpret_cast(addr) = value; + + break; + } + + case 8U: + { + const std::uint64_t value = + (static_cast(prot_data_[0U]) << UINT8_C(56)) + | (static_cast(prot_data_[1U]) << UINT8_C(48)) + | (static_cast(prot_data_[2U]) << UINT8_C(40)) + | (static_cast(prot_data_[3U]) << UINT8_C(32)) + | (static_cast(prot_data_[4U]) << UINT8_C(24)) + | (static_cast(prot_data_[5U]) << UINT8_C(16)) + | (static_cast(prot_data_[6U]) << UINT8_C( 8)) + | (static_cast(prot_data_[7U])); + + *reinterpret_cast(addr) = value; + + break; + } + + default: + // invalid data type, use byte access + for(std::uint_fast8_t i = UINT8_C(0); i < data_length; i++) + { + *reinterpret_cast(addr++) = prot_data_[i]; + } + + break; + } + } + else + { + // write byte access + for(std::uint_fast8_t i = UINT8_C(0); i < data_length; i++) + { + *reinterpret_cast(addr++) = prot_data_[i]; + } + } + } + else + { + // read command + if((prot_mode_ & UINT8_C(0x40)) != UINT8_C(0)) + { + // read type access + switch(data_length) + { + case UINT8_C(1): + prot_data_[0U] = *reinterpret_cast(addr); + break; + + case UINT8_C(2): + { + std::uint16_t value = *reinterpret_cast(addr); + + for(std::int_fast8_t tries = UINT8_C(4); --tries && (value != *reinterpret_cast(addr)); value = *reinterpret_cast(addr)) + { + ; + } + + prot_data_[0U] = byte_part(value); // MSB + prot_data_[1U] = byte_part(value); // LSB + + break; + } + + case UINT8_C(4): + { + std::uint32_t value = *reinterpret_cast(addr); + + for(std::int_fast8_t tries = UINT8_C(4); --tries && (value != *reinterpret_cast(addr)); value = *reinterpret_cast(addr)) + { + ; + } + + prot_data_[0U] = byte_part(value); // MSB + prot_data_[1U] = byte_part(value); + prot_data_[2U] = byte_part(value); + prot_data_[3U] = byte_part(value); // LSB + + break; + } + + case UINT8_C(8): + { + std::uint64_t value = *reinterpret_cast(addr); + + for(std::int_fast8_t tries = UINT8_C(4); --tries && (value != *reinterpret_cast(addr)); value = *reinterpret_cast(addr)) + { + ; + } + + prot_data_[0U] = byte_part(value); // MSB + prot_data_[1U] = byte_part(value); + prot_data_[2U] = byte_part(value); + prot_data_[3U] = byte_part(value); + prot_data_[4U] = byte_part(value); + prot_data_[5U] = byte_part(value); + prot_data_[6U] = byte_part(value); + prot_data_[7U] = byte_part(value); // LSB + + break; + } + + default: + // invalid data type, use byte access + for(std::uint_fast8_t i = UINT8_C(0); i < data_length; i++) + { + prot_data_[i] = *reinterpret_cast(addr++); + } + + break; + } + } + else + { + // read byte access + for(std::uint_fast8_t i = UINT8_C(0); i < data_length; i++) + { + prot_data_[i] = *reinterpret_cast(addr++); + } + } + } + } + + //////////////////////////////////////////////////////////////////////// + // H E L P E R F U N C T I O N S + + // CRC-8 algorithm, using x^8 + x^2 + x + 1 polynomial + // Process data, CRC result is in prot_crc_ + // We use a shifter here instead of a table lookup to save code size, speed + // is not so important at the swdm baudrate of 250 baud. + // \param data Data to process + void crc8(std::uint_fast8_t data) + { + for(std::uint_fast8_t i = UINT8_C(8); i; i--) + { + const std::uint_fast8_t sum = (prot_crc_ ^ data) & UINT8_C(0x01); + + prot_crc_ >>= UINT8_C(1); + + if(sum != UINT8_C(0)) + { + prot_crc_ ^= UINT8_C(0x8C); + } + + data >>= UINT8_C(1); + } + } + + // Return the according byte of the given position + // \param Long Type of the value + // \param Position Byte position to return, 0 is LSB + // \param value The Long value + // \return The byte of the Long value at the given position + template + std::uint8_t byte_part(const LongType& value) const + { + return static_cast(value >> (Position * UINT8_C(8))); + } + +private: + static constexpr std::uint_fast8_t request_sync_field = UINT8_C(0x55); // Request sync field + static constexpr std::uint_fast8_t response_sync_field = UINT8_C(0xAA); // Response sync field + + typedef enum enum_state_type + { + rx_start_bit, + rx_data_bits, + rx_stop_bit, + tx_start_bit, + tx_data_bits, + tx_stop_bit + } + state_type; + + typedef enum enum_prot_state_type + { + rx_sync, + rx_mode, + rx_addr, + rx_data, + rx_crc, + tx_sync, + tx_data, + tx_crc + } + prot_state_type; + + state_type uart_state_; + std::uint_fast8_t uart_buffer_; + std::uint_fast8_t uart_data_bit_count_; + + prot_state_type prot_state_; + std::uint_fast8_t prot_mode_; + std::uint8_t prot_addr_[ 8U]; + std::uint8_t prot_data_[16U]; + std::uint_fast8_t prot_crc_; + std::uint_fast8_t prot_idx_; + + bool bit_detect_last_state_; + std::uint_fast8_t bit_detect_sample_count_; + std::uint_fast8_t bit_detect_idle_count_; +}; + +} // namespace util + +#endif // UTIL_SWDM_2016_04_11_H diff --git a/examples/chapter12_04/src/util/utility/util_time.h b/examples/chapter12_04/src/util/utility/util_time.h index 938b83ab4..4cbc605ac 100644 --- a/examples/chapter12_04/src/util/utility/util_time.h +++ b/examples/chapter12_04/src/util/utility/util_time.h @@ -1,117 +1,145 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2014. +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2025. // 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 - #include - namespace util { - template - class timer + template + struct default_timer_backend; + + template> + class timer; + + template + struct default_timer_backend { - public: - typedef unsigned_tick_type tick_type; + using tick_type = UnsignedTickType; - static_assert(std::numeric_limits::is_signed == false, - "the timer tick_type must be unsigned"); + constexpr static auto get_now() -> tick_type + { + return static_cast(mcal::gpt::secure::get_time_elapsed()); + } + }; - 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"); + template + class timer + { + private: + using backend_type = BackendType; + + public: + using tick_type = typename backend_type::tick_type; private: - static const tick_type timer_mask = static_cast((UINTMAX_C(1) << (std::numeric_limits::digits - 1)) - UINTMAX_C(1)); + static constexpr auto timer_mask = + static_cast + ( + static_cast + ( + static_cast + ( + UINTMAX_C(1) << static_cast(std::numeric_limits::digits - 1) + ) + - UINTMAX_C(1) + ) + ); public: - template static tick_type microseconds(const other_tick_type& value_microseconds) { return static_cast(value_microseconds); } - template static tick_type milliseconds(const other_tick_type& value_milliseconds) { return static_cast(1000UL) * microseconds(value_milliseconds); } - template static tick_type seconds (const other_tick_type& value_seconds ) { return static_cast(1000UL) * milliseconds(value_seconds ); } - template static tick_type minutes (const other_tick_type& value_minutes ) { return static_cast( 60UL) * seconds (value_minutes ); } - template static tick_type hours (const other_tick_type& value_hours ) { return static_cast( 60UL) * minutes (value_hours ); } - template static tick_type days (const other_tick_type& value_days ) { return static_cast( 24UL) * hours (value_days ); } - template static tick_type weeks (const other_tick_type& value_weeks ) { return static_cast( 7UL) * days (value_weeks ); } + 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(UINT16_C(1000)) * microseconds(value_milliseconds); } + template static constexpr auto seconds (other_tick_type value_seconds) noexcept -> tick_type { return static_cast(UINT16_C(1000)) * milliseconds(value_seconds ); } + template static constexpr auto minutes (other_tick_type value_minutes) noexcept -> tick_type { return static_cast(UINT16_C( 60)) * seconds (value_minutes ); } + template static constexpr auto hours (other_tick_type value_hours) noexcept -> tick_type { return static_cast(UINT16_C( 60)) * minutes (value_hours ); } + template static constexpr auto days (other_tick_type value_days) noexcept -> tick_type { return static_cast(UINT16_C( 24)) * hours (value_days ); } + template static constexpr auto weeks (other_tick_type value_weeks) noexcept -> tick_type { return static_cast(UINT16_C( 7)) * days (value_weeks ); } - timer() : my_tick(0U) { } + constexpr timer() = default; - timer(const tick_type& tick_value) : my_tick(my_now() + tick_value) { } + explicit constexpr timer(tick_type tick_value) : my_tick(my_now() + tick_value) { } - timer(const timer& other) : my_tick(other.my_tick) { } + constexpr timer(const timer& other) = default; - timer& operator=(const timer& other) - { - if(this != &other) - { - my_tick = other.my_tick; - } + constexpr timer(timer&& other) noexcept = default; - return *this; - } + ~timer() = default; - void start_interval(const tick_type& tick_value) + constexpr auto operator=(const timer& other) -> timer& = default; + + constexpr auto operator=(timer&& other) noexcept -> timer& = default; + + constexpr auto start_interval(const tick_type& tick_value) -> void { my_tick += tick_value; } - void start_relative(const tick_type& tick_value) + constexpr auto start_relative(const tick_type& tick_value) -> void { my_tick = my_now() + tick_value; } - bool timeout() const + constexpr auto timeout() const -> 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 -> bool { - const tick_type delta = timepoint - my_tick; - - return (delta <= timer_mask); + return (static_cast(timepoint - my_tick) <= timer_mask); } - void set_mark() + constexpr auto set_mark() -> void { - my_tick = my_now(); - - return my_tick; + return (my_tick = my_now()); } - static tick_type get_mark() + static constexpr auto get_mark() -> tick_type { return my_now(); } - tick_type get_ticks_since_mark() const + constexpr auto get_ticks_since_mark() const -> tick_type { return my_now() - my_tick; } - static void blocking_delay(const tick_type& delay) + static auto blocking_delay(const tick_type& delay) -> void { - const timer t_delay(delay); + const timer t_delay { delay }; // NOLINT(altera-id-dependent-backward-branch) - while(false == t_delay.timeout()) + while(!t_delay.timeout()) // NOLINT(altera-id-dependent-backward-branch) { - mcal::cpu::nop(); + mcal::wdg::secure::trigger(); } } private: - tick_type my_tick; + tick_type my_tick { my_now() }; + + static constexpr auto my_now() -> tick_type + { + return static_cast(backend_type::get_now()); + } - static tick_type my_now() { return static_cast(mcal::gpt::secure::get_time_elapsed()); } + static_assert((!std::numeric_limits::is_signed), + "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"); }; - } + } // namespace util -#endif // UTIL_TIME_2010_04_10_H_ +#endif // UTIL_TIME_2010_04_10_H diff --git a/examples/chapter12_04/src/util/utility/util_two_part_data_manipulation.h b/examples/chapter12_04/src/util/utility/util_two_part_data_manipulation.h index a27077d74..282b5e6e6 100644 --- a/examples/chapter12_04/src/util/utility/util_two_part_data_manipulation.h +++ b/examples/chapter12_04/src/util/utility/util_two_part_data_manipulation.h @@ -1,28 +1,29 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef UTIL_TWO_PART_DATA_MANIPULATION_2010_06_13_H_ - #define UTIL_TWO_PART_DATA_MANIPULATION_2010_06_13_H_ +#ifndef UTIL_TWO_PART_DATA_MANIPULATION_2010_06_13_H + #define UTIL_TWO_PART_DATA_MANIPULATION_2010_06_13_H - #include #include + #include + namespace util { template(std::numeric_limits::digits * 2)>::exact_type> - inline unsigned_long_type make_long(unsigned_short_type lo, unsigned_short_type hi) + inline constexpr auto make_long(unsigned_short_type lo, unsigned_short_type hi) -> unsigned_long_type { // Ensure that the unsigned_short_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the unsigned_short_type of the make_long template must be an integer type"); // Ensure that the unsigned_long_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the unsigned_long_type of the make_long template must be an integer type."); // Ensure that the unsigned_long_type has exactly twice the digits as the unsigned_short_type. @@ -30,11 +31,11 @@ "the unsigned_long_type of the make_long template must be twice as wide as the unsigned_short_type"); // Ensure that the unsigned_short_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the unsigned_short_type of the make_long template must be unsigned"); // Ensure that the unsigned_long_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the unsigned_long_type of the make_long template must be unsigned."); return static_cast(static_cast(static_cast(hi) << std::numeric_limits::digits) | lo); @@ -42,14 +43,14 @@ template(std::numeric_limits::digits * 2)>::exact_type> - inline unsigned_short_type lo_part(unsigned_long_type val) + inline constexpr auto lo_part(unsigned_long_type val) -> unsigned_short_type { // Ensure that the unsigned_short_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the unsigned_short_type of the make_long template must be an integer type"); // Ensure that the unsigned_long_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the unsigned_long_type of the make_long template must be an integer type."); // Ensure that the unsigned_long_type has exactly twice the digits as the unsigned_short_type. @@ -57,11 +58,11 @@ "the unsigned_long_type of the lo_part template must be twice as wide as the unsigned_short_type"); // Ensure that the unsigned_short_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the unsigned_short_type of the lo_part template must be unsigned"); // Ensure that the unsigned_long_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the long type of the lo_part template must be unsigned"); return static_cast(val); @@ -69,14 +70,14 @@ template(std::numeric_limits::digits * 2)>::exact_type> - inline unsigned_short_type hi_part(unsigned_long_type val) + inline constexpr auto hi_part(unsigned_long_type val) -> unsigned_short_type { // Ensure that the unsigned_short_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the unsigned_short_type of the make_long template must be an integer type"); // Ensure that the unsigned_long_type is an integer type. - static_assert(std::numeric_limits::is_integer == true, + static_assert(std::numeric_limits::is_integer, "the unsigned_long_type of the make_long template must be an integer type."); // Ensure that the unsigned_long_type has exactly twice the digits as the unsigned_short_type. @@ -84,15 +85,15 @@ "the unsigned_long_type of the hi_part template must be twice as wide as the unsigned_short_type"); // Ensure that the unsigned_short_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the unsigned_short_type of the hi_part template must be unsigned"); // Ensure that the unsigned_long_type is unsigned. - static_assert(std::numeric_limits::is_signed == false, + static_assert((!std::numeric_limits::is_signed), "the unsigned_long_type of the hi_part template must be unsigned"); return static_cast(val >> std::numeric_limits::digits); } } -#endif // UTIL_TWO_PART_DATA_MANIPULATION_2010_06_13_H_ +#endif // UTIL_TWO_PART_DATA_MANIPULATION_2010_06_13_H diff --git a/examples/chapter12_04/src/util/utility/util_utype_helper.h b/examples/chapter12_04/src/util/utility/util_utype_helper.h index f009a0ff4..e6040965a 100644 --- a/examples/chapter12_04/src/util/utility/util_utype_helper.h +++ b/examples/chapter12_04/src/util/utility/util_utype_helper.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// 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) // -#ifndef UTIL_UTYPE_HELPER_2012_01_23_H_ - #define UTIL_UTYPE_HELPER_2012_01_23_H_ +#ifndef UTIL_UTYPE_HELPER_2012_01_23_H + #define UTIL_UTYPE_HELPER_2012_01_23_H #include @@ -17,44 +17,44 @@ static_assert(utype_bit_count <= 64U, "the bit count of the unsigned type can not exceed 64"); - typedef std::uint64_t exact_type; + using exact_type = std::uint64_t; }; - template<> struct utype_helper<0U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<1U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<2U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<3U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<4U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<5U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<6U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<7U> { typedef std::uint8_t exact_type; }; - template<> struct utype_helper<8U> { typedef std::uint8_t exact_type; }; - - template<> struct utype_helper<9U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<10U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<11U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<12U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<13U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<14U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<15U> { typedef std::uint16_t exact_type; }; - template<> struct utype_helper<16U> { typedef std::uint16_t exact_type; }; - - template<> struct utype_helper<17U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<18U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<19U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<20U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<21U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<22U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<23U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<24U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<25U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<26U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<27U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<28U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<29U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<30U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<31U> { typedef std::uint32_t exact_type; }; - template<> struct utype_helper<32U> { typedef std::uint32_t exact_type; }; + template<> struct utype_helper<0U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<1U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<2U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<3U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<4U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<5U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<6U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<7U> { using exact_type = std::uint8_t; }; + template<> struct utype_helper<8U> { using exact_type = std::uint8_t; }; + + template<> struct utype_helper<9U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<10U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<11U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<12U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<13U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<14U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<15U> { using exact_type = std::uint16_t; }; + template<> struct utype_helper<16U> { using exact_type = std::uint16_t; }; + + template<> struct utype_helper<17U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<18U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<19U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<20U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<21U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<22U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<23U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<24U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<25U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<26U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<27U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<28U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<29U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<30U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<31U> { using exact_type = std::uint32_t; }; + template<> struct utype_helper<32U> { using exact_type = std::uint32_t; }; } -#endif // UTIL_UTYPE_HELPER_2012_01_23_H_ +#endif // UTIL_UTYPE_HELPER_2012_01_23_H diff --git a/examples/chapter12_04/target/app/make/app_files.gmk b/examples/chapter12_04/target/app/make/app_files.gmk index 4d48ac972..1b7759c74 100644 --- a/examples/chapter12_04/target/app/make/app_files.gmk +++ b/examples/chapter12_04/target/app/make/app_files.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2018. +# Copyright Christopher Kormanyos 2007 - 2025. # 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,16 +12,17 @@ FILES_CPP = $(PATH_APP)/app/benchmark/app_benchmark \ $(PATH_APP)/app/led/app_led \ $(PATH_APP)/mcal/$(TGT)/mcal_cpu \ + $(PATH_APP)/mcal/$(TGT)/mcal_eep \ $(PATH_APP)/mcal/$(TGT)/mcal_gpt \ $(PATH_APP)/mcal/$(TGT)/mcal_irq \ $(PATH_APP)/mcal/$(TGT)/mcal_led \ $(PATH_APP)/mcal/$(TGT)/mcal_osc \ $(PATH_APP)/mcal/$(TGT)/mcal_port \ + $(PATH_APP)/mcal/$(TGT)/mcal_pwm \ + $(PATH_APP)/mcal/$(TGT)/mcal_spi \ $(PATH_APP)/mcal/$(TGT)/mcal_wdg \ $(PATH_APP)/mcal/mcal \ - $(PATH_APP)/mcal/mcal_gcc_cxx_completion \ $(PATH_APP)/os/os \ - $(PATH_APP)/os/os_task_control_block \ $(PATH_APP)/sys/idle/sys_idle \ $(PATH_APP)/sys/mon/sys_mon \ $(PATH_APP)/sys/start/sys_start diff --git a/examples/chapter12_04/target/app/make/app_make.gmk b/examples/chapter12_04/target/app/make/app_make.gmk index 8b50b92b9..f9f89892c 100644 --- a/examples/chapter12_04/target/app/make/app_make.gmk +++ b/examples/chapter12_04/target/app/make/app_make.gmk @@ -1,12 +1,12 @@ # -# Copyright Christopher Kormanyos 2007 - 2024. +# Copyright Christopher Kormanyos 2007 - 2025. # 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,24 +15,57 @@ # # 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 +# # ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ -# compiler location, build from GCC version and GCC target +# operating system # ------------------------------------------------------------------------------ -COMPILER_DIRECTORY = gcc-$(GCC_VERSION)-$(GCC_TARGET) + +ifeq ($(TYP_OS),) + +ifeq ($(OS),Windows_NT) +TYP_OS := WIN +else +TYP_OS := NIX +endif + +endif # ------------------------------------------------------------------------------ -# paths +# punctuation # ------------------------------------------------------------------------------ -PATH_TOOLS = tools -PATH_TOOLS_UTIL = $(PATH_TOOLS)\Util -PATH_TOOLS_MINGW = $(PATH_TOOLS_UTIL)\msys64\usr -PATH_TOOLS_MINGW_BIN = $(PATH_TOOLS_MINGW)\bin -PATH_TOOLS_CC = $(PATH_TOOLS_MINGW)\local\gcc-$(GCC_VERSION)-$(GCC_TARGET)\bin +DQUOTE := \" +$(DQUOTE) := \" + +SEMICOLON := ; +$(SEMICOLON) := ; + +DOLLAR := $$ +$(DOLLAR) := $$ + +# ------------------------------------------------------------------------------ +# null device +# ------------------------------------------------------------------------------ + +ifeq ($(TYP_OS),WIN) +NULL_DEVICE := NUL +$(NULL_DEVICE) := NUL +else +NULL_DEVICE := /dev/null +$(NULL_DEVICE) := /dev/null +endif + + +# ------------------------------------------------------------------------------ +# paths +# ------------------------------------------------------------------------------ PATH_APP = src PATH_TGT = target/micros/$(TGT) PATH_APP_MAKE = target/app/make @@ -40,16 +73,41 @@ 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 + +ifeq ($(TYP_OS),WIN) + +PATH_TOOLS = tools +PATH_TOOLS_UTIL = $(PATH_TOOLS)\Util +PATH_TOOLS_MINGW = $(PATH_TOOLS_UTIL)\msys64\usr +PATH_TOOLS_MINGW_BIN = $(PATH_TOOLS_MINGW)\bin +PATH_TOOLS_CC = $(PATH_TOOLS_MINGW)\local\gcc-$(GCC_VERSION)-$(GCC_TARGET)\bin + +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 + +else + +ECHO = echo +MAKE = make +MKDIR = mkdir +RM = rm +SED = sed + +ifneq ($(MY_GMAKE),) +MAKE := $(MY_GMAKE) +endif + +endif # ------------------------------------------------------------------------------ @@ -57,17 +115,32 @@ include $(PATH_TGT_MAKE)/$(TGT)_flags.gmk # Target compiler flags # ------------------------------------------------------------------------------ APP = $(PATH_BIN)/chapter12_04 +IMAGE_FILE = $(APP).bin + +RULE_SPECIAL_MAKE_IMAGE_FILE = +RULE_SPECIAL_MAKE_FLASH_BATCH = + +WARN_FLAGS := + # ------------------------------------------------------------------------------ -# object files +# linker definition file # ------------------------------------------------------------------------------ -FILES_TMP = $(FILES_CPP) $(FILES_TGT) -FILES_O = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .o, $(FILES_TMP)))) +LINKER_DEFINITION_FILE := $(PATH_TGT_MAKE)/$(TGT).ld # ------------------------------------------------------------------------------ -# linker definition file +# 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 + + # ------------------------------------------------------------------------------ -LINKER_DEFINITION_FILE = $(PATH_TGT_MAKE)/$(TGT).ld +# object files +# ------------------------------------------------------------------------------ +FILES_TMP = $(FILES_CPP) $(FILES_TGT) +FILES_O = $(addprefix $(PATH_OBJ)/, $(notdir $(addsuffix .o, $(FILES_TMP)))) # ------------------------------------------------------------------------------ @@ -85,21 +158,76 @@ 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 +ifeq ($(TYP_OS),WIN) + +ifeq ($(GCC_PREFIX),) + +ifeq ($(AR),) +AR := $(PATH_TOOLS_CC)\ar.exe +endif +ifeq ($(AS),) +AS := $(PATH_TOOLS_CC)\g++.exe +endif +ifeq ($(CC),) +CC := $(PATH_TOOLS_CC)\g++.exe +endif +ifeq ($(CPPFILT),) +CPPFILT := $(PATH_TOOLS_CC)\c++filt.exe +endif +ifeq ($(NM),) +NM := $(PATH_TOOLS_CC)\nm.exe +endif +ifeq ($(OBJDUMP),) +OBJDUMP := $(PATH_TOOLS_CC)\objdump.exe +endif +ifeq ($(OBJCOPY),) +OBJCOPY := $(PATH_TOOLS_CC)\objcopy.exe +endif +ifeq ($(READELF),) +READELF := $(PATH_TOOLS_CC)\readelf.exe +endif +ifeq ($(SIZE),) +SIZE := $(PATH_TOOLS_CC)\size.exe +endif -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 +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 +OBJCOPY := $(PATH_TOOLS_CC)\$(GCC_PREFIX)-objcopy.exe +READELF := $(PATH_TOOLS_CC)\$(GCC_PREFIX)-readelf.exe +SIZE := $(PATH_TOOLS_CC)\$(GCC_PREFIX)-size.exe +endif + +else + +ifeq ($(GCC_PREFIX),) +AR := ar +AS := g++ +CC := g++ +CPPFILT := c++filt +NM := nm +OBJDUMP := objdump +OBJCOPY := objcopy +READELF := readelf +SIZE := size +else +AR := $(GCC_PREFIX)-ar +AS := $(GCC_PREFIX)-g++ +CC := $(GCC_PREFIX)-g++ +CPPFILT := $(GCC_PREFIX)-c++filt +NM := $(GCC_PREFIX)-nm +OBJDUMP := $(GCC_PREFIX)-objdump +OBJCOPY := $(GCC_PREFIX)-objcopy +READELF := $(GCC_PREFIX)-readelf +SIZE := $(GCC_PREFIX)-size +endif + +endif # ------------------------------------------------------------------------------ @@ -109,13 +237,14 @@ 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 \ + -Wpedantic \ -Wmain \ -Wundef \ + -Wconversion \ -Wsign-conversion \ -Wunused-parameter \ -Wuninitialized \ @@ -128,40 +257,40 @@ GCCFLAGS = $(TGT_CFLAGS) \ -Wmissing-include-dirs \ -Winit-self \ -Wfloat-equal \ - -Wdouble-promotion \ + -Wdouble-promotion + +endif + +GCCFLAGS = -g \ + $(WARN_FLAGS) \ + -Wno-comment \ -gdwarf-2 \ -fno-exceptions \ - -ffunction-sections \ - -fdata-sections + -fdata-sections \ + -ffunction-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) \ - $(TGT_CFLAGS) \ + $(TGT_CXXFLAGS) \ $(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 +315,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 +329,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,21 +343,27 @@ clean_all: .PHONY: version version: # Print the GNU make version and the compiler version + @$(ECHO) @$(ECHO) +++ Print GNUmake version @$(MAKE) --version @$(ECHO) - @$(ECHO) +++ Print GCC version + @$(ECHO) +++ Print compiler version @$(CC) -v @$(ECHO) @$(ECHO) +++ Print compiler include paths @$(ECHO) $(C_INCLUDES) @$(ECHO) +ifeq ($(TYP_OS),WIN) @$(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) +endif @$(ECHO) +++ Print compiler definitions @$(ECHO) $(C_DEFINES) @$(ECHO) + @$(ECHO) +++ Print compiler CXXFLAGS flags + @$(ECHO) $(CXXFLAGS) + @$(ECHO) # ------------------------------------------------------------------------------ @@ -237,8 +372,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 +383,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 +396,31 @@ $(APP)_nm.txt : $(APP).$(TGT_SUFFIX) # create hex mask # ------------------------------------------------------------------------------ $(APP)_flash.hex : $(APP).$(TGT_SUFFIX) - @-$(ECHO) +++ creating hex module: $(APP).hex. - @-$(OBJCOPY) -O ihex $(APP).$(TGT_SUFFIX) $(APP).hex - @-$(OBJCOPY) -S -O binary $(APP).$(TGT_SUFFIX) $(APP).bin + @-$(ECHO) +++ creating hex module: $(APP).$(TGT_SUFFIX) +ifeq ($(TGT_SUFFIX),elf) + @-$(ECHO) +++ creating hex module: $(APP).hex + @-$(OBJCOPY) $(APP).$(TGT_SUFFIX) -O ihex $(APP).hex + @-$(ECHO) +++ creating srec module: $(APP).s19 + @-$(OBJCOPY) $(APP).$(TGT_SUFFIX) -O srec $(APP).s19 + @-$(ECHO) +++ creating disassembly listing: $(APP)_disassembly.txt + @-$(OBJDUMP) -D $(APP).$(TGT_SUFFIX) > $(APP)_disassembly.txt +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 +429,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/chapter12_04/target/app/make/app_rules.gmk b/examples/chapter12_04/target/app/make/app_rules.gmk index 9a0de5e83..c3e28832c 100644 --- a/examples/chapter12_04/target/app/make/app_rules.gmk +++ b/examples/chapter12_04/target/app/make/app_rules.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2018. +# Copyright Christopher Kormanyos 2007 - 2025. # 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/chapter12_04/target/build/build.bat b/examples/chapter12_04/target/build/build.bat index ebc8db6ec..0b3ac0ff3 100644 --- a/examples/chapter12_04/target/build/build.bat +++ b/examples/chapter12_04/target/build/build.bat @@ -1,5 +1,5 @@ @rem -@rem Copyright Christopher Kormanyos 2007 - 2021. +@rem Copyright Christopher Kormanyos 2007 - 2025. @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/chapter12_04/target/micros/avr/make/avr.ld b/examples/chapter12_04/target/micros/avr/make/avr.ld index ceace1c6a..434fbb2b4 100644 --- a/examples/chapter12_04/target/micros/avr/make/avr.ld +++ b/examples/chapter12_04/target/micros/avr/make/avr.ld @@ -1,6 +1,5 @@ - /* - Copyright Christopher Kormanyos 2007 - 2021. + Copyright Christopher Kormanyos 2007 - 2025. 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/chapter12_04/target/micros/avr/make/avr_files.gmk b/examples/chapter12_04/target/micros/avr/make/avr_files.gmk index 42e78648d..bc797a5a1 100644 --- a/examples/chapter12_04/target/micros/avr/make/avr_files.gmk +++ b/examples/chapter12_04/target/micros/avr/make/avr_files.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2020. +# Copyright Christopher Kormanyos 2007 - 2025. # 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,8 +9,8 @@ # File list of the avr files in the project # ------------------------------------------------------------------------------ -FILES_TGT = $(PATH_APP)/util/STL/impl/cmath_impl_gamma \ - $(PATH_APP)/util/STL/impl/avr/avr_float_limits \ +FILES_TGT = $(PATH_APP)/mcal/mcal_gcc_cxx_completion \ + $(PATH_APP)/util/STL/impl/cmath_impl_gamma \ $(PATH_TGT)/startup/crt0 \ $(PATH_TGT)/startup/crt0_init_ram \ $(PATH_TGT)/startup/crt1 \ diff --git a/examples/chapter12_04/target/micros/avr/make/avr_flags.gmk b/examples/chapter12_04/target/micros/avr/make/avr_flags.gmk index 8d762a099..59667982b 100644 --- a/examples/chapter12_04/target/micros/avr/make/avr_flags.gmk +++ b/examples/chapter12_04/target/micros/avr/make/avr_flags.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2024. +# Copyright Christopher Kormanyos 2007 - 2025. # 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,53 @@ # compiler flags for the target architecture # ------------------------------------------------------------------------------ -# See also: https://blog.zakkemble.net/avr-gcc-builds/ - -GCC_VERSION = 14.2.0 GCC_TARGET = avr GCC_PREFIX = avr +GCC_VERSION = 15.1.0 + TGT_SUFFIX = elf -TGT_CFLAGS = -Os \ - -mmcu=atmega328p \ - -fsigned-char \ - -mrelax +TGT_ALLFLAGS = -O2 \ + -mmcu=atmega328p \ + -mrelax \ + -finline-functions \ + -finline-limit=64 \ + -fsigned-char + +ifeq ($(TYP_OS),WIN) + +TGT_ALLFLAGS := $(TGT_ALLFLAGS) \ + -mdouble=64 \ + -mlong-double=64 + +INC_PREFIX := -isystem +STD_C := c11 +STD_CPP := c++20 + +else -TGT_CPPFLAGS = -std=c++11 +INC_PREFIX := -I +STD_C := c99 +STD_CPP := c++14 -TGT_INCLUDES = -I$(PATH_APP)/util/STL_C++XX_stdfloat \ +endif + +TGT_CFLAGS = -std=$(STD_C) \ + $(TGT_ALLFLAGS) + +TGT_CXXFLAGS = -std=$(STD_CPP) \ + $(TGT_ALLFLAGS) + +TGT_INCLUDES = -I$(PATH_APP)/util/STL_C++XX_stdfloat \ -I$(PATH_APP)/util/STL +#TGT_INCLUDES = $(INC_PREFIX)C:/ChrisGitRepos/avr-libstdcpp/include + 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/chapter12_04/target/micros/avr/startup/crt0.cpp b/examples/chapter12_04/target/micros/avr/startup/crt0.cpp index 03c33da6e..0616b2cd6 100644 --- a/examples/chapter12_04/target/micros/avr/startup/crt0.cpp +++ b/examples/chapter12_04/target/micros/avr/startup/crt0.cpp @@ -1,24 +1,26 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2025. // 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 +#include + asm(".extern __initial_stack_pointer"); namespace crt { - void init_ram () __attribute__((section(".startup"), used, noinline)); - void init_ctors() __attribute__((section(".startup"), used, noinline)); + void init_ram () ATTRIBUTE(section(".startup"), used, noinline); + void init_ctors() ATTRIBUTE(section(".startup"), used, noinline); } -extern "C" void __my_startup() __attribute__((section(".startup"), used, noinline)); +extern "C" void __my_startup() ATTRIBUTE(section(".startup"), used, noinline); void __my_startup() { diff --git a/examples/chapter12_04/target/micros/avr/startup/crt0_init_ram.cpp b/examples/chapter12_04/target/micros/avr/startup/crt0_init_ram.cpp index 58238983c..b15938f5e 100644 --- a/examples/chapter12_04/target/micros/avr/startup/crt0_init_ram.cpp +++ b/examples/chapter12_04/target/micros/avr/startup/crt0_init_ram.cpp @@ -1,16 +1,18 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2025. // 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 -#include - extern "C" { extern mcal_progmem_uintptr_t _rom_data_begin; // Start address for the initialization values of the rom-to-ram section. @@ -22,39 +24,30 @@ extern "C" namespace crt { - void init_ram() __attribute__((section(".startup"), used, noinline)); + void init_ram() ATTRIBUTE(section(".startup"), used, noinline); } 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/chapter12_04/target/micros/avr/startup/crt1.cpp b/examples/chapter12_04/target/micros/avr/startup/crt1.cpp index 13b0b6569..8afc4e7a4 100644 --- a/examples/chapter12_04/target/micros/avr/startup/crt1.cpp +++ b/examples/chapter12_04/target/micros/avr/startup/crt1.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,44 +8,45 @@ #include #include + +#include #include extern "C" { - struct constructor_function_type + struct ctor_type { - using pointer = void(*)(void); + using function_type = 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 { - void init_ctors() __attribute__((section(".startup"), used, noinline)); + void init_ctors() ATTRIBUTE(section(".startup"), used, noinline); } 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/chapter12_04/target/micros/avr/startup/int_vect.cpp b/examples/chapter12_04/target/micros/avr/startup/int_vect.cpp index e0661ae87..3174f0150 100644 --- a/examples/chapter12_04/target/micros/avr/startup/int_vect.cpp +++ b/examples/chapter12_04/target/micros/avr/startup/int_vect.cpp @@ -1,17 +1,21 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2019. +// Copyright Christopher Kormanyos 2007 - 2025. // 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 -#include -extern "C" void __my_startup () __attribute__((section(".startup"), used, noinline)); -extern "C" void __vector_unused_irq() __attribute__((signal, used, externally_visible)); -extern "C" void __vector_16 () __attribute__((signal, used, externally_visible)); +extern "C" void __my_startup () ATTRIBUTE(section(".startup"), used, noinline); +extern "C" void __vector_unused_irq() ATTRIBUTE(signal, used, externally_visible); +extern "C" void __vector_16 () ATTRIBUTE(signal, used, externally_visible); extern "C" void __vector_unused_irq() @@ -22,49 +26,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 }}; diff --git a/ref_app/src/app/led/app_led.cpp b/ref_app/src/app/led/app_led.cpp index d09656122..e47acb1b4 100644 --- a/ref_app/src/app/led/app_led.cpp +++ b/ref_app/src/app/led/app_led.cpp @@ -10,8 +10,8 @@ namespace app { namespace led { -void task_init(); -void task_func(); +auto task_init() -> void; +auto task_func() -> void; } // namespace led } // namespace app diff --git a/ref_app/src/math/constants/constants.h b/ref_app/src/math/constants/constants.h index 2080e4d57..5cbe847e0 100644 --- a/ref_app/src/math/constants/constants.h +++ b/ref_app/src/math/constants/constants.h @@ -1,12 +1,12 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2012 - 2018. +// Copyright Christopher Kormanyos 2012 - 2025. // 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 CONSTANTS_2012_01_09_H_ - #define CONSTANTS_2012_01_09_H_ +#ifndef CONSTANTS_2012_01_09_H + #define CONSTANTS_2012_01_09_H namespace math { @@ -80,4 +80,4 @@ } } -#endif // CONSTANTS_2012_01_09_H_ +#endif // CONSTANTS_2012_01_09_H diff --git a/ref_app/src/math/functions/math_functions_bessel.h b/ref_app/src/math/functions/math_functions_bessel.h index 6e36da9fd..20bf91a1c 100644 --- a/ref_app/src/math/functions/math_functions_bessel.h +++ b/ref_app/src/math/functions/math_functions_bessel.h @@ -1,13 +1,12 @@ - /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2018. +// Copyright Christopher Kormanyos 2014 - 2025. // 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 MATH_FUNCTIONS_BESSEL_2014_04_30_H_ - #define MATH_FUNCTIONS_BESSEL_2014_04_30_H_ +#ifndef MATH_FUNCTIONS_BESSEL_2014_04_30_H + #define MATH_FUNCTIONS_BESSEL_2014_04_30_H #include @@ -37,4 +36,4 @@ } } // namespace math::functions -#endif // MATH_FUNCTIONS_BESSEL_2014_04_30_H_ +#endif // MATH_FUNCTIONS_BESSEL_2014_04_30_H diff --git a/ref_app/src/math/functions/math_functions_hypergeometric.h b/ref_app/src/math/functions/math_functions_hypergeometric.h index 8c937f802..02cf779f1 100644 --- a/ref_app/src/math/functions/math_functions_hypergeometric.h +++ b/ref_app/src/math/functions/math_functions_hypergeometric.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2024. +// Copyright Christopher Kormanyos 2014 - 2025. // 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/ref_app/src/math/functions/math_functions_legendre.h b/ref_app/src/math/functions/math_functions_legendre.h index c2cf5e317..86f6f3e7a 100644 --- a/ref_app/src/math/functions/math_functions_legendre.h +++ b/ref_app/src/math/functions/math_functions_legendre.h @@ -1,13 +1,12 @@ - /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2018. +// Copyright Christopher Kormanyos 2014 - 2025. // 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 MATH_FUNCTIONS_LEGENDRE_2014_04_30_H_ - #define MATH_FUNCTIONS_LEGENDRE_2014_04_30_H_ +#ifndef MATH_FUNCTIONS_LEGENDRE_2014_04_30_H + #define MATH_FUNCTIONS_LEGENDRE_2014_04_30_H #include @@ -46,4 +45,4 @@ } } // namespace math::functions -#endif // MATH_FUNCTIONS_LEGENDRE_2014_04_30_H_ +#endif // MATH_FUNCTIONS_LEGENDRE_2014_04_30_H diff --git a/ref_app/src/sys/idle/sys_idle.cpp b/ref_app/src/sys/idle/sys_idle.cpp index 459ddfc01..748992a4b 100644 --- a/ref_app/src/sys/idle/sys_idle.cpp +++ b/ref_app/src/sys/idle/sys_idle.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2023. +// Copyright Christopher Kormanyos 2007 - 2025. // 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,13 +9,13 @@ namespace sys { namespace idle { -auto task_init() noexcept -> void; +auto task_init() -> void; auto task_func() -> void; } // namespace idle } // namespace sys -auto sys::idle::task_init() noexcept -> void { } +auto sys::idle::task_init() -> void { } auto sys::idle::task_func() -> void { diff --git a/ref_app/src/sys/mon/sys_mon.cpp b/ref_app/src/sys/mon/sys_mon.cpp index 5da788aaf..cc6daf24a 100644 --- a/ref_app/src/sys/mon/sys_mon.cpp +++ b/ref_app/src/sys/mon/sys_mon.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2022. +// Copyright Christopher Kormanyos 2007 - 2025. // 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/ref_app/src/util/memory/util_factory.h b/ref_app/src/util/memory/util_factory.h index 5765003ca..a6315eb4c 100644 --- a/ref_app/src/util/memory/util_factory.h +++ b/ref_app/src/util/memory/util_factory.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2024. +// Copyright Christopher Kormanyos 2007 - 2025. // 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/ref_app/target/app/make/app_files.gmk b/ref_app/target/app/make/app_files.gmk index 1ae3e493f..b127b5ebb 100644 --- a/ref_app/target/app/make/app_files.gmk +++ b/ref_app/target/app/make/app_files.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2024. +# Copyright Christopher Kormanyos 2007 - 2025. # 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/ref_app/target/app/make/app_rules.gmk b/ref_app/target/app/make/app_rules.gmk index 8737bc559..c3e28832c 100644 --- a/ref_app/target/app/make/app_rules.gmk +++ b/ref_app/target/app/make/app_rules.gmk @@ -1,5 +1,5 @@ # -# Copyright Christopher Kormanyos 2007 - 2024. +# Copyright Christopher Kormanyos 2007 - 2025. # 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/ref_app/target/build/build.bat b/ref_app/target/build/build.bat index 925526091..fb9e57a1d 100644 --- a/ref_app/target/build/build.bat +++ b/ref_app/target/build/build.bat @@ -1,5 +1,5 @@ @rem -@rem Copyright Christopher Kormanyos 2007 - 2024. +@rem Copyright Christopher Kormanyos 2007 - 2025. @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) diff --git a/ref_app/target/micros/bl602_sifive_e24_riscv/make/bl602_sifive_e24_riscv_flags.gmk b/ref_app/target/micros/bl602_sifive_e24_riscv/make/bl602_sifive_e24_riscv_flags.gmk index 1276335bb..8cf5163f5 100644 --- a/ref_app/target/micros/bl602_sifive_e24_riscv/make/bl602_sifive_e24_riscv_flags.gmk +++ b/ref_app/target/micros/bl602_sifive_e24_riscv/make/bl602_sifive_e24_riscv_flags.gmk @@ -15,7 +15,7 @@ GCC_VERSION := 15.2.0 TGT_SUFFIX = elf -TGT_ALLFLAGS = -O3 \ +TGT_ALLFLAGS = -O2 \ -ffast-math \ -mcpu=sifive-e24 \ -mabi=ilp32 \ @@ -33,6 +33,9 @@ TGT_CXXFLAGS = -std=c++23 \ TGT_INCLUDES := +#TGT_INCLUDES := -I$(PATH_APP)/math/boost_stubs \ +# -IC:/boost/boost_1_89_0 + TGT_AFLAGS = $(TGT_ALLFLAGS) TGT_LDFLAGS = $(TGT_ALLFLAGS) \ diff --git a/ref_app/tools/AVR/avrdude/avrdude-v8.0-windows-x64/12_04.bat b/ref_app/tools/AVR/avrdude/avrdude-v8.0-windows-x64/12_04.bat new file mode 100644 index 000000000..7434cdc21 --- /dev/null +++ b/ref_app/tools/AVR/avrdude/avrdude-v8.0-windows-x64/12_04.bat @@ -0,0 +1,27 @@ +rem /////////////////////////////////////////////////////////////////////////////// +rem // Copyright Christopher Kormanyos 2007 - 2025. +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) +rem // + +echo off + +set AVRDUDE=.\avrdude.exe + +set HEX=../../../../../examples/chapter12_04/bin/chapter12_04.hex + +rem Erase the chip. +echo "Erase the chip." +%AVRDUDE% -c arduino -p m328p -P COM5 -b 115200 -e +echo. + +rem Flash the HEX-file. +echo "Flash the HEX-file." +%AVRDUDE% -c arduino -p m328p -P COM5 -b 115200 -U flash:w:%HEX%:i +echo. + +rem Verify the flash. +echo "Verify the flash." +%AVRDUDE% -c arduino -p m328p -P COM5 -b 115200 -U flash:v:%HEX%:i +echo.