• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #if 0
3 auto val()
4 {
5   return -0xFFFFFFFF;
6 }
7 
8 #include <stdexcept>
9 #include <iostream>
10 #include <boost/safe_numerics/safe_integer.hpp>
11 #include <boost/safe_numerics/safe_integer_literal.hpp>
12 
13 void val0(){
14     const boost::safe_numerics::safe<unsigned int> x{0};
15     std::cout << x << std::endl;
16     std::cout << -x << std::endl;
17     auto y = -x;
18     std::cout << y << std::endl;
19 }
20 
21 constexpr boost::safe_numerics::safe<unsigned int> val1()
22 {
23     constexpr boost::safe_numerics::safe<unsigned int> x = 0xFFFFFFFF;
24     return -x;
25 }
26 constexpr boost::safe_numerics::safe<unsigned int> val2()
27 {
28     boost::safe_numerics::safe<unsigned int> x = - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
29     return x;
30 }
31 
32 constexpr boost::safe_numerics::safe<unsigned int> val3()
33 {
34     return - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
35 }
36 
37 int main(){
38     val0();
39     std::cout << val1() << std::endl;
40     std::cout << val2() << std::endl;
41     std::cout << val3() << std::endl;
42     return 0;
43 }
44 
45 // test utility
46 #include <boost/safe_numerics/utility.hpp>
47 
48 int main(){
49     using namespace boost::safe_numerics;
50     using x = unsigned_stored_type<0, 42>;
51     print_type<x> p1;
52 
53     return 0;
54 }
55 
56 // test automatic type promotion
57 #include <boost/safe_numerics/automatic.hpp>
58 #include <boost/safe_numerics/safe_integer.hpp>
59 #include <type_traits>
60 #include <cstdint>
61 #include <iostream>
62 
63 int main(){
64     using namespace boost::safe_numerics;
65     using ar = automatic::addition_result<std::uint8_t, std::uint8_t>;
66     static_assert(
67         std::is_same<ar::type, std::uint16_t>::value,
68         "sum of two 8 bit unsigned integers should fit in on 16 bit unsigned integer"
69     );
70     return 0;
71 }
72 
73 
74 // test automatic type promotion
75 #include <boost/safe_numerics/safe_integer.hpp>
76 #include <boost/safe_numerics/safe_integer_range.hpp>
77 #include <boost/safe_numerics/safe_integer_literal.hpp>
78 #include <boost/safe_numerics/automatic.hpp>
79 #include <type_traits>
80 #include <cstdint>
81 #include <iostream>
82 
83 int main(){
84     using namespace boost::safe_numerics;
85     unsigned char t1 = 1;
86     constexpr const safe_unsigned_literal<42, automatic, default_exception_policy> v2;
87     using result_type = decltype(t1 + v2);
88 
89     static_assert(
90         std::is_same<
91             result_type,
92             safe_unsigned_range<42, 297, automatic, default_exception_policy>
93         >::value,
94         "result type should have a range 42-297"
95     );
96     return 0;
97 }
98 void f1(){
99     using namespace boost::safe_numerics;
100     constexpr safe<int> j = 0;
101     constexpr safe<int> k = 3;
102     constexpr safe<int> l = j + k; // compile error
103 }
104 
105 void f2(){
106     using namespace boost::safe_numerics;
107     constexpr safe<int> j = boost::safe_numerics::safe_signed_literal<0>();
108     constexpr safe<int> k = boost::safe_numerics::safe_signed_literal<3>();
109     constexpr safe<int> l = j + k; // compile error
110 }
111 
112 void f3(){
113     using namespace boost::safe_numerics;
114     constexpr auto j = safe_signed_literal<0, native, loose_trap_policy>();
115     constexpr auto k = safe_signed_literal<3>();
116     constexpr const safe<int> l = j + k;
117 }
118 
119 void f4(){
120     using namespace boost::safe_numerics;
121     safe_signed_literal<0, native, loose_trap_policy> j;
122     safe_signed_literal<3> k;
123     constexpr auto l = safe_signed_literal<3>();
124     constexpr const safe<int> l2 = j + k;
125 }
126 
127 #include <boost/safe_numerics/interval.hpp>
128 
129 int main(){
130     return 0;
131 }
132 
133 #include <boost/safe_numerics/utility.hpp>
134 #include <boost/safe_numerics/cpp.hpp>
135 #include <boost/safe_numerics/safe_common.hpp>
136 
137 using pic16_promotion = boost::safe_numerics::cpp<
138     8,  // char
139     8,  // short
140     8,  // int
141     16, // long
142     32  // long long
143 >;
144 
145 #include <type_traits>
146 #include <boost/safe_numerics/safe_integer.hpp>
147 #include <boost/safe_numerics/range_value.hpp>
148 #include <iostream>
149 
150 int main(){
151     using namespace boost::safe_numerics;
152     static_assert(
153         std::is_literal_type<safe<int>>::value,
154         "safe type is a literal type"
155     );
156     static_assert(
157         std::is_literal_type<interval<int>>::value,
158         "interval type is a literal type"
159     );
160     static_assert(
161         std::is_literal_type<interval<
162             safe<int>
163         >>::value,
164         "interval of safe types is a literal type"
165     );
166     static_assert(
167         std::is_literal_type<range_value<
168             safe<int>
169         >>::value,
170         "range_value of safe types is a literal type"
171     );
172     safe<int> x = 42;
173     std::cout << make_range_value(x);
174     return 0;
175 }
176 
177 auto val()
178 {
179   return -0xFFFFFFFF;
180 }
181 
182 #include <stdexcept>
183 #include <iostream>
184 #include <boost/safe_numerics/safe_integer.hpp>
185 #include <boost/safe_numerics/safe_integer_literal.hpp>
186 
187 void val0(){
188     const boost::safe_numerics::safe<unsigned int> x{0};
189     std::cout << x << std::endl;
190     std::cout << -x << std::endl;
191     auto y = -x;
192     std::cout << y << std::endl;
193 }
194 
195 constexpr boost::safe_numerics::safe<unsigned int> val1(){
196     constexpr boost::safe_numerics::safe<unsigned int> x = 0xFFFFFFFF;
197     return -x;
198 }
199 constexpr boost::safe_numerics::safe<unsigned int> val2(){
200     const boost::safe_numerics::safe<unsigned int> x
201         = -boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
202     return x;
203 }
204 constexpr boost::safe_numerics::safe<unsigned int> val3(){
205     return - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
206 }
207 
208 int main(){
209     val0();
210     std::cout << val1() << std::endl;
211     std::cout << val2() << std::endl;
212     std::cout << val3() << std::endl;
213     return 0;
214 }
215 
216 #include <boost/logic/tribool.hpp>
217 #include <boost/safe_integer/checked_integer.hpp>
218 #include <boost/safe_integer/checked_result.hpp>
219 #include <boost/safe_integer/checked_result_operations.hpp>
220 #include <boost/safe_integer/interval.hpp>
221 
222 namespace boost {
223 namespace safe_numerics {
224 
225 template<class EP, typename R>
226 constexpr void
227 dispatch(const checked_result<R> & cr){
228 }
229 
230 template<class T>
231 constexpr T base_value(const T & t){
232     return t;
233 }
234 
235 template<typename R, R Min, R Max, typename E>
236 struct validate_detail {
237 
238     constexpr static const interval<checked_result<R>> t_interval{
239         checked::cast<R>(base_value(std::numeric_limits<T>::min())),
240         checked::cast<R>(base_value(std::numeric_limits<T>::max()))
241     };
242     constexpr static const interval<checked_result<R>> r_interval{Min, Max};
243 
244 /*
245     static_assert(
246         ! static_cast<bool>(r_interval.excludes(t_interval)),
247         "ranges don't overlap: can't cast"
248     );
249 */
250 
251     struct exception_possible {
252         constexpr static R return_value(
253             const T & t
254         ){
255             static_assert(
256                 ! static_cast<bool>(r_interval.includes(t_interval)),
257                 "exeption not possible"
258             );
259             // INT08-C
260             const checked_result<R> r = checked::cast<R>(t);
261             dispatch<E>(r);
262             return base_value(r);
263         }
264     };
265     struct exception_not_possible {
266         constexpr static R return_value(
267             const T & t
268         ){
269             static_assert(
270                 static_cast<bool>(r_interval.includes(t_interval)),
271                 "exeption not possible"
272             );
273             return static_cast<R>(t);
274         }
275     };
276 
277     static R return_value(const T & t){
278         return std::conditional<
279             static_cast<bool>(r_interval.includes(t_interval)),
280             exception_not_possible,
281             exception_possible
282         >::type::return_value(t);
283     }
284 };
285 
286 template<typename R, R Min, R Max, typename T>
287 bool test1(const T & t){
288     const interval<checked_result<R>> t_interval{
289         checked::cast<R>(base_value(std::numeric_limits<T>::min())),
290         checked::cast<R>(base_value(std::numeric_limits<T>::max()))
291     };
292     const interval<checked_result<R>> r_interval{Min, Max};
293 
294 /*
295     static_assert(
296         ! static_cast<bool>(r_interval.excludes(t_interval)),
297         "ranges don't overlap: can't cast"
298     );
299 */
300     const boost::logic::tribool tb1 = r_interval.includes(t_interval);
301     const bool x1 = tb1;
302 
303     const boost::logic::tribool tb2 = r_interval.excludes(t_interval);
304     const bool x2 = tb2;
305     return x2;
306 }
307 
308 
309 } // safe_numerics
310 } // boost
311 
312 int main(){
313     unsigned int x1 = boost::safe_numerics::test1<
314         unsigned int, 0, 100, signed char
315     >(-1);
316     bool x2 = boost::safe_numerics::validate_detail<
317         unsigned int, 0, 100, signed char, void
318     >::return_value(-1);
319     return 0;
320 }
321 
322 using uint8_t = unsigned char;
323 
324 enum class safe_numerics_error : uint8_t {
325     success = 0,
326     failure,    // result is above representational maximum
327     error_count
328 };
329 
330 template<typename R>
331 struct checked_result {
332     const safe_numerics_error m_e;
333     const union {
334         const R m_r;
335         char const * const m_msg;
336     };
337     constexpr /*explicit*/ checked_result(const R & r) :
338         m_e(safe_numerics_error::success),
339         m_r(r)
340     {}
341     constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
342         m_e(e),
343         m_msg("")
344     {}
345 };
346 
347 // integers addition
348 template<class T>
349 constexpr inline checked_result<T> operator+(
350     const checked_result<T> & t,
351     const checked_result<T> & u
352 ){
353 #if 1  // compile fails
354     constexpr const safe_numerics_error x[2][2]{
355         // t == success
356         {
357             // u == ...
358             safe_numerics_error::success,
359             safe_numerics_error::failure
360         },
361         // t == positive_overflow_error,
362         {
363             // u == ...
364             safe_numerics_error::success,
365             safe_numerics_error::failure
366         }
367     };
368 
369     // "Constexpr variable 'e' must be initialized by a constant expression"
370     constexpr const safe_numerics_error e = x
371         [static_cast<uint8_t>(t.m_e)]
372         [static_cast<uint8_t>(u.m_e)]
373     ;
374 
375     return
376         safe_numerics_error::success == e
377         ? t.m_r + u.m_r
378         : checked_result<T>(e)
379     ;
380 #else  // works as expected
381     constexpr const safe_numerics_error x[2][2]{
382         // t == success
383         {
384             // u == ...
385             safe_numerics_error::success,
386             safe_numerics_error::failure
387         },
388         // t == failure,
389         {
390             // u == ...
391             safe_numerics_error::failure,
392             safe_numerics_error::failure
393         }
394     };
395 
396     return
397         safe_numerics_error::success == x
398         [static_cast<uint8_t>(t.m_e)]
399         [static_cast<uint8_t>(u.m_e)]
400         ? t.m_r + u.m_r
401         : checked_result<T>(x
402         [static_cast<uint8_t>(t.m_e)]
403         [static_cast<uint8_t>(u.m_e)]
404         )
405     ;
406 #endif
407 }
408 
409 int main(){
410     constexpr const checked_result<unsigned> i = 0;
411     constexpr const checked_result<unsigned> j = 0;
412 
413     constexpr const checked_result<unsigned> k = i + j;
414 
415     // return k.m_r;
416 
417     constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
418     constexpr const checked_result<unsigned> j2 = 0;
419 
420     constexpr const checked_result<unsigned> k2 = i2 + j2;
421     return k2.m_r;
422 }
423 #endif
424 
425 #if 0
426 using uint8_t = unsigned char;
427 
428 
429 #if 1
430 enum class safe_numerics_error : uint8_t {
431     success = 0,
432     failure,    // result is above representational maximum
433     error_count
434 };
435 #else
436 // avoiding enum class fails to solve problem
437 struct safe_numerics_error {
438     const uint8_t m_t;
439     constexpr const static uint8_t success = 0;
440     constexpr const static uint8_t failure = 1;
441     constexpr safe_numerics_error(uint8_t t) :
442         m_t(t)
443     {}
444     constexpr operator uint8_t () const {
445         return m_t;
446     }
447 };
448 #endif
449 
450 template<typename R>
451 struct checked_result {
452     const safe_numerics_error m_e;
453     const union {
454         const R m_r;
455         char const * const m_msg;
456     };
457     constexpr /*explicit*/ checked_result(const R & r) :
458         m_e(safe_numerics_error::success),
459         m_r(r)
460     {}
461     constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
462         m_e(e),
463         m_msg("")
464     {}
465 };
466 
467 // integers addition
468 template<class T>
469 constexpr inline checked_result<T> operator+(
470     const checked_result<T> & t,
471     const checked_result<T> & u
472 ){
473     // "Constexpr variable 'e' must be initialized by a constant expression"
474     constexpr const safe_numerics_error x[2][2]{
475         // t == success
476         {
477             // u == ...
478             safe_numerics_error::success,
479             safe_numerics_error::failure
480         },
481         // t == positive_overflow_error,
482         {
483             // u == ...
484             safe_numerics_error::failure,
485             safe_numerics_error::failure
486         }
487     };
488 
489 #if 1  // compile fails
490     const safe_numerics_error e = x
491         [static_cast<uint8_t>(t.m_e)]
492         [static_cast<uint8_t>(u.m_e)]
493     ;
494 
495     return
496         (safe_numerics_error::success == e)
497         ? t.m_r + u.m_r
498         : checked_result<T>(e)
499     ;
500 #else  // works as expected
501     return
502         safe_numerics_error::success == x
503             [static_cast<uint8_t>(t.m_e)]
504             [static_cast<uint8_t>(u.m_e)]
505         ? t.m_r + u.m_r
506         : checked_result<T>(x
507             [static_cast<uint8_t>(t.m_e)]
508             [static_cast<uint8_t>(u.m_e)]
509         )
510     ;
511 #endif
512 }
513 
514 int main(){
515     constexpr const checked_result<unsigned> i = 0;
516     constexpr const checked_result<unsigned> j = 0;
517 
518     //constexpr const checked_result<unsigned> k = i + j;
519     // return k.m_r;
520 
521     constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
522     constexpr const checked_result<unsigned> j2 = 0;
523 
524     constexpr const checked_result<unsigned> k2 = i2 + j2;
525     return 0;
526 }
527 
528 #endif
529 
530 #if 0
531 //#include "safe_common.hpp>
532 //#include "checked_result.hpp>
533 //#include "checked_default.hpp>
534 #include <cassert>
535 #include <boost/logic/tribool.hpp>
536 
537 #include <iostream>
538 
539 // note: Don't reorder these.  Code in the file checked_result_operations.hpp
540 // depends upon this order !!!
541 enum class safe_numerics_error : std::uint8_t {
542     success = 0,
543     positive_overflow_error,    // result is above representational maximum
544     negative_overflow_error,    // result is below representational minimum
545     domain_error,               // one operand is out of valid range
546     range_error,                // result cannot be produced for this operation
547     precision_overflow_error,   // result lost precision
548     underflow_error,            // result is too small to be represented
549     negative_value_shift,       // negative value in shift operator
550     negative_shift,             // shift a negative value
551     shift_too_large,            // l/r shift exceeds variable size
552     uninitialized_value         // l/r shift exceeds variable size
553 };
554 
555 // checked result is an "extended version" of the type R.  That is it's domain is
556 // the domain of R U possible other values which might result from arithmetic
557 // operations.  An example of such a value would be safe_error::positive_overflow_error.
558 template<typename R>
559 struct checked_result {
560     const safe_numerics_error m_e;
561     const union {
562         R m_r;
563         char const * m_msg;
564     };
565 
566     constexpr /*explicit*/ checked_result(const R & r) :
567         m_e(safe_numerics_error::success),
568         m_r(r)
569     {}
570     constexpr /*explicit*/ checked_result(
571         safe_numerics_error e,
572         const char * msg = ""
573     ) :
574         m_e(e),
575         m_msg(msg)
576     {
577         assert(m_e != safe_numerics_error::success);
578     }
579     constexpr bool exception() const {
580         return m_e != safe_numerics_error::success;
581     }
582 
583     // don't permit construction without initial value;
584     checked_result() = delete;
585 
586     // disallow assignment
587     checked_result & operator=(const checked_result &) = delete;
588 };
589 
590 // all arithmetic operations of type T are supported on checked_result<T>.
591 // but the results might surprising.  For example
592 
593 
594 constexpr signed int test_constexpr(
595     const checked_result<signed int> & t,
596     const checked_result<signed int> & u
597 ){
598     const boost::logic::tribool tb2 = t < u;
599     const signed int x = (tb2) ? 2 : 3;
600     return x;
601 }
602 
603 using namespace boost::safe_numerics;
604 
605 int main()
606 {
607     constexpr const checked_result<signed int> po = safe_numerics_error::positive_overflow_error;
608     constexpr const checked_result<signed int> no = safe_numerics_error::negative_overflow_error;
609     constexpr const boost::logic::tribool tb = no < po;
610     const boost::logic::tribool tb1 = no > po;
611     constexpr const checked_result<signed int> re = safe_numerics_error::range_error;
612     const boost::logic::tribool tb2 = no < re;
613     const checked_result<signed int> x = no < re ? no : re;
614 
615     static_assert(test_constexpr(no, re) == 3, "test_constexpr(no, re)");
616 
617 
618     static_assert(tb, "no < po");
619 
620     signed int result;
621     if(tb)
622         result = 0;
623     else
624         result = 1;
625     std::cout << result;
626     return result;
627 }
628 
629 #endif
630 
631 #if 0
632 
633 #include <boost/logic/tribool.hpp>
634 #include <cassert>
635 int main(){
636     constexpr const boost::tribool tb_t{true};
637     static_assert(tb_t, "tb_t");
638     assert(static_cast<bool>(tb_t));
639     constexpr boost::tribool tb_f{false};
640     static_assert(! tb_f, "tb_f");
641     assert(! static_cast<bool>(tb_f));
642     return 0;
643 }
644 #endif
645 
646 #if 0
647 #include <boost/integer.hpp>
648 #include <boost/safe_numerics/utility.hpp>
649 
650 // include headers to support safe integers
651 #include <boost/safe_numerics/cpp.hpp>
652 //#include <boost/safe_numerics/exception.hpp>
653 
654 using promotion_policy = boost::safe_numerics::cpp<
655     8,  // char      8 bits
656     16, // short     16 bits
657     16, // int       16 bits
658     16, // long      32 bits
659     32  // long long 32 bits
660 >;
661 
662 template<typename R, typename T, typename U>
663 struct test {
664     using ResultType = promotion_policy::result_type<T,U>;
665     //boost::safe_numerics::utility::print_type<ResultType> pt;
666     static_assert(
667         std::is_same<R, ResultType>::value,
668         "is_same<R, ResultType>"
669     );
670 };
671 
672 test<std::uint16_t, std::uint8_t, std::uint8_t> t1;
673 
674 int main(){
675     return 0;
676 }
677 
678 #endif
679 
680 #if 0
681 #include <string>
682 #include <unordered_map>
683 #include <boost/safe_numerics/safe_integer.hpp>
684 
685 #include <functional> // hash
686 
687 template<typename T>
688 struct safe_hash {
689     size_t operator()(boost::safe_numerics::safe<T> const& t) const  {
690         return std::hash<T>()(t);
691     }
692 };
693 
694 int main(){
695     auto foo = std::unordered_map<
696         boost::safe_numerics::safe<int>,
697         std::string,
698         safe_hash<int>
699     >{};
700     foo[boost::safe_numerics::safe<int>(42)] = "hello, world!";
701     foo[42] = "hello, world!";
702 }
703 
704 #endif
705 
706 #if 0
707 
708 #include <string>
709 #include <unordered_map>
710 #include <boost/safe_numerics/safe_integer.hpp>
711 
712 #include <functional> // hash
713 
714 template<typename T>
715 struct safe_hash {
716     size_t operator()(boost::safe_numerics::safe<T> const& t) const  {
717         return std::hash<T>()(t);
718     }
719 };
720 
721 int main(){
722     auto foo = std::unordered_map<int, std::string>{};
723     foo[boost::safe_numerics::safe<int>(42)] = "hello, world!";
724 }
725 
726 #endif
727 
728 #if 0
729 
730 #include <iostream>
731 #include <boost/safe_numerics/safe_integer.hpp>
732 //#include <boost/safe_numerics/automatic.hpp>
733 
734 using namespace boost::safe_numerics;
735 
736 int main(){
737     using safe_int = safe<
738         int,
739         automatic,
740         loose_trap_policy
741     >;
742     safe_int i;
743     std::cin >> i; // might throw exception
744     auto j = i * i;
745         // won't ever trap
746         // result type can hold the maximum value of i * i
747     static_assert(is_safe<decltype(j)>::value, "result is a safe type");
748     static_assert(
749         std::numeric_limits<decltype(i * i)>::max() >=
750         std::numeric_limits<safe_int>::max() * std::numeric_limits<safe_int>::max(),
751         "result can never overflow"
752     ); // always true
753 
754     return 0;
755 }
756 
757 
758 #include <cstdint>
759 #include <boost/safe_numerics/safe_integer_range.hpp>
760 #include <boost/safe_numerics/safe_integer_literal.hpp>
761 
762 template <uintmax_t Min, uintmax_t Max>
763 using urange = boost::safe_numerics::safe_unsigned_range<
764     Min,
765     Max,
766     boost::safe_numerics::native,
767     boost::safe_numerics::strict_trap_policy
768 >;
769 
770 template <uintmax_t N>
771 using ulit = boost::safe_numerics::safe_unsigned_literal<
772     N,
773     boost::safe_numerics::native,
774     boost::safe_numerics::strict_trap_policy
775 >;
776 
777 int main(){
778     urange<0,4095> x = ulit<0>(); // 12 bits
779     urange<0, 69615> y = x * ulit<17>(); // no error - resulting value
780         // cannot exceed  69615
781     auto z = y / ulit<17>() ; //Boom, compile-time error
782     return z;
783 }
784 
785 #endif
786 
787 #include <boost/safe_numerics/safe_integer_range.hpp>
788 
main()789 int main(){
790     using namespace boost::safe_numerics;
791     safe_unsigned_range<0, 36> a = 30;
792     return 0;
793 }
794