diff --git a/CMake/CMakeLists.txt b/CMake/CMakeLists.txt index ef38f98..7977945 100644 --- a/CMake/CMakeLists.txt +++ b/CMake/CMakeLists.txt @@ -215,7 +215,7 @@ set_target_properties(test_z example84 PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE ) -set_target_properties(example81 PROPERTIES +set_target_properties(example81 example91 example92 PROPERTIES WILL_FAIL TRUE ) diff --git a/examples/18F252_desktop.h b/examples/18F252_desktop.h index bb531fb..0950a69 100644 --- a/examples/18F252_desktop.h +++ b/examples/18F252_desktop.h @@ -72,6 +72,14 @@ struct bit { } }; +#if ! defined(literal) +// define a macro for literal types. This may not be strictly necessary +// but it provides more information at compile time to the safe numerics +// library which may result in faster code. +//#define literal(x) boost::numeric::safe_literal{} +#define literal(x) x +#endif + // make a 16 bit value from two 8 bit ones int16 inline make16(int8 h, int8 l){ return (h << literal(8)) | l; diff --git a/examples/example9.cpp b/examples/example9.cpp deleted file mode 100644 index f24bd63..0000000 --- a/examples/example9.cpp +++ /dev/null @@ -1,343 +0,0 @@ -////////////////////////////////////////////////////////////////// -// test wrapper to permit compilation execution and debug of code -// intended for the PIC family of processors on the desktop -// development environment. -// -// Robert Ramey, 2015 - -#include -#include - -#include "../include/cpp.hpp" -#include "../include/automatic.hpp" -#include "../include/exception.hpp" -#include "../include/safe_integer.hpp" -#include "../include/safe_range.hpp" -#include "../include/safe_literal.hpp" - -using pic16_promotion = boost::numeric::cpp< - 8, // char - 8, // short - 8, // int - 16, // long - 32 // long long ->; - -template // T is char, int, etc data type -using safe_t = boost::numeric::safe< - T, - boost::numeric::automatic, - boost::numeric::trap_exception // use for compiling and running tests ->; -using safe_bool_t = boost::numeric::safe_unsigned_range< - 0, - 1, - pic16_promotion, - boost::numeric::trap_exception // use for compiling and running tests ->; - -using int8 = safe_t; -using int16 = safe_t; -using int32 = safe_t; -using uint8 = safe_t; -using uint16 = safe_t; -using uint32 = safe_t; -using signed_int16 = safe_t; - -#define literal(x) boost::numeric::safe_literal{} - -std::uint8_t base[0xfff]; -#define TRISC base[0xf94] -#define T3CON base[0xfb1] -#define CCP2CON base[0xfba] -#define CCPR2L base[0xfbb] -#define CCPR2H base[0xfbc] -#define CCP1CON base[0xfbd] -#define CCPR1L base[0xfbe] -#define CCPR1H base[0xfbf] -#define T1CON base[0xfcd] -#define TMR1L base[0xfce] -#define TMR1H base[0xfcf] -// implement equivalent to #bit in C++ - -// this types is meant to implement operations of naming bits -// which are part of a larger word. -// example -// unsigned int x. -// bit switch; // switch now refers to the -// second bit from the right of the variable x. So now can use: -// -// switch = 1; -// if(switch) -// ... - -template -struct bit { - T & m_word; - bit(T & rhs) : - m_word(rhs) - {} - bit & operator=(const safe_bool_t & b){ - if(b) - m_word |= (1 << N); - else - m_word &= ~(1 << N); - return *this; - } - bit & operator=(const boost::numeric::safe_literal<0>){ - m_word &= ~(1 << N); - return *this; - } - bit & operator=(const boost::numeric::safe_literal<1>){ - m_word |= (1 << N); - return *this; - } - operator safe_bool_t () const { - return m_word >> N & 1; - } -}; - -// now we can render -//#bit TMR1ON = T1CON.0 -// as -bit TMR1ON(T1CON); -// and use expressions such as TMR1ON = 0 - -// make a 16 bit value from two 8 bit ones -int16 make16(int8 h, int8 l){ - return (h << literal(8)) | l; -} - -#define disable_interrupts(x) -#define enable_interrupts(x) -#define output_c(x) -#define set_tris_c(x) -#define TRUE literal(1) -#define FALSE literal(0) - -// note changes to original source code -// signed int16 <- signed_int16 note '-' added -// commented out the #byte and #bit statements -// commented out the #INT_CCP1 -// void main() <- int main() -// added return 0 to main -// changed instances of x = 0 to x = literal(0) - -////////////////////////////////////////////////////////////////// -// motor.c -// 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 -// #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 literal(50000) -#define C_MIN literal(2500) - -// ramp state-machine states -#define ramp_idle literal(0) -#define ramp_up literal(1) -#define ramp_max literal(2) -#define ramp_down literal(3) -#define ramp_last literal(4) - -// Types: int8,int16,int32=8,16,32bit integers, unsigned by default -int8 ramp_sts=ramp_idle; -signed_int16 motor_pos = literal(0); // absolute step number -signed_int16 pos_inc = literal(0); // motor_pos increment -int16 phase=literal(0); // ccpPhase[phase_ix] -int8 phase_ix=literal(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[] = { - 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 - -// 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) << literal(2) )+literal(1); - - if (!(move & literal(1))) - { // even move: repeat last delay before decel - denom +=literal(4); - break; - } - } - // no break: share code for ramp algo - case ramp_down: // decel - if (step_no == move-literal(1)) - { // next irq is cleanup (no step) - ramp_sts = ramp_last; - break; - } - denom+=4; - c32 -= (c32 << literal(1)) / denom; // ramp algorithm - // beware confict with foreground code if long div not reentrant - c = (c32+literal(128))>>literal(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)<> literal(8)); // timer value at next CCP match - CCPR2L = CCPR1L = (ccpr & literal(0xff)); - if (ramp_sts!=ramp_last) // else repeat last action: no step - phase_ix = (phase_ix + phase_inc) & literal(3); - phase = ccpPhase[phase_ix]; - CCP1CON = phase & literal(0xff); // set CCP action on next match - CCP2CON = phase >> literal(8); - } // if (ramp_sts != ramp_idle) -} // isr_motor_step() - - -void motor_run(signed_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 = literal(-1); - phase_inc = literal(0xff); - } - else if (pos_new != motor_pos) - { - move = pos_new-motor_pos; - pos_inc = literal(1); - phase_inc = literal(1); - } - else return; // already there - /* - midpt = (move-1)>>1; - */ - auto x1 = move - 1; - auto x2 = x1 >> 1; - midpt = x2; - c = C0; - c32 = c<> literal(8)); - CCPR2L = CCPR1L = (ccpr & literal(0xff)); - phase_ix = (phase_ix + phase_inc) & literal(3); - phase = ccpPhase[phase_ix]; - CCP1CON = phase & literal(0xff); // sets action on match - CCP2CON = phase >> literal(8); - current_on(); // current in motor windings - enable_interrupts(INT_CCP1); - TMR1ON=TRUE; // 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() - -// test program -int main() -{ - std::cout << "start test\n"; - try{ - initialize(); - motor_run(literal(100)); - - // move motor to position 1000 - motor_run(literal(1000)); - while (run_flg){ - isr_motor_step(); - } - // move back to position 0 - motor_run(literal(0)); - while (run_flg) - isr_motor_step(); - } - catch(...){ - std::cout << "test interrupted\n"; - return 1; - } - std::cout << "end test\n"; - return literal(0); -} // main() -// end of file motor.c diff --git a/examples/example91.cpp b/examples/example91.cpp index 3efc920..0eec7a2 100644 --- a/examples/example91.cpp +++ b/examples/example91.cpp @@ -46,12 +46,6 @@ using safe_bool_t = boost::numeric::safe_unsigned_range< boost::numeric::throw_exception // use for compiling and running tests >; -// define a macro for literal types. This may not be strictly necessary -// but it provides more information at compile time to the safe numerics -// library which may result in faster code. -//#define literal(x) boost::numeric::safe_literal{} -#define literal(x) x - #define DESKTOP #include "motor1.c" @@ -63,30 +57,34 @@ int main() std::cout << "start test\n"; try{ initialize(); - motor_run(literal(100)); + motor_run(100); do{ std::this_thread::sleep_for(std::chrono::microseconds(ccpr)); isr_motor_step(); }while (run_flg); // move motor to position 1000 - motor_run(literal(1000)); + motor_run(1000); do{ std::this_thread::sleep_for(std::chrono::microseconds(ccpr)); isr_motor_step(); }while (run_flg); // move back to position 0 - motor_run(literal(0)); + motor_run(0); do{ std::this_thread::sleep_for(std::chrono::microseconds(ccpr)); isr_motor_step(); }while (run_flg); } + catch(std::exception & e){ + std::cout << e.what() << '\n'; + return 1; + } catch(...){ std::cout << "test interrupted\n"; return 1; } std::cout << "end test\n"; - return literal(0); + return 0; } \ No newline at end of file diff --git a/examples/example92.cpp b/examples/example92.cpp index f2c8dbe..c587eef 100644 --- a/examples/example92.cpp +++ b/examples/example92.cpp @@ -76,6 +76,10 @@ int main() // move back to position 0 test(0); } + catch(std::exception & e){ + std::cout << e.what() << '\n'; + return 1; + } catch(...){ std::cout << "test interrupted\n"; return 1; diff --git a/examples/example93.cpp b/examples/example93.cpp index 623fbcf..189f015 100644 --- a/examples/example93.cpp +++ b/examples/example93.cpp @@ -37,27 +37,33 @@ using pic16_promotion = boost::numeric::cpp< template // T is char, int, etc data type using safe_t = boost::numeric::safe< T, - boost::numeric::automatic, - boost::numeric::trap_exception // use for compiling and running tests + pic16_promotion, + boost::numeric::throw_exception // use for compiling and running tests >; using safe_bool_t = boost::numeric::safe_unsigned_range< 0, 1, pic16_promotion, - boost::numeric::trap_exception // use for compiling and running tests + boost::numeric::throw_exception // use for compiling and running tests >; using step_t = boost::numeric::safe_signed_range< 0, 1000, - boost::numeric::automatic, - boost::numeric::trap_exception + pic16_promotion, + boost::numeric::throw_exception >; using denom_t = boost::numeric::safe_signed_range< 1, 4001, - boost::numeric::automatic, - boost::numeric::trap_exception + pic16_promotion, + boost::numeric::throw_exception +>; +using phase_ix_t = boost::numeric::safe_unsigned_range< + 0, + 3, + pic16_promotion, + boost::numeric::throw_exception >; #define literal(x) boost::numeric::safe_literal{} @@ -68,7 +74,7 @@ using denom_t = boost::numeric::safe_signed_range< #include #include -void test(int16 m){ +void test(step_t m){ std::cout << "move motor to " << m << '\n'; int i = 0; motor_run(m); @@ -76,7 +82,7 @@ void test(int16 m){ isr_motor_step(); std::cout << ++i << ' ' << c32 << ' ' << c << '\n'; std::this_thread::sleep_for(std::chrono::microseconds(ccpr)); - }while(run_flg); + }while(true == run_flg); } int main() @@ -85,11 +91,15 @@ int main() try{ initialize(); // move motor to position 100 - test(100); + test(literal(100)); // move motor to position 1000 //test(1000); // move back to position 0 - test(0); + test(literal(0)); + } + catch(std::exception & e){ + std::cout << e.what() << '\n'; + return 1; } catch(...){ std::cout << "test interrupted\n"; diff --git a/examples/motor3.c b/examples/motor3.c index eb50cd7..8316c48 100644 --- a/examples/motor3.c +++ b/examples/motor3.c @@ -33,6 +33,7 @@ // d) changed phase_inc to 8 bit signed type // e) factored phase index into phase_bump in order to have // standard conforming code +// f) limited phase_ix to 0-3 #include "motor3.h" @@ -61,15 +62,12 @@ #define ramp_down literal(3) #define ramp_last literal(4) - - // Types: int8,int16,int32=8,16,32bit integers, unsigned by default int8 ramp_sts=ramp_idle; step_t motor_pos = literal(0); // absolute step number step_t pos_inc = literal(0); // motor_pos increment int16 phase = literal(0); // ccpPhase[phase_ix] -int8 phase_ix = literal(0); // index to ccpPhase[] -int8 phase_inc; // phase_ix increment +signed_int8 phase_inc; // phase_ix increment int8 run_flg; // true while motor is running mod16 ccpr; // copy of CCPR1&2 mod16 c; // integer delay count @@ -88,6 +86,7 @@ int16 const ccpPhase[] = { literal(0x808), literal(0x809) }; // 00,01,11,10 +phase_ix_t phase_ix = literal(0); // index to ccpPhase[] void current_on(){/* code as needed */} // motor drive current void current_off(){/* code as needed */} // reduce to holding value @@ -194,7 +193,7 @@ void motor_run(step_t pos_new) denom = literal(1); // 4.n+1, n=0 ramp_sts = ramp_up; // start ramp state-machine run_flg = literal(TRUE); - TMR1ON = 0; // stop timer1; + TMR1ON = literal(0); // stop timer1; ccpr = make16(TMR1H,TMR1L); // 16bit value of Timer1 ccpr += 1000; // 1st step + irq 1ms after timer1 restart CCPR2H = CCPR1H = (ccpr >> 8); @@ -202,7 +201,7 @@ void motor_run(step_t pos_new) phase_bump(); current_on(); // current in motor windings enable_interrupts(INT_CCP1); - TMR1ON=1; // restart timer1; + TMR1ON=literal(1); // restart timer1; } // motor_run() void initialize() diff --git a/include/cpp.hpp b/include/cpp.hpp index c7cedcf..206bd65 100755 --- a/include/cpp.hpp +++ b/include/cpp.hpp @@ -50,83 +50,6 @@ struct cpp { using local_long_type = typename boost::int_t::exact; using local_long_long_type = typename boost::int_t::exact; - /* - template - using normalize = typename std::make_signed< - typename std::remove_cv::type - >::type; - - // given a native type - return the equivalent local type - template - using local_type_0 = - typename boost::mpl::if_< - std::is_same, - local_char_type, - typename boost::mpl::if_< - std::is_same, - local_short_type, - typename boost::mpl::if_< - std::is_same, - local_int_type, - typename boost::mpl::if_< - std::is_same, - local_long_type, - typename boost::mpl::if_< - std::is_same, - local_long_long_type, - void - >::type>::type>::type>::type>::type; - - template - using local_type_1 = - typename boost::mpl::if_< - std::is_signed, - local_type_0, - typename std::make_unsigned< - local_type_0::type> - >::type - >::type; - - template - using local_type = - typename boost::mpl::if_< - std::is_const, - typename std::add_const< - local_type_1::type> - >::type, - typename boost::mpl::if_< - std::is_volatile, - typename std::add_volatile< - local_type_1::type> - >::type, - local_type_1 - >::type>::type; - - // section 4.13 integer conversion rank - template - using rank_helper = - typename boost::mpl::if_c< - std::is_same::value, - std::integral_constant, - typename boost::mpl::if_c< - std::is_same::value, - std::integral_constant, - typename boost::mpl::if_c< - std::is_same::value, - std::integral_constant, - typename boost::mpl::if_c< - std::is_same::value, - std::integral_constant, - typename boost::mpl::if_c< - std::is_same::value, - std::integral_constant, - typename boost::mpl::if_c< - std::is_same::value, - std::integral_constant, - void - >::type>::type>::type>::type>::type>::type; - */ - template using rank = typename boost::mpl::if_c< diff --git a/include/exception.hpp b/include/exception.hpp index 7598489..72eb0bf 100644 --- a/include/exception.hpp +++ b/include/exception.hpp @@ -49,7 +49,6 @@ dispatch(const exception_type e, char const * const msg){ EP::domain_error(msg); break; case exception_type::no_exception: - EP::no_error(msg); break; default: assert(false); diff --git a/include/interval.hpp b/include/interval.hpp index db23d30..742b050 100644 --- a/include/interval.hpp +++ b/include/interval.hpp @@ -301,13 +301,10 @@ constexpr checked_result> right_shift_positive( const interval & t, const interval & u ){ - const U ul = std::max(std::initializer_list{0, u.l}); - const U uu = std::min(std::initializer_list{ - u.u, - boost::numeric::log( - std::numeric_limits::max() - ) - }); + const U ul = safe_compare::greater_than(0, u.l) ? 0 : u.l; + + const U ux = boost::numeric::log(std::numeric_limits::max()); + const U uu = safe_compare::less_than(u.u, ux) ? u.u : ux; return select( std::initializer_list> { checked::right_shift(t.l, ul), @@ -322,15 +319,32 @@ constexpr checked_result> intersection( const interval & t, const interval & u ){ + const R rl = safe_compare::greater_than(t.l, u.l) ? t.l : u.l; + const R ru = safe_compare::less_than(t, u) ? t.u : u.u; - const R rl = std::max(std::initializer_list{t.l, u.l}); - const R ru = std::min(std::initializer_list{t.u, u.u}); - - if(rl > ru) + if(safe_compare::greater_than(rl, ru)){ return checked_result>( exception_type::uninitialized, "null intersection" ); + } + return interval(rl, ru); +} + +template +constexpr checked_result> union_interval( + const interval & t, + const interval & u +){ + const R rl = safe_compare::less_than(t.l, u.l) ? t.l : u.l; + const R ru = safe_compare::greater_than(t, u) ? t.u : u.u; + + if(safe_compare::greater_than(rl, ru)){ + return checked_result>( + exception_type::uninitialized, + "null intersection" + ); + } return interval(rl, ru); } @@ -341,11 +355,11 @@ constexpr boost::logic::tribool operator<( ){ return // if every element in t is less than every element in u - safe_compare::less_than(static_cast(t.u), static_cast(u.l)) ? + safe_compare::less_than(t.u, u.l) ? boost::logic::tribool(true) : // if every element in t is greater than every element in u - safe_compare::greater_than(static_cast(t.l), static_cast(u.u)) ? + safe_compare::greater_than(t.l, u.u) ? boost::logic::tribool(false) : // otherwise some element(s) in t are greater than some element in u @@ -360,11 +374,11 @@ constexpr boost::logic::tribool operator>( ){ return // if every element in t is greater than every element in u - safe_compare::greater_than(static_cast(t.l), static_cast(u.u)) ? + safe_compare::greater_than(t.l, u.u) ? boost::logic::tribool(true) : // if every element in t is less than every element in u - safe_compare::less_than(static_cast(t.u), static_cast(u.l)) ? + safe_compare::less_than(t.u, u.l) ? boost::logic::tribool(false) : // otherwise some element(s) in t are greater than some element in u @@ -378,7 +392,8 @@ constexpr bool operator==( const interval & u ){ // intervals have the same limits - return (t.l == u.l && t.u == u.u) ; + return safe_compare::equal(t.l, u.l) + && safe_compare::equal(t.u, u.u) ; } template diff --git a/include/safe_base_operations.hpp b/include/safe_base_operations.hpp index eb0d6b4..b5d182f 100644 --- a/include/safe_base_operations.hpp +++ b/include/safe_base_operations.hpp @@ -37,29 +37,31 @@ namespace numeric { ///////////////////////////////////////////////////////////////// // validation -template +template struct validate_detail { - // exception possible - template - constexpr static Stored return_value( - const T & t, std::true_type - ){ - // INT08-C - if(! interval().includes(t)) - E::range_error("Value out of range for this safe type"); - checked_result r = checked::cast(t); - if(!r.no_exception()){ - E::domain_error("Stored type cannot hold argument"); + struct exception_possible { + template + constexpr static R return_value( + const T & t, + const interval & this_interval + ){ + // INT08-C + if(! this_interval.includes(t)) + E::range_error("Value out of range for this safe type"); + checked_result r = checked::cast(t); + assert(r.no_exception()); + return r; } - return static_cast(r); - } - // exception not possible - template - constexpr static Stored return_value( - const T & t, std::false_type - ){ - return static_cast(t); - } + }; + struct exception_not_possible { + template + constexpr static R return_value( + const T & t, + const interval & this_interval + ){ + return static_cast(t); + } + }; }; template @@ -77,13 +79,11 @@ validated_cast(const T & t) const { indeterminate(t_interval < this_interval), "safe type cannot be constructed with this type" ); - return validate_detail::template return_value( - base_value(t), - typename std::integral_constant< - bool, - ! this_interval.includes(t_interval) - >() - ); + return boost::mpl::if_c< + this_interval.includes(t_interval), + typename validate_detail::exception_not_possible, + typename validate_detail::exception_possible + >::type::template return_value(base_value(t), this_interval); } template @@ -128,30 +128,6 @@ operator=(const safe_base & rhs){ ///////////////////////////////////////////////////////////////// // casting operators -template -struct cast_detail { - struct exception_possible { - template - constexpr static R - return_value(const T & t){ - if(! interval().includes(t)) - E::range_error("Value out of range for this safe type"); - checked_result r = checked::cast(t); - if(!r.no_exception()) - E::domain_error("Stored type cannot hold argument"); - return static_cast(r); - } - }; - - struct exception_not_possible { - template - constexpr static R - return_value(const T & t){ - return t; - } - }; -}; - template< class Stored, Stored Min, Stored Max, class P, class E> template< class R, @@ -162,14 +138,18 @@ template< > constexpr safe_base:: operator R () const { - constexpr interval r_interval; - constexpr interval this_interval(Min, Max); - + constexpr const interval r_interval; + constexpr const interval this_interval(Min, Max); + // if static values don't overlap, the program can never function + static_assert( + indeterminate(r_interval < this_interval), + "safe type cannot be constructed with this type" + ); return boost::mpl::if_c< r_interval.includes(this_interval), - typename cast_detail::exception_not_possible, - typename cast_detail::exception_possible - >::type::return_value(m_t); + typename validate_detail::exception_not_possible, + typename validate_detail::exception_possible + >::type::template return_value(m_t, r_interval); } template< class Stored, Stored Min, Stored Max, class P, class E> @@ -1267,25 +1247,24 @@ struct bitwise_and_result { u_base_type >::type; - constexpr static const interval t_interval{ - base_value(std::numeric_limits::min()), - base_value(std::numeric_limits::max()) + constexpr static interval t_b { + 0u, + log(base_value(std::numeric_limits::max())) + }; + constexpr static interval u_b { + 0u, + log(base_value(std::numeric_limits::max())) }; - constexpr static const interval u_interval{ - base_value(std::numeric_limits::min()), - base_value(std::numeric_limits::max()) - }; + constexpr static const checked_result> + r_b = intersection(t_b, u_b); - constexpr static const checked_result> - result_interval = intersection(t_interval, u_interval); - - static_assert(result_interval.no_exception(), "null intersection"); + static_assert(r_b.no_exception(), "null intersection"); using type = safe_base< result_base_type, - result_interval.m_r.l, - result_interval.m_r.u, + 1 << r_b.m_r.l, + (1 << r_b.m_r.u) - 1, promotion_policy, exception_policy >; diff --git a/include/safe_compare.hpp b/include/safe_compare.hpp index efff550..862e348 100644 --- a/include/safe_compare.hpp +++ b/include/safe_compare.hpp @@ -28,13 +28,13 @@ namespace safe_compare { // safe comparison on primitive types namespace detail { template - struct make_unsigned { - typedef typename boost::mpl::eval_if_c< - std::numeric_limits::is_signed, - typename std::make_unsigned, - typename boost::mpl::identity - >::type type; - }; + using make_unsigned = typename boost::mpl::if_c< + //std::numeric_limits::is_signed, + std::is_signed::value, + std::make_unsigned, + boost::mpl::identity + >::type; + // both arguments unsigned or signed template struct less_than { @@ -81,8 +81,8 @@ namespace detail { template constexpr bool less_than(const T & lhs, const U & rhs) { return detail::less_than< - std::numeric_limits::is_signed, - std::numeric_limits::is_signed + std::is_signed::value, + std::is_signed::value >::template invoke(lhs, rhs); } @@ -161,6 +161,7 @@ constexpr bool not_equal(const T & lhs, const U & rhs) { >::template invoke(lhs, rhs); } + } // safe_compare } // numeric } // boost diff --git a/include/utility.hpp b/include/utility.hpp index 3b9cb4d..985a784 100644 --- a/include/utility.hpp +++ b/include/utility.hpp @@ -57,6 +57,7 @@ namespace numeric { std::max(log(Min), log(Max)) >::least ; + } // numeric } // boost diff --git a/test/test_assignment.cpp b/test/test_assignment.cpp index 8ebc92e..244aa05 100644 --- a/test/test_assignment.cpp +++ b/test/test_assignment.cpp @@ -194,11 +194,11 @@ bool test_assignment(T1 v1, const char *t2_name, const char *t1_name){ #include "test_types.hpp" #include "test_values.hpp" -#define TEST_ASSIGNMENT(T1, v) \ - test_assignment( \ - v, \ - BOOST_PP_STRINGIZE(T1), \ - BOOST_PP_STRINGIZE(v) \ +#define TEST_ASSIGNMENT(T1, v) \ + rval = rval && test_assignment( \ + v, \ + BOOST_PP_STRINGIZE(T1), \ + BOOST_PP_STRINGIZE(v) \ ); /**/ @@ -217,11 +217,13 @@ bool test_assignment(T1 v1, const char *t2_name, const char *t1_name){ ) \ /**/ int main(int argc, char *argv[]){ + bool rval = true; BOOST_PP_REPEAT( BOOST_PP_ARRAY_SIZE(TYPES), EACH_TYPE1, nothing ) - return 0; + std::cout << (rval ? "success!" : "failure") << std::endl; + return rval ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/test/test_interval.cpp b/test/test_interval.cpp index a7c57c4..c762d1b 100644 --- a/test/test_interval.cpp +++ b/test/test_interval.cpp @@ -54,12 +54,11 @@ bool test5(){ interval u; std::cout << "u = " << u << std::endl; if(t.includes(u)) - std::cout << "t includes u "; + std::cout << "t includes u\n"; if(u.includes(t)) - std::cout << "u includes t"; + std::cout << "u includes t\n"; if(!t.includes(u) && ! u.includes(t)) - std::cout << "neither interval includes the other"; - std::cout << std::endl; + std::cout << "neither interval includes the other\n"; return ExpectedResult == t.includes(u); } @@ -343,6 +342,9 @@ int main(){ test5() && test5() && test5() && + test5() && + test5() && + test5() && test4::test1() && test4::test2() && test4::test3() && diff --git a/test/test_range.cpp b/test/test_range.cpp index 90ba4c7..1c6328d 100644 --- a/test/test_range.cpp +++ b/test/test_range.cpp @@ -14,12 +14,12 @@ void display_log(T Max){ bool test_log(){ using namespace boost::numeric; - assert(log(127u) == 7); // 7 bits - assert(log(127u) == 7); // 7 bits - assert(log(128u) == 8); // 8 bits - assert(log(129u) == 8); // 8 bits - assert(log(255u) == 8); // 8 bits - assert(log(256u) == 9); // 9 bits + assert(ulog(127u) == 7); // 7 bits + assert(ulog(127u) == 7); // 7 bits + assert(ulog(128u) == 8); // 8 bits + assert(ulog(129u) == 8); // 8 bits + assert(ulog(255u) == 8); // 8 bits + assert(ulog(256u) == 9); // 9 bits assert(log(127) == 8); // 7 bits + 1 sign bit assert(log(128) == 9); // 8 bits + 1 sign bit @@ -103,12 +103,14 @@ int main(){ //safe_signed_literal2<100> one_hundred; //one_hundred = 200; - return ( + bool rval = test_log() && test1() && test2() /* && test3() && test4() */ - ) ? EXIT_SUCCESS : EXIT_FAILURE; + ; + std::cout << (rval ? "success!" : "failure") << std::endl; + return rval ? EXIT_SUCCESS : EXIT_FAILURE; }