test_z.cpp 19 KB

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