summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/safe_numerics/example
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/safe_numerics/example
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/safe_numerics/example')
-rw-r--r--src/boost/libs/safe_numerics/example/CMakeLists.txt52
-rw-r--r--src/boost/libs/safe_numerics/example/Jamfile.v231
-rw-r--r--src/boost/libs/safe_numerics/example/Motor.c179
-rw-r--r--src/boost/libs/safe_numerics/example/example1.cpp42
-rw-r--r--src/boost/libs/safe_numerics/example/example10.cpp45
-rw-r--r--src/boost/libs/safe_numerics/example/example11.cpp42
-rw-r--r--src/boost/libs/safe_numerics/example/example13.cpp36
-rw-r--r--src/boost/libs/safe_numerics/example/example14.cpp37
-rw-r--r--src/boost/libs/safe_numerics/example/example15.cpp45
-rw-r--r--src/boost/libs/safe_numerics/example/example16.cpp16
-rw-r--r--src/boost/libs/safe_numerics/example/example17.cpp16
-rw-r--r--src/boost/libs/safe_numerics/example/example18.cpp19
-rw-r--r--src/boost/libs/safe_numerics/example/example19.cpp32
-rw-r--r--src/boost/libs/safe_numerics/example/example2.cpp40
-rw-r--r--src/boost/libs/safe_numerics/example/example20.cpp29
-rw-r--r--src/boost/libs/safe_numerics/example/example3.cpp47
-rw-r--r--src/boost/libs/safe_numerics/example/example4.cpp57
-rw-r--r--src/boost/libs/safe_numerics/example/example5.cpp39
-rw-r--r--src/boost/libs/safe_numerics/example/example6.cpp41
-rw-r--r--src/boost/libs/safe_numerics/example/example7.cpp84
-rw-r--r--src/boost/libs/safe_numerics/example/example8.cpp44
-rw-r--r--src/boost/libs/safe_numerics/example/example81.cpp18
-rw-r--r--src/boost/libs/safe_numerics/example/example82.cpp23
-rw-r--r--src/boost/libs/safe_numerics/example/example83.cpp37
-rw-r--r--src/boost/libs/safe_numerics/example/example84.cpp53
-rw-r--r--src/boost/libs/safe_numerics/example/example91.cpp90
-rw-r--r--src/boost/libs/safe_numerics/example/example92.cpp207
-rw-r--r--src/boost/libs/safe_numerics/example/example93.cpp299
-rw-r--r--src/boost/libs/safe_numerics/example/motor1.c152
-rw-r--r--src/boost/libs/safe_numerics/example/motor2.c169
-rw-r--r--src/boost/libs/safe_numerics/example/motor3.c195
-rw-r--r--src/boost/libs/safe_numerics/example/motor_test1.c44
-rw-r--r--src/boost/libs/safe_numerics/example/motor_test2.c48
-rw-r--r--src/boost/libs/safe_numerics/example/motor_test3.c58
-rw-r--r--src/boost/libs/safe_numerics/example/picsfr.h29
-rw-r--r--src/boost/libs/safe_numerics/example/safe_format.hpp52
-rw-r--r--src/boost/libs/safe_numerics/example/stepper-motor.pdfbin0 -> 1198964 bytes
37 files changed, 2447 insertions, 0 deletions
diff --git a/src/boost/libs/safe_numerics/example/CMakeLists.txt b/src/boost/libs/safe_numerics/example/CMakeLists.txt
new file mode 100644
index 00000000..d00186e7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/CMakeLists.txt
@@ -0,0 +1,52 @@
+# CMake build control file for safe numerics Library Examples
+
+###########################
+# examples
+
+message( STATUS "Runtimes are stored in ${CMAKE_CURRENT_BINARY_DIR}" )
+
+set(run_examples_list
+ example1
+ example2
+ example3
+ example4
+ example5
+ example6
+ example7
+ example8
+ example10
+ example11
+ example13
+ example14
+ example15
+ example18
+ example19
+ example20
+ # example81 # requires console input
+ example82
+ example83
+ # example84 # requires console input
+ example92
+ example93
+)
+
+foreach(test_name ${run_examples_list})
+ test_run_pass(${test_name})
+ set_target_properties(${test_name} PROPERTIES FOLDER "run test examples")
+endforeach(test_name)
+
+# end examples targets
+####################
+
+###########################
+# add misc files to IDE
+
+file(GLOB misc_files
+ RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c"
+)
+add_custom_target(miscellaneous SOURCES ${misc_files})
+set_target_properties(miscellaneous PROPERTIES FOLDER "examples")
+
+# end headers in IDE
+####################
diff --git a/src/boost/libs/safe_numerics/example/Jamfile.v2 b/src/boost/libs/safe_numerics/example/Jamfile.v2
new file mode 100644
index 00000000..321c3acd
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/Jamfile.v2
@@ -0,0 +1,31 @@
+# Boost.SafeNumerics Library test Jamfile
+#
+# Copyright (c) 2017 Robert Ramey
+#
+# 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
+
+import testing ;
+
+run example1.cpp ;
+run example11.cpp ;
+run example2.cpp ;
+run example3.cpp ;
+run example4.cpp ;
+run example5.cpp ;
+run example6.cpp ;
+run example7.cpp ;
+run example8.cpp ;
+compile-fail example81.cpp ;
+# run example81.cpp ; # requires console input
+run example82.cpp ;
+run example83.cpp ;
+# run example84.cpp ; # requires console input
+run example10.cpp ;
+run example11.cpp ;
+run example13.cpp ;
+run example15.cpp ;
+run example92.cpp ;
+run example93.cpp ;
+
diff --git a/src/boost/libs/safe_numerics/example/Motor.c b/src/boost/libs/safe_numerics/example/Motor.c
new file mode 100644
index 00000000..cc9e91c5
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/Motor.c
@@ -0,0 +1,179 @@
+// Demo program for stepper motor control with linear ramps
+// Hardware: PIC18F252, L6219
+#include "18F252.h"
+
+// PIC18F252 SFRs
+#byte TRISC = 0xf94
+#byte T3CON = 0xfb1
+#byte CCP2CON = 0xfba
+#byte CCPR2L = 0xfbb
+#byte CCPR2H = 0xfbc
+#byte CCP1CON = 0xfbd
+#byte CCPR1L = 0xfbe
+#byte CCPR1H = 0xfbf
+#byte T1CON = 0xfcd
+#byte TMR1L = 0xfce
+#byte TMR1H = 0xfcf
+#bit TMR1ON = T1CON.0
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 50000
+#define C_MIN 2500
+
+// ramp state-machine states
+#define ramp_idle 0
+#define ramp_up 1
+#define ramp_max 2
+#define ramp_down 3
+#define ramp_last 4
+
+// Types: int8,int16,int32=8,16,32bit integers, unsigned by default
+int8 ramp_sts=ramp_idle;
+signed int16 motor_pos = 0; // absolute step number
+signed int16 pos_inc=0; // motor_pos increment
+int16 phase=0; // ccpPhase[phase_ix]
+int8 phase_ix=0; // index to ccpPhase[]
+int8 phase_inc; // phase_ix increment
+int8 run_flg; // true while motor is running
+int16 ccpr; // copy of CCPR1&2
+int16 c; // integer delay count
+int16 step_no; // progress of move
+int16 step_down; // start of down-ramp
+int16 move; // total steps to move
+int16 midpt; // midpoint of move
+int32 c32; // 24.8 fixed point delay count
+signed int16 denom; // 4.n+1 in ramp algo
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+int16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+// compiler-specific ISR declaration
+#INT_CCP1
+void isr_motor_step()
+{ // CCP1 match -> step pulse + IRQ
+ ccpr += c; // next comparator value: add step delay count
+ switch (ramp_sts)
+ {
+ case ramp_up: // accel
+ if (step_no==midpt)
+ { // midpoint: decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move)<<2)+1;
+ if (!(move & 1))
+ { // even move: repeat last delay before decel
+ denom +=4;
+ break;
+ }
+ }
+ // no break: share code for ramp algo
+ case ramp_down: // decel
+ if (step_no == move-1)
+ { // next irq is cleanup (no step)
+ ramp_sts = ramp_last;
+ break;
+ }
+ denom+=4;
+ c32 -= (c32<<1)/denom; // ramp algorithm
+ // beware confict with foreground code if long div not reentrant
+ c = (c32+128)>>8; // round 24.8format->int16
+ if (c <= C_MIN)
+ { // go to constant speed
+ ramp_sts = ramp_max;
+ step_down = move - step_no;
+ c = C_MIN;
+ break;
+ }
+ break;
+ case ramp_max: // constant speed
+ if (step_no == step_down)
+ { // start decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move)<<2)+5;
+ }
+ break;
+ default: // last step: cleanup
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ disable_interrupts(INT_CCP1);
+ run_flg = FALSE; // move complete
+ break;
+ } // switch (ramp_sts)
+ if (ramp_sts!=ramp_idle)
+ {
+ motor_pos += pos_inc;
+ ++step_no;
+ CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ if (ramp_sts!=ramp_last) // else repeat last action: no step
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // set CCP action on next match
+ CCP2CON = phase >> 8;
+ } // if (ramp_sts != ramp_idle)
+} // isr_motor_step()
+
+void motor_run(short pos_new)
+{ // set up to drive motor to pos_new (absolute step#)
+ if (pos_new < motor_pos) // get direction & #steps
+ {
+ move = motor_pos-pos_new;
+ pos_inc = -1;
+ phase_inc = 0xff;
+ }
+ else if (pos_new != motor_pos)
+ {
+ move = pos_new-motor_pos;
+ pos_inc = 1;
+ phase_inc = 1;
+ }
+ else return; // already there
+ midpt = (move-1)>>1;
+ c = C0;
+ c32 = c<<8; // keep c in 24.8 fixed-point format for ramp calcs
+ step_no = 0; // step counter
+ denom = 1; // 4.n+1, n=0
+ ramp_sts = ramp_up; // start ramp state-machine
+ run_flg = TRUE;
+ TMR1ON = 0; // stop timer1;
+ ccpr = make16(TMR1H,TMR1L); // 16bit value of Timer1
+ ccpr += 1000; // 1st step + irq 1ms after timer1 restart
+ CCPR2H = CCPR1H = (ccpr >> 8);
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // sets action on match
+ CCP2CON = phase >> 8;
+ current_on(); // current in motor windings
+ enable_interrupts(INT_CCP1);
+ TMR1ON=1; // restart timer1;
+} // motor_run()
+
+
+void initialize()
+{
+ disable_interrupts(GLOBAL);
+ disable_interrupts(INT_CCP1);
+ disable_interrupts(INT_CCP2);
+ output_c(0);
+ set_tris_c(0);
+ T3CON = 0;
+ T1CON = 0x35;
+ enable_interrupts(GLOBAL);
+} // initialize()
+
+void main()
+{
+ initialize();
+ while (1)
+ { // repeat 5 revs forward & back
+ motor_run(1000);
+ while (run_flg);
+ motor_run(0);
+ while (run_flg);
+ }
+} // main()
+// end of file motor.c
diff --git a/src/boost/libs/safe_numerics/example/example1.cpp b/src/boost/libs/safe_numerics/example/example1.cpp
new file mode 100644
index 00000000..2d2f67fd
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example1.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 1:";
+ std::cout << "undetected erroneous expression evaluation" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ try{
+ std::int8_t x = 127;
+ std::int8_t y = 2;
+ std::int8_t z;
+ // this produces an invalid result !
+ z = x + y;
+ std::cout << "error NOT detected!" << std::endl;
+ std::cout << (int)z << " != " << (int)x << " + " << (int)y << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<std::int8_t> x = INT_MAX;
+ safe<std::int8_t> y = 2;
+ safe<std::int8_t> z;
+ // rather than producing an invalid result an exception is thrown
+ z = x + y;
+ }
+ catch(const std::exception & e){
+ // which we can catch here
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example10.cpp b/src/boost/libs/safe_numerics/example/example10.cpp
new file mode 100644
index 00000000..f6796974
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example10.cpp
@@ -0,0 +1,45 @@
+#include <iostream>
+#include <cstdint>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+using namespace std;
+using namespace boost::safe_numerics;
+
+void f(const unsigned int & x, const int8_t & y){
+ cout << x * y << endl;
+}
+void safe_f(
+ const safe<unsigned int> & x,
+ const safe<int8_t> & y
+){
+ cout << x * y << endl;
+}
+
+int main(){
+ cout << "example 4: ";
+ cout << "mixing types produces surprising results" << endl;
+ try {
+ std::cout << "Not using safe numerics" << std::endl;
+ // problem: mixing types produces surprising results.
+ f(100, 100); // works as expected
+ f(100, -100); // wrong result - unnoticed
+ cout << "error NOT detected!" << endl;;
+ }
+ catch(const std::exception & e){
+ // never arrive here
+ cout << "error detected:" << e.what() << endl;;
+ }
+ try {
+ // solution: use safe types
+ std::cout << "Using safe numerics" << std::endl;
+ safe_f(100, 100); // works as expected
+ safe_f(100, -100); // throw error
+ cout << "error NOT detected!" << endl;;
+ }
+ catch(const std::exception & e){
+ cout << "error detected:" << e.what() << endl;;
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/safe_numerics/example/example11.cpp b/src/boost/libs/safe_numerics/example/example11.cpp
new file mode 100644
index 00000000..51c17f05
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example11.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char * []){
+ std::cout << "example 1:";
+ std::cout << "undetected erroneous expression evaluation" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ // problem: arithmetic operations can yield incorrect results.
+ try{
+ std::int8_t x = 127;
+ std::int8_t y = 2;
+ std::int8_t z;
+ // this produces an invalid result !
+ z = x + y;
+ std::cout << z << " != " << x + y << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace std::int8_t with safe<std::int8_t>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<std::int8_t> x = 127;
+ safe<std::int8_t> y = 2;
+ // rather than producing and invalid result an exception is thrown
+ safe<std::int8_t> z = x + y;
+ }
+ catch(const std::exception & e){
+ // which can catch here
+ std::cout << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example13.cpp b/src/boost/libs/safe_numerics/example/example13.cpp
new file mode 100644
index 00000000..f78c6dc5
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example13.cpp
@@ -0,0 +1,36 @@
+#include <stdexcept>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // problem: cannot recover from arithmetic errors
+ std::cout << "example 7: ";
+ std::cout << "cannot recover from arithmetic errors" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ try{
+ int x = 1;
+ int y = 0;
+ // can't do this as it will crash the program with no
+ // opportunity for recovery - comment out for example
+ // std::cout << x / y;
+ std::cout << "error cannot be handled at runtime!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error handled at runtime!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ const safe<int> x = 1;
+ const safe<int> y = 0;
+ std::cout << x / y;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "error handled at runtime!" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example14.cpp b/src/boost/libs/safe_numerics/example/example14.cpp
new file mode 100644
index 00000000..44a206d2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example14.cpp
@@ -0,0 +1,37 @@
+#include <stdexcept>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // problem: cannot recover from arithmetic errors
+ std::cout << "example 8: ";
+ std::cout << "cannot detect compile time arithmetic errors" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ try{
+ const int x = 1;
+ const int y = 0;
+ // will emit warning at compile time
+ // will leave an invalid result at runtime.
+ std::cout << x / y; // will display "0"!
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ const safe<int> x = 1;
+ const safe<int> y = 0;
+ // constexpr const safe<int> z = x / y; // note constexpr here!
+ std::cout << x / y; // error would be detected at runtime
+ std::cout << " error NOT detected!" << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example15.cpp b/src/boost/libs/safe_numerics/example/example15.cpp
new file mode 100644
index 00000000..829dff29
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example15.cpp
@@ -0,0 +1,45 @@
+#include <iostream>
+#include <limits>
+
+#include <boost/rational.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // simple demo of rational library
+ const boost::rational<int> r {1, 2};
+ std::cout << "r = " << r << std::endl;
+ const boost::rational<int> q {-2, 4};
+ std::cout << "q = " << q << std::endl;
+ // display the product
+ std::cout << "r * q = " << r * q << std::endl;
+
+ // problem: rational doesn't handle integer overflow well
+ const boost::rational<int> c {1, INT_MAX};
+ std::cout << "c = " << c << std::endl;
+ const boost::rational<int> d {1, 2};
+ std::cout << "d = " << d << std::endl;
+ // display the product - wrong answer
+ std::cout << "c * d = " << c * d << std::endl;
+
+ // solution: use safe integer in rational definition
+ using safe_rational = boost::rational<
+ boost::safe_numerics::safe<int>
+ >;
+
+ // use rationals created with safe_t
+ const safe_rational sc {1, INT_MAX};
+ std::cout << "c = " << sc << std::endl;
+ const safe_rational sd {1, 2};
+ std::cout << "d = " << sd << std::endl;
+ std::cout << "c * d = ";
+ try {
+ // multiply them. This will overflow
+ std::cout << sc * sd << std::endl;
+ }
+ catch (std::exception const& e) {
+ // catch exception due to multiplication overflow
+ std::cout << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example16.cpp b/src/boost/libs/safe_numerics/example/example16.cpp
new file mode 100644
index 00000000..d6782452
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example16.cpp
@@ -0,0 +1,16 @@
+#include <boost/safe_numerics/safe_integer.hpp>
+using namespace boost::safe_numerics;
+
+int f(int i){
+ return i;
+}
+
+using safe_t = safe<long>;
+
+int main(){
+ const long x = 97;
+ f(x); // OK - implicit conversion to int
+ const safe_t y = 97;
+ f(y); // Also OK - checked implicit conversion to int
+ return 0;
+} \ No newline at end of file
diff --git a/src/boost/libs/safe_numerics/example/example17.cpp b/src/boost/libs/safe_numerics/example/example17.cpp
new file mode 100644
index 00000000..372be9cc
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example17.cpp
@@ -0,0 +1,16 @@
+#include <boost/safe_numerics/safe_integer.hpp>
+using namespace boost::safe_numerics;
+
+int f(int i){
+ return i;
+}
+
+using safe_t = safe<long, native, loose_trap_policy>;
+
+int main(){
+ const long x = 97;
+ f(x); // OK - implicit conversion to int
+ const safe_t y = 97;
+ f(y); // Would be OK, but will invoke compile time error
+ return 0;
+} \ No newline at end of file
diff --git a/src/boost/libs/safe_numerics/example/example18.cpp b/src/boost/libs/safe_numerics/example/example18.cpp
new file mode 100644
index 00000000..bb59602e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example18.cpp
@@ -0,0 +1,19 @@
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+using namespace boost::safe_numerics;
+
+int f(int i){
+ return i;
+}
+
+template<intmax_t N>
+using safe_literal = safe_signed_literal<N, native, loose_trap_policy>;
+
+int main(){
+ const long x = 97;
+ f(x); // OK - implicit conversion to int
+ const safe_literal<97> y;
+ f(y); // OK - y is a type with min/max = 97;
+ return 0;
+} \ No newline at end of file
diff --git a/src/boost/libs/safe_numerics/example/example19.cpp b/src/boost/libs/safe_numerics/example/example19.cpp
new file mode 100644
index 00000000..e9cd4648
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example19.cpp
@@ -0,0 +1,32 @@
+#include <type_traits>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+#include <boost/safe_numerics/utility.hpp>
+
+using namespace boost::safe_numerics;
+
+void f(){
+ safe_unsigned_range<7, 24> i;
+ // since the range is included in [0,255], the underlying type of i
+ // will be an unsigned char.
+ i = 0; // throws out_of_range exception
+ i = 9; // ok
+ i *= 9; // throws out_of_range exception
+ i = -1; // throws out_of_range exception
+ std::uint8_t j = 4;
+ auto k = i + j;
+
+ // if either or both types are safe types, the result is a safe type
+ // determined by promotion policy. In this instance
+ // the range of i is [7, 24] and the range of j is [0,255].
+ // so the type of k will be a safe type with a range of [7,279]
+ static_assert(
+ is_safe<decltype(k)>::value
+ && std::numeric_limits<decltype(k)>::min() == 7
+ && std::numeric_limits<decltype(k)>::max() == 279,
+ "k is a safe range of [7,279]"
+ );
+}
+
+int main(){}
diff --git a/src/boost/libs/safe_numerics/example/example2.cpp b/src/boost/libs/safe_numerics/example/example2.cpp
new file mode 100644
index 00000000..3866fe85
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example2.cpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 2:";
+ std::cout << "undetected overflow in data type" << std::endl;
+ // problem: undetected overflow
+ std::cout << "Not using safe numerics" << std::endl;
+ try{
+ int x = INT_MAX;
+ // the following silently produces an incorrect result
+ ++x;
+ std::cout << x << " != " << INT_MAX << " + 1" << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<int> x = INT_MAX;
+ // throws exception when result is past maximum possible
+ ++x;
+ assert(false); // never arrive here
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << std::endl;
+ std::cout << "error detected!" << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example20.cpp b/src/boost/libs/safe_numerics/example/example20.cpp
new file mode 100644
index 00000000..160995d0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example20.cpp
@@ -0,0 +1,29 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+
+int main(){
+ using ext_uint = boost::safe_numerics::checked_result<unsigned int>;
+ const ext_uint x{4};
+ const ext_uint y{3};
+
+ // operation is a success!
+ std::cout << "success! x - y = " << x - y;
+
+ // subtraction would result in -1, and invalid result for an unsigned value
+ std::cout << "problem: y - x = " << y - x;
+
+ const ext_uint z = y - x;
+ std::cout << "z = " << z;
+ // sum of two negative overflows is a negative overflow.
+ std::cout << "z + z" << z + z;
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example3.cpp b/src/boost/libs/safe_numerics/example/example3.cpp
new file mode 100644
index 00000000..15b810eb
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example3.cpp
@@ -0,0 +1,47 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 3:";
+ std::cout << "undetected underflow in data type" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ // problem: decrement can yield incorrect result
+ try{
+ unsigned int x = 0;
+ // the following silently produces an incorrect result
+ --x;
+ std::cout << x << " != " << -1 << std::endl;
+
+ // when comparing int and unsigned int, C++ converts
+ // the int to unsigned int so the following assertion
+ // fails to detect the above error!
+ assert(x == -1);
+
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ // never arrive here
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace unsigned int with safe<unsigned int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<unsigned int> x = 0;
+ // decrement unsigned to less than zero throws exception
+ --x;
+ assert(false); // never arrive here
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << std::endl;
+ std::cout << "error detected!" << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example4.cpp b/src/boost/libs/safe_numerics/example/example4.cpp
new file mode 100644
index 00000000..d3b8eae7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example4.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) 2018Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(){
+ std::cout << "example 4: ";
+ std::cout << "implicit conversions change data values" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ // problem: implicit conversions change data values
+ try{
+ signed int a{-1};
+ unsigned int b{1};
+ std::cout << "a is " << a << " b is " << b << '\n';
+ if(a < b){
+ std::cout << "a is less than b\n";
+ }
+ else{
+ std::cout << "b is less than a\n";
+ }
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ // never arrive here - just produce the wrong answer!
+ std::cout << "error detected!" << std::endl;
+ return 1;
+ }
+
+ // solution: replace int with safe<int> and unsigned int with safe<unsigned int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<signed int> a{-1};
+ safe<unsigned int> b{1};
+ std::cout << "a is " << a << " b is " << b << '\n';
+ if(a < b){
+ std::cout << "a is less than b\n";
+ }
+ else{
+ std::cout << "b is less than a\n";
+ }
+ std::cout << "error NOT detected!" << std::endl;
+ return 1;
+ }
+ catch(const std::exception & e){
+ // never arrive here - just produce the correct answer!
+ std::cout << e.what() << std::endl;
+ std::cout << "error detected!" << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example5.cpp b/src/boost/libs/safe_numerics/example/example5.cpp
new file mode 100644
index 00000000..efb3d2ea
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example5.cpp
@@ -0,0 +1,39 @@
+#include <stdexcept>
+#include <iostream>
+#include <array>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+void detected_msg(bool detected){
+ std::cout << (detected ? "error detected!" : "error NOT detected! ") << std::endl;
+}
+
+int main(int, const char *[]){
+ // problem: array index values can exceed array bounds
+ std::cout << "example 5: ";
+ std::cout << "array index values can exceed array bounds" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ std::array<int, 37> i_array;
+
+ // unsigned int i_index = 43;
+ // the following corrupts memory.
+ // This may or may not be detected at run time.
+ // i_array[i_index] = 84; // comment this out so it can be tested!
+ std::cout << "error NOT detected!" << std::endl;
+
+ // solution: replace unsigned array index with safe_unsigned_range
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ using i_index_t = safe_unsigned_range<0, i_array.size() - 1>;
+ i_index_t i_index;
+ i_index = 36; // this works fine
+ i_array[i_index] = 84;
+ i_index = 43; // throw exception here!
+ std::cout << "error NOT detected!" << std::endl; // so we never arrive here
+ }
+ catch(const std::exception & e){
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example6.cpp b/src/boost/libs/safe_numerics/example/example6.cpp
new file mode 100644
index 00000000..fbd44a8e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example6.cpp
@@ -0,0 +1,41 @@
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // problem: checking of externally produced value can be overlooked
+ std::cout << "example 6: ";
+ std::cout << "checking of externally produced value can be overlooked" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ std::istringstream is("12317289372189 1231287389217389217893");
+
+ try{
+ int x, y;
+ is >> x >> y; // get integer values from the user
+ std::cout << x << ' ' << y << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+
+ // solution: assign externally retrieved values to safe equivalents
+ std::cout << "Using safe numerics" << std::endl;
+ {
+ using namespace boost::safe_numerics;
+ safe<int> x, y;
+ is.seekg(0);
+ try{
+ is >> x >> y; // get integer values from the user
+ std::cout << x << ' ' << y << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example7.cpp b/src/boost/libs/safe_numerics/example/example7.cpp
new file mode 100644
index 00000000..076abfd8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example7.cpp
@@ -0,0 +1,84 @@
+#include <cassert>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+// NOT using safe numerics - enforce program contract explicitly
+// return total number of minutes
+unsigned int contract_convert(
+ const unsigned int & hours,
+ const unsigned int & minutes
+) {
+ // check that parameters are within required limits
+ // invokes a runtime cost EVERYTIME the function is called
+ // and the overhead of supporting an interrupt.
+ // note high runtime cost!
+ if(minutes > 59)
+ throw std::domain_error("minutes exceeded 59");
+ if(hours > 23)
+ throw std::domain_error("hours exceeded 23");
+ return hours * 60 + minutes;
+}
+
+// Use safe numerics to enforce program contract automatically
+// define convenient typenames for hours and minutes hh:mm
+using hours_t = boost::safe_numerics::safe_unsigned_range<0, 23>;
+using minutes_t = boost::safe_numerics::safe_unsigned_range<0, 59>;
+using minutes_total_t = boost::safe_numerics::safe_unsigned_range<0, 59>;
+
+// return total number of minutes
+// type returned is safe_unsigned_range<0, 24*60 - 1>
+auto convert(const hours_t & hours, const minutes_t & minutes) {
+ // no need to test pre-conditions
+ // input parameters are guaranteed to hold legitimate values
+ // no need to test post-conditions
+ // return value guaranteed to hold result
+ return hours * 60 + minutes;
+}
+
+unsigned int test1(unsigned int hours, unsigned int minutes){
+ // problem: checking of externally produced value can be expensive
+ // invalid parameters - detected - but at a heavy cost
+ return contract_convert(hours, minutes);
+}
+
+auto test2(unsigned int hours, unsigned int minutes){
+ // solution: use safe numerics
+ // safe types can be implicitly constructed base types
+ // construction guarentees corectness
+ // return value is known to fit in unsigned int
+ return convert(hours, minutes);
+}
+
+auto test3(unsigned int hours, unsigned int minutes){
+ // actually we don't even need the convert function any more
+ return hours_t(hours) * 60 + minutes_t(minutes);
+}
+
+int main(int, const char *[]){
+ std::cout << "example 7: ";
+ std::cout << "enforce contracts with zero runtime cost" << std::endl;
+
+ unsigned int total_minutes;
+
+ try {
+ total_minutes = test3(17, 83);
+ std::cout << "total minutes = " << total_minutes << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "parameter error detected" << std::endl;
+ }
+
+ try {
+ total_minutes = test3(17, 10);
+ std::cout << "total minutes = " << total_minutes << std::endl;
+ }
+ catch(const std::exception & e){
+ // should never arrive here
+ std::cout << "parameter error erroneously detected" << std::endl;
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example8.cpp b/src/boost/libs/safe_numerics/example/example8.cpp
new file mode 100644
index 00000000..a8229f19
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example8.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// 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 <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 8:";
+ std::cout << "undetected erroneous expression evaluation" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ try{
+ unsigned int x = 127;
+ unsigned int y = 2;
+ unsigned int z;
+ // this produces an invalid result !
+ z = y - x;
+ std::cout << "error NOT detected!" << std::endl;
+ std::cout << z << " != " << y << " - " << x << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<unsigned int> x = 127;
+ safe<unsigned int> y = 2;
+ safe<unsigned int> z;
+ // rather than producing an invalid result an exception is thrown
+ z = y - x;
+ std::cout << "error NOT detected!" << std::endl;
+ std::cout << z << " != " << y << " - " << x << std::endl;
+ }
+ catch(const std::exception & e){
+ // which we can catch here
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example81.cpp b/src/boost/libs/safe_numerics/example/example81.cpp
new file mode 100644
index 00000000..5c7fc236
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example81.cpp
@@ -0,0 +1,18 @@
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/exception_policies.hpp> // include exception policies
+
+using safe_t = boost::safe_numerics::safe<
+ int,
+ boost::safe_numerics::native,
+ boost::safe_numerics::loose_trap_policy // note use of "loose_trap_exception" policy!
+>;
+
+int main(int argc, const char * argv[]){
+ std::cout << "example 81:\n";
+ safe_t x(INT_MAX);
+ safe_t y(2);
+ safe_t z = x + y; // will fail to compile !
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example82.cpp b/src/boost/libs/safe_numerics/example/example82.cpp
new file mode 100644
index 00000000..0e49e9e7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example82.cpp
@@ -0,0 +1,23 @@
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/exception_policies.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "safe_format.hpp" // prints out range and value of any type
+
+using safe_t = boost::safe_numerics::safe<
+ int,
+ boost::safe_numerics::automatic, // note use of "automatic" policy!!!
+ boost::safe_numerics::loose_trap_policy
+>;
+
+int main(int, const char *[]){
+ std::cout << "example 82:\n";
+ safe_t x(INT_MAX);
+ safe_t y = 2;
+ std::cout << "x = " << safe_format(x) << std::endl;
+ std::cout << "y = " << safe_format(y) << std::endl;
+ std::cout << "x + y = " << safe_format(x + y) << std::endl;
+ return 0;
+}
+
diff --git a/src/boost/libs/safe_numerics/example/example83.cpp b/src/boost/libs/safe_numerics/example/example83.cpp
new file mode 100644
index 00000000..3d345b62
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example83.cpp
@@ -0,0 +1,37 @@
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+#include <boost/safe_numerics/exception.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "safe_format.hpp" // prints out range and value of any type
+
+using namespace boost::safe_numerics;
+
+// create a type for holding small integers in a specific range
+using safe_t = safe_signed_range<
+ -24,
+ 82,
+ native, // C++ type promotion rules work OK for this example
+ loose_trap_policy // catch problems at compile time
+>;
+
+// create a type to hold one specific value
+template<int I>
+using const_safe_t = safe_signed_literal<I, native, loose_trap_policy>;
+
+// We "know" that C++ type promotion rules will work such that
+// addition will never overflow. If we change the program to break this,
+// the usage of the loose_trap_policy promotion policy will prevent compilation.
+int main(int, const char *[]){
+ std::cout << "example 83:\n";
+
+ constexpr const const_safe_t<10> x;
+ std::cout << "x = " << safe_format(x) << std::endl;
+ constexpr const const_safe_t<67> y;
+ std::cout << "y = " << safe_format(y) << std::endl;
+ const safe_t z = x + y;
+ std::cout << "x + y = " << safe_format(x + y) << std::endl;
+ std::cout << "z = " << safe_format(z) << std::endl;
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example84.cpp b/src/boost/libs/safe_numerics/example/example84.cpp
new file mode 100644
index 00000000..68285af2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example84.cpp
@@ -0,0 +1,53 @@
+#include <stdexcept>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include <boost/safe_numerics/exception.hpp>
+
+#include "safe_format.hpp" // prints out range and value of any type
+
+using namespace boost::safe_numerics;
+
+using safe_t = safe_signed_range<
+ -24,
+ 82,
+ automatic,
+ loose_trap_policy
+>;
+
+// define variables used for input
+using input_safe_t = safe_signed_range<
+ -24,
+ 82,
+ automatic, // we don't need automatic in this case
+ loose_exception_policy // assignment of out of range value should throw
+>;
+
+// function arguments can never be outside of limits
+auto f(const safe_t & x, const safe_t & y){
+ auto z = x + y; // we know that this cannot fail
+ std::cout << "z = " << safe_format(z) << std::endl;
+ std::cout << "(x + y) = " << safe_format(x + y) << std::endl;
+ std::cout << "(x - y) = " << safe_format(x - y) << std::endl;
+ return z;
+}
+
+int main(int argc, const char * argv[]){
+ std::cout << "example 84:\n";
+ input_safe_t x, y;
+ try{
+ std::cout << "type in values in format x y:" << std::flush;
+ std::cin >> x >> y; // read varibles, maybe throw exception
+ }
+ catch(const std::exception & e){
+ // none of the above should trap. Mark failure if they do
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ std::cout << "x" << safe_format(x) << std::endl;
+ std::cout << "y" << safe_format(y) << std::endl;
+ std::cout << safe_format(f(x, y)) << std::endl;
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example91.cpp b/src/boost/libs/safe_numerics/example/example91.cpp
new file mode 100644
index 00000000..f3bc4872
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example91.cpp
@@ -0,0 +1,90 @@
+//////////////////////////////////////////////////////////////////
+// example91.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// 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 <iostream>
+#include <limits>
+
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics//safe_integer_range.hpp>
+
+// use same type promotion as used by the pic compiler
+// see the following comment in motor.c
+// Types: int8,int16,int32=8,16,32bit integers
+
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char
+ 8, // short
+ 8, // int
+ 16, // long
+ 32 // long long
+>;
+
+// define safe types used desktop version of the program. In conjunction
+// with the promotion policy above, this will permit us to guarantee that
+// the resulting program will be free of arithmetic errors introduced by
+// C expression syntax and type promotion with no runtime penalty
+template <typename T> // T is char, int, etc data type
+using safe_t = boost::safe_numerics::safe<
+ T,
+ pic16_promotion,
+ boost::safe_numerics::default_exception_policy // use for compiling and running tests
+>;
+using safe_bool_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 1,
+ pic16_promotion,
+ boost::safe_numerics::default_exception_policy // use for compiling and running tests
+>;
+
+#define DESKTOP
+#include "motor1.c"
+
+#include <chrono>
+#include <thread>
+
+void sleep(int16){
+ std::this_thread::sleep_for(std::chrono::microseconds(ccpr));
+}
+
+int main(){
+ std::cout << "start test\n";
+ try{
+ initialize();
+ motor_run(100);
+ do{
+ isr_motor_step();
+ }while (run_flg);
+
+ // move motor to position 1000
+ motor_run(1000);
+ do{
+ sleep(ccpr);
+ isr_motor_step();
+ }while (run_flg);
+
+ // move back to position 0
+ motor_run(0);
+ do{
+ sleep(ccpr);
+ isr_motor_step();
+ }while (run_flg);
+ }
+ catch(std::exception & e){
+ std::cout << e.what() << '\n';
+ // we expect to trap an exception
+ return 0;
+ }
+ catch(...){
+ std::cout << "test interrupted\n";
+ return 1;
+ }
+ std::cout << "end test\n";
+ return 1;
+}
diff --git a/src/boost/libs/safe_numerics/example/example92.cpp b/src/boost/libs/safe_numerics/example/example92.cpp
new file mode 100644
index 00000000..cec7928f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example92.cpp
@@ -0,0 +1,207 @@
+//////////////////////////////////////////////////////////////////
+// example92.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// 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 <iostream>
+
+// ***************************
+// 1. include headers to support safe integers
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/exception.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+// ***************************
+// 2. specify a promotion policy to support proper emulation of
+// PIC types on the desktop
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char 8 bits
+ 16, // short 16 bits
+ 16, // int 16 bits
+ 16, // long 16 bits
+ 32 // long long 32 bits
+>;
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 (50000 << 8)
+#define C_MIN (2500 << 8)
+
+static_assert(C0 < 0xffffff, "Largest step too long");
+static_assert(C_MIN > 0, "Smallest step must be greater than zero");
+static_assert(C_MIN < C0, "Smallest step must be smaller than largest step");
+
+// ***************************
+// 3. define PIC integer type names to be safe integer types of he same size.
+
+template <typename T> // T is char, int, etc data type
+using safe_t = boost::safe_numerics::safe<
+ T,
+ pic16_promotion
+>;
+
+// alias original program's integer types to corresponding PIC safe types
+// In conjunction with the promotion policy above, this will permit us to
+// guarantee that the resulting program will be free of arithmetic errors
+// introduced by C expression syntax and type promotion with no runtime penalty
+
+typedef safe_t<int8_t> int8;
+typedef safe_t<int16_t> int16;
+typedef safe_t<int32_t> int32;
+typedef safe_t<uint8_t> uint8;
+typedef safe_t<uint16_t> uint16;
+typedef safe_t<uint32_t> uint32;
+
+// ***************************
+// 4. emulate PIC features on the desktop
+
+// filter out special keyword used only by XC8 compiler
+#define __interrupt
+// filter out XC8 enable/disable global interrupts
+#define ei()
+#define di()
+
+// emulate PIC special registers
+uint8 RCON;
+uint8 INTCON;
+uint8 CCP1IE;
+uint8 CCP2IE;
+uint8 PORTC;
+uint8 TRISC;
+uint8 T3CON;
+uint8 T1CON;
+
+uint8 CCPR2H;
+uint8 CCPR2L;
+uint8 CCPR1H;
+uint8 CCPR1L;
+uint8 CCP1CON;
+uint8 CCP2CON;
+uint8 TMR1H;
+uint8 TMR1L;
+
+// create type used to map PIC bit names to
+// correct bit in PIC register
+template<typename T, std::int8_t N>
+struct bit {
+ T & m_word;
+ constexpr explicit bit(T & rhs) :
+ m_word(rhs)
+ {}
+ constexpr bit & operator=(int b){
+ if(b != 0)
+ m_word |= (1 << N);
+ else
+ m_word &= ~(1 << N);
+ return *this;
+ }
+ constexpr operator int () const {
+ return m_word >> N & 1;
+ }
+};
+
+// define bits for T1CON register
+struct {
+ bit<uint8, 7> RD16{T1CON};
+ bit<uint8, 5> T1CKPS1{T1CON};
+ bit<uint8, 4> T1CKPS0{T1CON};
+ bit<uint8, 3> T1OSCEN{T1CON};
+ bit<uint8, 2> T1SYNC{T1CON};
+ bit<uint8, 1> TMR1CS{T1CON};
+ bit<uint8, 0> TMR1ON{T1CON};
+} T1CONbits;
+
+// define bits for T1CON register
+struct {
+ bit<uint8, 7> GEI{INTCON};
+ bit<uint8, 5> PEIE{INTCON};
+ bit<uint8, 4> TMR0IE{INTCON};
+ bit<uint8, 3> RBIE{INTCON};
+ bit<uint8, 2> TMR0IF{INTCON};
+ bit<uint8, 1> INT0IF{INTCON};
+ bit<uint8, 0> RBIF{INTCON};
+} INTCONbits;
+
+// ***************************
+// 5. include the environment independent code we want to test
+#include "motor2.c"
+
+#include <chrono>
+#include <thread>
+
+// round 24.8 format to microseconds
+int32 to_microseconds(uint32 t){
+ return (t + 128) / 256;
+}
+
+using result_t = uint8_t;
+const result_t success = 1;
+const result_t fail = 0;
+
+// move motor to the indicated target position in steps
+result_t test(int32 m){
+ try {
+ std::cout << "move motor to " << m << '\n';
+ motor_run(m);
+ std::cout
+ << "step #" << ' '
+ << "delay(us)(24.8)" << ' '
+ << "delay(us)" << ' '
+ << "CCPR" << ' '
+ << "motor position" << '\n';
+ do{
+ std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
+ uint32 last_c = c;
+ uint32 last_ccpr = ccpr;
+ isr_motor_step();
+ std::cout
+ << step_no << ' '
+ << last_c << ' '
+ << to_microseconds(last_c) << ' '
+ << std::hex << last_ccpr << std::dec << ' '
+ << motor_pos << '\n';
+ }while(run_flg);
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << '\n';
+ return fail;
+ }
+ return success;
+}
+
+int main(){
+ std::cout << "start test\n";
+ result_t result = success;
+ try{
+ initialize();
+ // move motor to position 1000
+ result &= test(1000);
+ // move motor to position 200
+ result &= test(200);
+ // move motor to position 200 again! Should result in no movement.
+ result &= test(200);
+ // move back to position 0
+ result &= test(0);
+ // ***************************
+ // 6. error detected here! data types can't handle enough
+ // steps to move the carriage from end to end! Suppress this
+ // test for now.
+ // move motor to position 50000.
+// result &= test(50000);
+ // move motor back to position 0.
+ result &= test(0);
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << '\n';
+ return 1;
+ }
+ catch(...){
+ std::cout << "test interrupted\n";
+ return EXIT_FAILURE;
+ }
+ std::cout << "end test\n";
+ return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/boost/libs/safe_numerics/example/example93.cpp b/src/boost/libs/safe_numerics/example/example93.cpp
new file mode 100644
index 00000000..658c6316
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example93.cpp
@@ -0,0 +1,299 @@
+//////////////////////////////////////////////////////////////////
+// example93.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// 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 <iostream>
+
+// include headers to support safe integers
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/exception.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+// use same type promotion as used by the pic compiler
+// target compiler XC8 supports:
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char 8 bits
+ 16, // short 16 bits
+ 16, // int 16 bits
+ 16, // long 16 bits
+ 32 // long long 32 bits
+>;
+
+// ***************************
+// 1. Specify exception policies so we will generate a
+// compile time error whenever an operation MIGHT fail.
+
+// ***************************
+// generate runtime errors if operation could fail
+using exception_policy = boost::safe_numerics::default_exception_policy;
+
+// generate compile time errors if operation could fail
+using trap_policy = boost::safe_numerics::loose_trap_policy;
+
+// ***************************
+// 2. Create a macro named literal an integral value
+// that can be evaluated at compile time.
+#define literal(n) make_safe_literal(n, pic16_promotion, void)
+
+// For min speed of 2 mm / sec (24.8 format)
+// sec / step = sec / 2 mm * 2 mm / rotation * rotation / 200 steps
+#define C0 literal(5000 << 8)
+
+// For max speed of 400 mm / sec
+// sec / step = sec / 400 mm * 2 mm / rotation * rotation / 200 steps
+#define C_MIN literal(25 << 8)
+
+static_assert(
+ C0 < make_safe_literal(0xffffff, pic16_promotion,trap_policy),
+ "Largest step too long"
+);
+static_assert(
+ C_MIN > make_safe_literal(0, pic16_promotion,trap_policy),
+ "Smallest step must be greater than zero"
+);
+
+// ***************************
+// 3. Create special ranged types for the motor program
+// These wiil guarantee that values are in the expected
+// ranges and permit compile time determination of when
+// exceptional conditions might occur.
+
+using pic_register_t = boost::safe_numerics::safe<
+ uint8_t,
+ pic16_promotion,
+ trap_policy // use for compiling and running tests
+>;
+
+// note: the maximum value of step_t would be:
+// 50000 = 500 mm / 2 mm/rotation * 200 steps/rotation.
+// But in one expression the value of number of steps * 4 is
+// used. To prevent introduction of error, permit this
+// type to hold the larger value.
+using step_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 200000,
+ pic16_promotion,
+ exception_policy
+>;
+
+// position
+using position_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 50000, // 500 mm / 2 mm/rotation * 200 steps/rotation
+ pic16_promotion,
+ exception_policy
+>;
+
+// next end of step timer value in format 24.8
+// where the .8 is the number of bits in the fractional part.
+using ccpr_t = boost::safe_numerics::safe<
+ uint32_t,
+ pic16_promotion,
+ exception_policy
+>;
+
+// pulse length in format 24.8
+// note: this value is constrainted to be a positive value. But
+// we still need to make it a signed type. We get an arithmetic
+// error when moving to a negative step number.
+using c_t = boost::safe_numerics::safe_unsigned_range<
+ C_MIN,
+ C0,
+ pic16_promotion,
+ exception_policy
+>;
+
+// index into phase table
+// note: The legal values are 0-3. So why must this be a signed
+// type? Turns out that expressions like phase_ix + d
+// will convert both operands to unsigned. This in turn will
+// create an exception. So leave it signed even though the
+// value is greater than zero.
+using phase_ix_t = boost::safe_numerics::safe_signed_range<
+ 0,
+ 3,
+ pic16_promotion,
+ trap_policy
+>;
+
+// settings for control value output
+using phase_t = boost::safe_numerics::safe<
+ uint16_t,
+ pic16_promotion,
+ trap_policy
+>;
+
+// direction of rotation
+using direction_t = boost::safe_numerics::safe_signed_range<
+ -1,
+ +1,
+ pic16_promotion,
+ trap_policy
+>;
+
+// some number of microseconds
+using microseconds = boost::safe_numerics::safe<
+ uint32_t,
+ pic16_promotion,
+ trap_policy
+>;
+
+// ***************************
+// emulate PIC features on the desktop
+
+// filter out special keyword used only by XC8 compiler
+#define __interrupt
+// filter out XC8 enable/disable global interrupts
+#define ei()
+#define di()
+
+// emulate PIC special registers
+pic_register_t RCON;
+pic_register_t INTCON;
+pic_register_t CCP1IE;
+pic_register_t CCP2IE;
+pic_register_t PORTC;
+pic_register_t TRISC;
+pic_register_t T3CON;
+pic_register_t T1CON;
+
+pic_register_t CCPR2H;
+pic_register_t CCPR2L;
+pic_register_t CCPR1H;
+pic_register_t CCPR1L;
+pic_register_t CCP1CON;
+pic_register_t CCP2CON;
+pic_register_t TMR1H;
+pic_register_t TMR1L;
+
+// ***************************
+// special checked type for bits - values restricted to 0 or 1
+using safe_bit_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 1,
+ pic16_promotion,
+ trap_policy
+>;
+
+// create type used to map PIC bit names to
+// correct bit in PIC register
+template<typename T, std::int8_t N>
+struct bit {
+ T & m_word;
+ constexpr explicit bit(T & rhs) :
+ m_word(rhs)
+ {}
+ // special functions for assignment of literal
+ constexpr bit & operator=(decltype(literal(1))){
+ m_word |= literal(1 << N);
+ return *this;
+ }
+ constexpr bit & operator=(decltype(literal(0))){
+ m_word &= ~literal(1 << N);
+ return *this;
+ }
+ // operator to convert to 0 or 1
+ constexpr operator safe_bit_t () const {
+ return m_word >> literal(N) & literal(1);
+ }
+};
+
+// define bits for T1CON register
+struct {
+ bit<pic_register_t, 7> RD16{T1CON};
+ bit<pic_register_t, 5> T1CKPS1{T1CON};
+ bit<pic_register_t, 4> T1CKPS0{T1CON};
+ bit<pic_register_t, 3> T1OSCEN{T1CON};
+ bit<pic_register_t, 2> T1SYNC{T1CON};
+ bit<pic_register_t, 1> TMR1CS{T1CON};
+ bit<pic_register_t, 0> TMR1ON{T1CON};
+} T1CONbits;
+
+// define bits for T1CON register
+struct {
+ bit<pic_register_t, 7> GEI{INTCON};
+ bit<pic_register_t, 5> PEIE{INTCON};
+ bit<pic_register_t, 4> TMR0IE{INTCON};
+ bit<pic_register_t, 3> RBIE{INTCON};
+ bit<pic_register_t, 2> TMR0IF{INTCON};
+ bit<pic_register_t, 1> INT0IF{INTCON};
+ bit<pic_register_t, 0> RBIF{INTCON};
+} INTCONbits;
+
+#include "motor3.c"
+
+#include <chrono>
+#include <thread>
+
+// round 24.8 format to microseconds
+microseconds to_microseconds(ccpr_t t){
+ return (t + literal(128)) / literal(256);
+}
+
+using result_t = uint8_t;
+const result_t success = 1;
+const result_t fail = 0;
+
+// move motor to the indicated target position in steps
+result_t test(position_t new_position){
+ try {
+ std::cout << "move motor to " << new_position << '\n';
+ motor_run(new_position);
+ std::cout
+ << "step #" << ' '
+ << "delay(us)(24.8)" << ' '
+ << "delay(us)" << ' '
+ << "CCPR" << ' '
+ << "motor position" << '\n';
+ while(busy()){
+ std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
+ c_t last_c = c;
+ ccpr_t last_ccpr = ccpr;
+ isr_motor_step();
+ std::cout << i << ' '
+ << last_c << ' '
+ << to_microseconds(last_c) << ' '
+ << std::hex << last_ccpr << std::dec << ' '
+ << motor_position << '\n';
+ };
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << '\n';
+ return fail;
+ }
+ return success;
+}
+
+int main(){
+ std::cout << "start test\n";
+ result_t result = success;
+ try {
+ initialize();
+ // move motor to position 1000
+ result &= test(literal(1000));
+ // move to the left before zero position
+ // fails to compile !
+ // result &= ! test(-10);
+ // move motor to position 200
+ result &= test(literal(200));
+ // move motor to position 200 again! Should result in no movement.
+ result &= test(literal(200));
+ // move motor to position 50000.
+ result &= test(literal(50000));
+ // move motor back to position 0.
+ result &= test(literal(0));
+ }
+ catch(...){
+ std::cout << "test interrupted\n";
+ return EXIT_FAILURE;
+ }
+ std::cout << "end test\n";
+ return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/boost/libs/safe_numerics/example/motor1.c b/src/boost/libs/safe_numerics/example/motor1.c
new file mode 100644
index 00000000..d8fb51b9
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor1.c
@@ -0,0 +1,152 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * 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)
+ */
+
+// ramp state-machine states
+enum ramp_state {
+ ramp_idle = 0,
+ ramp_up = 1,
+ ramp_max = 2,
+ ramp_down = 3,
+ ramp_last = 4,
+};
+
+enum ramp_state ramp_sts=ramp_idle;
+int16 motor_pos = 0; // absolute step number
+int16 pos_inc=0; // motor_pos increment
+uint16 phase=0; // ccpPhase[phase_ix]
+uint8 phase_ix=0; // index to ccpPhase[]
+uint8 phase_inc; // phase_ix increment
+uint8 run_flg; // true while motor is running
+uint16 ccpr; // copy of CCPR1&2
+uint16 c; // integer delay count
+uint16 step_no; // progress of move
+uint16 step_down; // start of down-ramp
+uint16 move; // total steps to move
+uint16 midpt; // midpoint of move
+uint32 c32; // 24.8 fixed point delay count
+int16 denom; // 4.n+1 in ramp algo
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+uint16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+uint16 make16(uint8 l, uint8 r) {
+ return (uint16) l << 8 + r;
+}
+
+// compiler-specific ISR declaration
+
+void __interrupt isr_motor_step(void) { // CCP1 match -> step pulse + IRQ
+ ccpr += c; // next comparator value
+ switch (ramp_sts) {
+ case ramp_up: // accel
+ if (step_no == midpt) { // midpoint: decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move) << 2) + 1;
+ if (!(move & 1)) { // even move: repeat last delay before decel
+ denom += 4;
+ break;
+ }
+ }
+ // no break: share code for ramp algo
+ case ramp_down: // decel
+ if (step_no == move - 1) { // next irq is cleanup (no step)
+ ramp_sts = ramp_last;
+ break;
+ }
+ denom += 4;
+ c32 -= (c32 << 1) / denom; // ramp algorithm
+ // beware confict with foreground code if long div not reentrant
+ c = (c32 + 128) >> 8; // round 24.8format->int16
+ if (c <= C_MIN) { // go to constant speed
+ ramp_sts = ramp_max;
+ step_down = move - step_no;
+ c = C_MIN;
+ break;
+ }
+ break;
+ case ramp_max: // constant speed
+ if (step_no == step_down) { // start decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move) << 2) + 5;
+ }
+ break;
+ default: // last step: cleanup
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ run_flg = false; // move complete
+ break;
+ } // switch (ramp_sts)
+ if (ramp_sts != ramp_idle) {
+ motor_pos += pos_inc;
+ ++step_no;
+ CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ if (ramp_sts != ramp_last) // else repeat last action: no step
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // set CCP action on next match
+ CCP2CON = phase >> 8;
+ } // if (ramp_sts != ramp_idle)
+} // isr_motor_step()
+
+void motor_run(int16 pos_new) { // set up to drive motor to pos_new (absolute step#)
+ if (pos_new < motor_pos) { // get direction & #steps
+ move = motor_pos - pos_new;
+ pos_inc = -1;
+ phase_inc = 0xff;
+ }
+ else if (pos_new != motor_pos) {
+ move = pos_new - motor_pos;
+ pos_inc = 1;
+ phase_inc = 1;
+ } else return; // already there
+ midpt = (move - 1) >> 1;
+ c = C0;
+ c32 = c << 8; // keep c in 24.8 fixed-point format for ramp calcs
+ step_no = 0; // step counter
+ denom = 1; // 4.n+1, n=0
+ ramp_sts = ramp_up; // start ramp state-machine
+ run_flg = true;
+ T1CONbits.TMR1ON = 0; // stop timer1;
+ ccpr = make16(TMR1H, TMR1L); // 16bit value of Timer1
+ ccpr += 1000; // 1st step + irq 1ms after timer1 restart
+ CCPR2H = CCPR1H = (ccpr >> 8);
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // sets action on match
+ CCP2CON = phase >> 8;
+ current_on(); // current in motor windings
+ CCP1IE = 1; // enable_interrupts(INT_CCP1);
+ T1CONbits.TMR1ON = 1; // restart timer1;
+} // motor_run()
+
+void initialize() {
+ di(); // disable_interrupts(GLOBAL);
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ CCP2IE = 0; // disable_interrupts(INT_CCP2);
+ PORTC = 0; // output_c(0);
+ TRISC = 0; // set_tris_c(0);
+ T3CON = 0;
+ T1CON = 0x35;
+ INTCONbits.PEIE = 1;
+ INTCONbits.RBIF = 0;
+ ei(); // enable_interrupts(GLOBAL);
+} // initialize()
diff --git a/src/boost/libs/safe_numerics/example/motor2.c b/src/boost/libs/safe_numerics/example/motor2.c
new file mode 100644
index 00000000..78e08fef
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor2.c
@@ -0,0 +1,169 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * 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)
+ */
+
+// ramp state-machine states
+enum ramp_state {
+ ramp_idle = 0,
+ ramp_up = 1,
+ ramp_max = 2,
+ ramp_down = 3,
+ ramp_last = 4,
+};
+
+enum ramp_state ramp_sts=ramp_idle;
+int16 motor_pos = 0; // absolute step number
+int16 pos_inc=0; // motor_pos increment
+uint16 phase=0; // ccpPhase[phase_ix]
+uint8 phase_ix=0; // index to ccpPhase[]
+uint8 phase_inc; // phase_ix increment
+uint8 run_flg; // true while motor is running
+// ***************************
+// 1. keep track of total delay count
+uint32 ccpr; // 24.8 fixed point delay count
+uint32 c; // 24.8 fixed point delay count increment
+uint16 step_no; // progress of move
+uint16 step_down; // start of down-ramp
+uint16 move; // total steps to move
+uint16 midpt; // midpoint of move
+int16 denom; // 4.n+1 in ramp algo
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+uint16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+uint16 make16(uint8 l, uint8 r) {
+ return (uint16) l << 8 + r;
+}
+
+// compiler-specific ISR declaration
+
+void __interrupt isr_motor_step(void) { // CCP1 match -> step pulse + IRQ
+ ccpr += c; // next comparator value
+ switch (ramp_sts) {
+ case ramp_up: // accel
+ if (step_no == midpt) { // midpoint: decel
+ ramp_sts = ramp_down;
+ // ***************************
+ // 2. convert shift to multiplication
+ // 3. avoid negative result from subtraction of unsigned values
+ // denom = ((step_no - move) << 2) + 1;
+ if(step_no > move)
+ denom = ((step_no - move) * 4) + 1;
+ else
+ denom = ((move - step_no) * 4) - 1;
+ if (!(move & 1)) { // even move: repeat last delay before decel
+ denom += 4;
+ break;
+ }
+ }
+ // no break: share code for ramp algo
+ case ramp_down: // decel
+ if (step_no == move - 1) { // next irq is cleanup (no step)
+ ramp_sts = ramp_last;
+ break;
+ }
+ denom += 4;
+ // calculate increment/decrement in delay count
+ // ***************************
+ // 3. avoid negative result from subtraction of unsigned values
+ // c -= (c << 1) / denom; // ramp algorithm
+ if(denom > 0)
+ c -= (c << 1) / denom;
+ else
+ c += (c << 1) / -denom;
+
+ if (c <= C_MIN) { // go to constant speed
+ ramp_sts = ramp_max;
+ step_down = move - step_no;
+ c = C_MIN;
+ break;
+ }
+ break;
+ case ramp_max: // constant speed
+ if (step_no == step_down) { // start decel
+ ramp_sts = ramp_down;
+ // ***************************
+ // 2. convert shift to multiplication
+ // 3. avoid negative result from subtraction of unsigned values
+ // denom = ((step_no - move) << 2) + 1;
+ denom = 5 - ((move - step_no) * 4);
+ }
+ break;
+ default: // last step: cleanup
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ run_flg = false; // move complete
+ break;
+ } // switch (ramp_sts)
+ if (ramp_sts != ramp_idle) {
+ motor_pos += pos_inc;
+ ++step_no;
+ CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ if (ramp_sts != ramp_last) // else repeat last action: no step
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // set CCP action on next match
+ CCP2CON = phase >> 8;
+ } // if (ramp_sts != ramp_idle)
+} // isr_motor_step()
+
+void motor_run(int16 pos_new) { // set up to drive motor to pos_new (absolute step#)
+ if (pos_new < motor_pos) { // get direction & #steps
+ move = motor_pos - pos_new;
+ pos_inc = -1;
+ phase_inc = 0xff;
+ }
+ else if (pos_new != motor_pos) {
+ move = pos_new - motor_pos;
+ pos_inc = 1;
+ phase_inc = 1;
+ } else return; // already there
+ midpt = (move - 1) >> 1;
+ c = C0;
+ step_no = 0; // step counter
+ denom = 1; // 4.n+1, n=0
+ ramp_sts = ramp_up; // start ramp state-machine
+ run_flg = true;
+ T1CONbits.TMR1ON = 0; // stop timer1;
+ ccpr = make16(TMR1H, TMR1L); // 16bit value of Timer1
+ ccpr += 1000; // 1st step + irq 1ms after timer1 restart
+ CCPR2H = CCPR1H = (ccpr >> 8);
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // sets action on match
+ CCP2CON = phase >> 8;
+ current_on(); // current in motor windings
+ CCP1IE = 1; // enable_interrupts(INT_CCP1);
+ T1CONbits.TMR1ON = 1; // restart timer1;
+} // motor_run()
+
+void initialize() {
+ di(); // disable_interrupts(GLOBAL);
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ CCP2IE = 0; // disable_interrupts(INT_CCP2);
+ PORTC = 0; // output_c(0);
+ TRISC = 0; // set_tris_c(0);
+ T3CON = 0;
+ T1CON = 0x35;
+ INTCONbits.PEIE = 1;
+ INTCONbits.RBIF = 0;
+ ei(); // enable_interrupts(GLOBAL);
+} // initialize()
diff --git a/src/boost/libs/safe_numerics/example/motor3.c b/src/boost/libs/safe_numerics/example/motor3.c
new file mode 100644
index 00000000..c6175d36
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor3.c
@@ -0,0 +1,195 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * 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 <assert.h>
+
+// ramp state-machine states
+enum ramp_state {
+ ramp_idle = 0,
+ ramp_up = 1,
+ ramp_const = 2,
+ ramp_down = 3,
+};
+
+// ***************************
+// 1. Define state variables using custom strong types
+
+// initial setup
+enum ramp_state ramp_sts;
+position_t motor_position;
+position_t m; // target position
+position_t m2; // midpoint or point where acceleration changes
+direction_t d; // direction of traval -1 or +1
+
+// curent state along travel
+step_t i; // step number
+c_t c; // 24.8 fixed point delay count increment
+ccpr_t ccpr; // 24.8 fixed point delay count
+phase_ix_t phase_ix; // motor phase index
+
+// ***************************
+// 2. Surround all literal values with the "literal" keyword
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+phase_t const ccpPhase[] = {
+ literal(0x909),
+ literal(0x908),
+ literal(0x808),
+ literal(0x809)
+}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+// ***************************
+// 3. Refactor code to make it easier to understand
+// and relate to the documentation
+
+bool busy(){
+ return ramp_idle != ramp_sts;
+}
+
+// set outputs to energize motor coils
+void update(ccpr_t ccpr, phase_ix_t phase_ix){
+ // energize correct windings
+ const phase_t phase = ccpPhase[phase_ix];
+ CCP1CON = phase & literal(0xff); // set CCP action on next match
+ CCP2CON = phase >> literal(8);
+ // timer value at next CCP match
+ CCPR1H = literal(0xff) & (ccpr >> literal(8));
+ CCPR1L = literal(0xff) & ccpr;
+}
+
+// compiler-specific ISR declaration
+// ***************************
+// 4. Rewrite interrupt handler in a way which mirrors the orginal
+// description of the algorithm and minimizes usage of state variable,
+// accumulated values, etc.
+void __interrupt isr_motor_step(void) { // CCP1 match -> step pulse + IRQ
+ // *** possible exception
+ // motor_position += d;
+ // use the following to avoid mixing exception policies which is an error
+ if(d < 0)
+ --motor_position;
+ else
+ ++motor_position;
+ // *** possible exception
+ ++i;
+ // calculate next difference in time
+ for(;;){
+ switch (ramp_sts) {
+ case ramp_up: // acceleration
+ if (i == m2) {
+ ramp_sts = ramp_down;
+ continue;
+ }
+ // equation 13
+ // *** possible negative overflow on update of c
+ c -= literal(2) * c / (literal(4) * i + literal(1));
+ if(c < C_MIN){
+ c = C_MIN;
+ ramp_sts = ramp_const;
+ // *** possible exception
+ m2 = m - i; // new inflection point
+ continue;
+ }
+ break;
+ case ramp_const: // constant speed
+ if(i > m2) {
+ ramp_sts = ramp_down;
+ continue;
+ }
+ break;
+ case ramp_down: // deceleration
+ if (i == m) {
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ CCP1IE = literal(0); // disable_interrupts(INT_CCP1);
+ return;
+ }
+ // equation 14
+ // *** possible positive overflow on update of c
+ // note: re-arrange expression to avoid negative result
+ // from difference of two unsigned values
+ c += literal(2) * c / (literal(4) * (m - i) - literal(1));
+ if(c > C0){
+ c = C0;
+ }
+ break;
+ default:
+ // should never arrive here!
+ assert(false);
+ } // switch (ramp_sts)
+ break;
+ }
+ assert(c <= C0 && c >= C_MIN);
+ // *** possible exception
+ ccpr = literal(0xffffff) & (ccpr + c);
+ phase_ix = (phase_ix + d) & literal(3);
+ update(ccpr, phase_ix);
+} // isr_motor_step()
+
+// set up to drive motor to pos_new (absolute step#)
+void motor_run(position_t new_position) {
+ if(new_position > motor_position){
+ d = literal(1);
+ // *** possible exception
+ m = new_position - motor_position;
+ }
+ else
+ if(motor_position > new_position){
+ d = literal(-1);
+ // *** possible exception
+ m = motor_position - new_position;
+ }
+ else{
+ d = literal(0);
+ m = literal(0);
+ ramp_sts = ramp_idle; // start ramp state-machine
+ return;
+ }
+
+ i = literal(0);
+ m2 = m / literal(2);
+
+ ramp_sts = ramp_up; // start ramp state-machine
+
+ T1CONbits.TMR1ON = literal(0); // stop timer1;
+
+ current_on(); // current in motor windings
+
+ c = C0;
+ ccpr = (TMR1H << literal(8) | TMR1L) + C0 + literal(1000);
+ phase_ix = d & literal(3);
+ update(ccpr, phase_ix);
+
+ CCP1IE = literal(1); // enable_interrupts(INT_CCP1);
+ T1CONbits.TMR1ON = literal(1); // restart timer1;
+} // motor_run()
+
+void initialize() {
+ di(); // disable_interrupts(GLOBAL);
+ motor_position = literal(0);
+ CCP1IE = literal(0); // disable_interrupts(INT_CCP1);
+ CCP2IE = literal(0); // disable_interrupts(INT_CCP2);
+ PORTC = literal(0); // output_c(0);
+ TRISC = literal(0); // set_tris_c(0);
+ T3CON = literal(0);
+ T1CON = literal(0x35);
+ INTCONbits.PEIE = literal(1);
+ INTCONbits.RBIF = literal(0);
+ ei(); // enable_interrupts(GLOBAL);
+} // initialize()
diff --git a/src/boost/libs/safe_numerics/example/motor_test1.c b/src/boost/libs/safe_numerics/example/motor_test1.c
new file mode 100644
index 00000000..afe54cb7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor_test1.c
@@ -0,0 +1,44 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Compile with on Microchip XC8 compiler with the command line:
+ * XC8 --chip=18F252 motor_test1.c
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * 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 <xc.h>
+#include <stdint.h>
+#include <stdbool.h> /* For true/false definition */
+
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 (50000 << 8)
+#define C_MIN (2500 << 8)
+
+#include "motor1.c"
+
+void main() {
+ initialize();
+ while (1) { // repeat 5 revs forward & back
+ motor_run(1000);
+ while (run_flg);
+ motor_run(0);
+ while (run_flg);
+ }
+} // main()
diff --git a/src/boost/libs/safe_numerics/example/motor_test2.c b/src/boost/libs/safe_numerics/example/motor_test2.c
new file mode 100644
index 00000000..23f70576
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor_test2.c
@@ -0,0 +1,48 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Compile with on Microchip XC8 compiler with the command line:
+ * XC8 --chip=18F252 motor_test2.c
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * 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 <xc.h>
+#include <stdint.h>
+#include <stdbool.h> /* For true/false definition */
+
+// ***************************
+// alias integer types standard C integer types
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 (50000*8l)
+#define C_MIN (2500*8)
+
+#include "motor2.c"
+
+void main() {
+ initialize();
+ while (1) { // repeat 5 revs forward & back
+ motor_run(1000);
+ while (run_flg);
+ motor_run(0);
+ while (run_flg);
+ motor_run(50000);
+ while (run_flg);
+ }
+} // main()
diff --git a/src/boost/libs/safe_numerics/example/motor_test3.c b/src/boost/libs/safe_numerics/example/motor_test3.c
new file mode 100644
index 00000000..0ef5a022
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor_test3.c
@@ -0,0 +1,58 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Compile with on Microchip XC8 compiler with the command line:
+ * XC8 --chip=18F252 motor_test3.c
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * 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 <xc.h>
+
+// 8 MHz internal clock
+#define _XTAL_FREQ 8000000
+
+#include <stdint.h>
+#include <stdbool.h> /* For true/false definition */
+
+// ***************************
+// nullify macro for literals
+#define literal(n) n
+
+// ***************************
+// map strong types to appropriate underlying types.
+typedef uint16_t position_t;
+typedef int16_t step_t;
+typedef uint32_t ccpr_t;
+typedef int32_t c_t;
+typedef uint16_t phase_t;
+typedef uint8_t phase_ix_t;
+typedef int8_t direction_t;
+
+// 1st step=10ms; max speed=300rpm (based on 1MHz timer, 1.8deg steps)
+#define C_MIN literal((1000 << 8))
+#define C0 literal((10000 << 8))
+
+#include "motor3.c"
+
+void main() {
+ initialize();
+ // move motor to position 200
+ motor_run(200);
+ while(busy()) __delay_ms(100);
+ // move motor to position 1000
+ motor_run(1000);
+ while(busy()) __delay_ms(100);
+ // move back to position 0
+ motor_run(200);
+ while(busy()) __delay_ms(100);
+} // main()
diff --git a/src/boost/libs/safe_numerics/example/picsfr.h b/src/boost/libs/safe_numerics/example/picsfr.h
new file mode 100644
index 00000000..a100731c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/picsfr.h
@@ -0,0 +1,29 @@
+//////////////////////////////////////////////////////////////////
+// picsfr.h
+// Copyright (c) 2015 Robert Ramey
+//
+// 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)
+//
+// Put these in a separate file so they can conditionally included.
+// This is necessary since their mere inclusion will cause syntax
+// errors on some compilers.
+
+#ifndef PICSFR_H
+#define PICSFR_H
+
+#byte TRISC = 0xf94
+#byte T3CON = 0xfb1
+#byte CCP2CON = 0xfba
+#byte CCPR2L = 0xfbb
+#byte CCPR2H = 0xfbc
+#byte CCP1CON = 0xfbd
+#byte CCPR1L = 0xfbe
+#byte CCPR1H = 0xfbf
+#byte T1CON = 0xfcd
+#byte TMR1L = 0xfce
+#byte TMR1H = 0xfcf
+#bit TMR1ON = T1CON.0
+
+#endif // PICSFR_H
diff --git a/src/boost/libs/safe_numerics/example/safe_format.hpp b/src/boost/libs/safe_numerics/example/safe_format.hpp
new file mode 100644
index 00000000..317c2201
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/safe_format.hpp
@@ -0,0 +1,52 @@
+#ifndef BOOST_SAFE_FORMAT_HPP
+#define BOOST_SAFE_FORMAT_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// 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 <ostream>
+#include <typeinfo>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/safe_common.hpp>
+
+namespace {
+
+// create an output manipulator which prints variable type and limits
+// as well as value
+template<typename T>
+struct safe_format_impl {
+ const T & m_t;
+ safe_format_impl(const T & t) :
+ m_t(t)
+ {}
+ template <class charT, class Traits>
+ friend std::basic_ostream<charT,Traits> &
+ operator<<(
+ std::basic_ostream<charT,Traits> & os,
+ const safe_format_impl<T> & f
+ ){
+ return os
+ << "<"
+ << boost::core::demangle(typeid(
+ typename boost::safe_numerics::base_type<T>::type
+ ).name()
+ )
+ << ">["
+ << std::numeric_limits<T>::min() << ","
+ << std::numeric_limits<T>::max() << "] = "
+ << f.m_t;
+ }
+};
+
+} // anonymous namespace
+
+template<typename T>
+auto safe_format(const T & t){
+ return safe_format_impl<T>(t);
+}
+
+#endif // BOOST_SAFE_FORMAT_HPP
diff --git a/src/boost/libs/safe_numerics/example/stepper-motor.pdf b/src/boost/libs/safe_numerics/example/stepper-motor.pdf
new file mode 100644
index 00000000..7088a779
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/stepper-motor.pdf
Binary files differ