From 69c3e12e1636fa844282e510e9eff0e530b4a2bf Mon Sep 17 00:00:00 2001 From: Robert Ramey Date: Fri, 13 Jul 2012 09:11:40 -0800 Subject: [PATCH] initial commit to Git for GitHub --- safe_numerics/doc/boostbook/bb2db.xsl | 4 + safe_numerics/doc/boostbook/db2html.xsl | 60 ++ safe_numerics/doc/boostbook/makehtml.bat | 13 + safe_numerics/doc/boostbook/makehtml.sh | 9 + .../doc/boostbook/numeric_concept.xml | 460 ++++++++++ safe_numerics/doc/boostbook/overflow.xml | 59 ++ safe_numerics/doc/boostbook/pre-boost.jpg | Bin 0 -> 9606 bytes safe_numerics/doc/boostbook/safe.xml | 147 ++++ safe_numerics/doc/boostbook/safe_cast.xml | 99 +++ safe_numerics/doc/boostbook/safe_compare.xml | 94 +++ safe_numerics/doc/boostbook/safe_numerics.xml | 251 ++++++ .../doc/boostbook/safe_signed_range.xml | 96 +++ .../doc/boostbook/safe_unsigned_range.xml | 97 +++ safe_numerics/doc/boostbook/tutorial.xml | 74 ++ safe_numerics/doc/html/acknowledgements.html | 44 + safe_numerics/doc/html/boostbook.css | 601 +++++++++++++ safe_numerics/doc/html/change_log.html | 42 + safe_numerics/doc/html/concepts.html | 42 + safe_numerics/doc/html/functions.html | 46 + safe_numerics/doc/html/index.html | 74 ++ safe_numerics/doc/html/introduction.html | 47 ++ safe_numerics/doc/html/notes.html | 66 ++ safe_numerics/doc/html/numeric.html | 382 +++++++++ safe_numerics/doc/html/pre-boost.jpg | Bin 0 -> 9606 bytes safe_numerics/doc/html/rationale.html | 96 +++ .../doc/html/rationale/overflow.html | 92 ++ safe_numerics/doc/html/references.html | 54 ++ safe_numerics/doc/html/safe.html | 160 ++++ safe_numerics/doc/html/safe_cast.html | 125 +++ safe_numerics/doc/html/safe_compare.html | 117 +++ safe_numerics/doc/html/safe_signed_range.html | 117 +++ .../doc/html/safe_unsigned_range.html | 118 +++ safe_numerics/doc/html/tutorial.html | 46 + safe_numerics/doc/html/types.html | 46 + safe_numerics/examples/example1.cpp | 35 + safe_numerics/examples/example2.cpp | 25 + safe_numerics/examples/example3.cpp | 25 + safe_numerics/examples/example4.cpp | 31 + safe_numerics/examples/example_test.cpp | 22 + safe_numerics/include/concept/numeric.hpp | 28 + safe_numerics/include/numeric.hpp | 356 ++++++++ safe_numerics/include/overflow.hpp | 32 + safe_numerics/include/safe_cast.hpp | 112 +++ safe_numerics/include/safe_compare.hpp | 155 ++++ safe_numerics/include/safe_integer.hpp | 81 ++ safe_numerics/include/safe_range.hpp | 795 ++++++++++++++++++ safe_numerics/tests/test.cpp | 87 ++ safe_numerics/tests/test.hpp | 116 +++ safe_numerics/tests/test_add.cpp | 17 + safe_numerics/tests/test_add.hpp | 178 ++++ safe_numerics/tests/test_add1.cpp | 37 + safe_numerics/tests/test_add2.cpp | 38 + safe_numerics/tests/test_add3.cpp | 38 + safe_numerics/tests/test_conversion.cpp | 180 ++++ safe_numerics/tests/test_divide.cpp | 11 + safe_numerics/tests/test_divide.hpp | 178 ++++ safe_numerics/tests/test_divide1.cpp | 37 + safe_numerics/tests/test_divide2.cpp | 37 + safe_numerics/tests/test_divide3.cpp | 37 + safe_numerics/tests/test_misc.cpp | 7 + safe_numerics/tests/test_modulus.cpp | 17 + safe_numerics/tests/test_modulus.hpp | 178 ++++ safe_numerics/tests/test_modulus1.cpp | 37 + safe_numerics/tests/test_modulus2.cpp | 37 + safe_numerics/tests/test_modulus3.cpp | 37 + safe_numerics/tests/test_multiply.cpp | 17 + safe_numerics/tests/test_multiply.hpp | 174 ++++ safe_numerics/tests/test_multiply1.cpp | 37 + safe_numerics/tests/test_multiply2.cpp | 37 + safe_numerics/tests/test_multiply3.cpp | 37 + safe_numerics/tests/test_numeric.cpp | 230 +++++ safe_numerics/tests/test_subtract.cpp | 17 + safe_numerics/tests/test_subtract.hpp | 178 ++++ safe_numerics/tests/test_subtract1.cpp | 37 + safe_numerics/tests/test_subtract2.cpp | 38 + safe_numerics/tests/test_subtract3.cpp | 38 + safe_numerics/tests/vcide/example_test.vcproj | 242 ++++++ safe_numerics/tests/vcide/safe_numerics.sln | 99 +++ safe_numerics/tests/vcide/test_add.vcproj | 206 +++++ .../tests/vcide/test_comparison.vcproj | 188 +++++ .../tests/vcide/test_conversion.vcproj | 198 +++++ safe_numerics/tests/vcide/test_divide.vcproj | 210 +++++ safe_numerics/tests/vcide/test_modulus.vcproj | 206 +++++ .../tests/vcide/test_multiply.vcproj | 206 +++++ safe_numerics/tests/vcide/test_numeric.vcproj | 202 +++++ .../tests/vcide/test_subtract.vcproj | 206 +++++ 86 files changed, 9582 insertions(+) create mode 100644 safe_numerics/doc/boostbook/bb2db.xsl create mode 100644 safe_numerics/doc/boostbook/db2html.xsl create mode 100644 safe_numerics/doc/boostbook/makehtml.bat create mode 100644 safe_numerics/doc/boostbook/makehtml.sh create mode 100644 safe_numerics/doc/boostbook/numeric_concept.xml create mode 100644 safe_numerics/doc/boostbook/overflow.xml create mode 100644 safe_numerics/doc/boostbook/pre-boost.jpg create mode 100644 safe_numerics/doc/boostbook/safe.xml create mode 100644 safe_numerics/doc/boostbook/safe_cast.xml create mode 100644 safe_numerics/doc/boostbook/safe_compare.xml create mode 100644 safe_numerics/doc/boostbook/safe_numerics.xml create mode 100644 safe_numerics/doc/boostbook/safe_signed_range.xml create mode 100644 safe_numerics/doc/boostbook/safe_unsigned_range.xml create mode 100644 safe_numerics/doc/boostbook/tutorial.xml create mode 100644 safe_numerics/doc/html/acknowledgements.html create mode 100644 safe_numerics/doc/html/boostbook.css create mode 100644 safe_numerics/doc/html/change_log.html create mode 100644 safe_numerics/doc/html/concepts.html create mode 100644 safe_numerics/doc/html/functions.html create mode 100644 safe_numerics/doc/html/index.html create mode 100644 safe_numerics/doc/html/introduction.html create mode 100644 safe_numerics/doc/html/notes.html create mode 100644 safe_numerics/doc/html/numeric.html create mode 100644 safe_numerics/doc/html/pre-boost.jpg create mode 100644 safe_numerics/doc/html/rationale.html create mode 100644 safe_numerics/doc/html/rationale/overflow.html create mode 100644 safe_numerics/doc/html/references.html create mode 100644 safe_numerics/doc/html/safe.html create mode 100644 safe_numerics/doc/html/safe_cast.html create mode 100644 safe_numerics/doc/html/safe_compare.html create mode 100644 safe_numerics/doc/html/safe_signed_range.html create mode 100644 safe_numerics/doc/html/safe_unsigned_range.html create mode 100644 safe_numerics/doc/html/tutorial.html create mode 100644 safe_numerics/doc/html/types.html create mode 100644 safe_numerics/examples/example1.cpp create mode 100644 safe_numerics/examples/example2.cpp create mode 100644 safe_numerics/examples/example3.cpp create mode 100644 safe_numerics/examples/example4.cpp create mode 100644 safe_numerics/examples/example_test.cpp create mode 100644 safe_numerics/include/concept/numeric.hpp create mode 100644 safe_numerics/include/numeric.hpp create mode 100644 safe_numerics/include/overflow.hpp create mode 100644 safe_numerics/include/safe_cast.hpp create mode 100644 safe_numerics/include/safe_compare.hpp create mode 100644 safe_numerics/include/safe_integer.hpp create mode 100644 safe_numerics/include/safe_range.hpp create mode 100644 safe_numerics/tests/test.cpp create mode 100644 safe_numerics/tests/test.hpp create mode 100644 safe_numerics/tests/test_add.cpp create mode 100644 safe_numerics/tests/test_add.hpp create mode 100644 safe_numerics/tests/test_add1.cpp create mode 100644 safe_numerics/tests/test_add2.cpp create mode 100644 safe_numerics/tests/test_add3.cpp create mode 100644 safe_numerics/tests/test_conversion.cpp create mode 100644 safe_numerics/tests/test_divide.cpp create mode 100644 safe_numerics/tests/test_divide.hpp create mode 100644 safe_numerics/tests/test_divide1.cpp create mode 100644 safe_numerics/tests/test_divide2.cpp create mode 100644 safe_numerics/tests/test_divide3.cpp create mode 100644 safe_numerics/tests/test_misc.cpp create mode 100644 safe_numerics/tests/test_modulus.cpp create mode 100644 safe_numerics/tests/test_modulus.hpp create mode 100644 safe_numerics/tests/test_modulus1.cpp create mode 100644 safe_numerics/tests/test_modulus2.cpp create mode 100644 safe_numerics/tests/test_modulus3.cpp create mode 100644 safe_numerics/tests/test_multiply.cpp create mode 100644 safe_numerics/tests/test_multiply.hpp create mode 100644 safe_numerics/tests/test_multiply1.cpp create mode 100644 safe_numerics/tests/test_multiply2.cpp create mode 100644 safe_numerics/tests/test_multiply3.cpp create mode 100644 safe_numerics/tests/test_numeric.cpp create mode 100644 safe_numerics/tests/test_subtract.cpp create mode 100644 safe_numerics/tests/test_subtract.hpp create mode 100644 safe_numerics/tests/test_subtract1.cpp create mode 100644 safe_numerics/tests/test_subtract2.cpp create mode 100644 safe_numerics/tests/test_subtract3.cpp create mode 100644 safe_numerics/tests/vcide/example_test.vcproj create mode 100644 safe_numerics/tests/vcide/safe_numerics.sln create mode 100644 safe_numerics/tests/vcide/test_add.vcproj create mode 100644 safe_numerics/tests/vcide/test_comparison.vcproj create mode 100644 safe_numerics/tests/vcide/test_conversion.vcproj create mode 100644 safe_numerics/tests/vcide/test_divide.vcproj create mode 100644 safe_numerics/tests/vcide/test_modulus.vcproj create mode 100644 safe_numerics/tests/vcide/test_multiply.vcproj create mode 100644 safe_numerics/tests/vcide/test_numeric.vcproj create mode 100644 safe_numerics/tests/vcide/test_subtract.vcproj diff --git a/safe_numerics/doc/boostbook/bb2db.xsl b/safe_numerics/doc/boostbook/bb2db.xsl new file mode 100644 index 0000000..7744c97 --- /dev/null +++ b/safe_numerics/doc/boostbook/bb2db.xsl @@ -0,0 +1,4 @@ + + + + diff --git a/safe_numerics/doc/boostbook/db2html.xsl b/safe_numerics/doc/boostbook/db2html.xsl new file mode 100644 index 0000000..c31de26 --- /dev/null +++ b/safe_numerics/doc/boostbook/db2html.xsl @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + +horizontal + +http://www.boost.org/doc/libs +file:///index.html + + + + + + + + + +pre-boost.jpg +pre-boost +30% +30% + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/doc/boostbook/makehtml.bat b/safe_numerics/doc/boostbook/makehtml.bat new file mode 100644 index 0000000..e66e125 --- /dev/null +++ b/safe_numerics/doc/boostbook/makehtml.bat @@ -0,0 +1,13 @@ +if x == x%BOOST_ROOT% goto abort + +xsltproc --nonet --xinclude bb2db.xsl safe_numerics.xml | xsltproc --nonet db2html.xsl - +xcopy /i /q /y *.jpg ..\html +if not exist ..\html md ..\html +xcopy /i /q /y %BOOST_ROOT%\doc\src\boostbook.css ..\html +if not exist ..\html md ..\html\images +xcopy /i /q /y /s %BOOST_ROOT%\doc\html\images ..\html\images +exit + +:abort +echo BOOST_ROOT not set +exit diff --git a/safe_numerics/doc/boostbook/makehtml.sh b/safe_numerics/doc/boostbook/makehtml.sh new file mode 100644 index 0000000..6bb1978 --- /dev/null +++ b/safe_numerics/doc/boostbook/makehtml.sh @@ -0,0 +1,9 @@ +if test x = x$BOOST_ROOT +then + echo BOOST_ROOT not set + exit 1 +fi +xsltproc --nonet --xinclude bb2db.xsl safe_numerics.xml | xsltproc --nonet db2html.xsl - +cp pre-boost.jpg ../html +cp $BOOST_ROOT/doc/src/boostbook.css ../html +cp -R $BOOST_ROOT/doc/html/images ../html diff --git a/safe_numerics/doc/boostbook/numeric_concept.xml b/safe_numerics/doc/boostbook/numeric_concept.xml new file mode 100644 index 0000000..c7d14a4 --- /dev/null +++ b/safe_numerics/doc/boostbook/numeric_concept.xml @@ -0,0 +1,460 @@ + + +
+ Numeric<T> + +
+ Description + + A type is Numeric if it has the properties of a number. + + More specifically, a type T is Numeric if there exists + specialization of std::numeric_limits<T>. See the + documentation for standard library class numeric_limits. The standard + library includes such specializations for all the primitive numeric types. + Note that this concept is distinct from the C++ standard library type + traits is_integral and is_arithmetic. These + latter fullfill the requirement of the concept Numeric. But there are + types T which fullfill this concept for which + is_arithmetic<T>::value == false. For example see + safe_signed_integer<int>. +
+ +
+ Notation + + + Notation + + + + + + + + + T, U, V + + A type that is a model of the Numeric + + + + t, u, v + + An object of type modeling Numeric + + + +
+
+ +
+ Associated Types + + + Associated Types + + + + + + + + + std::numeric_limits<T> + + The numeric_limits class template provides a C++ program + with information about various properties of the implementation’s + representation of the arithmetic types. See C++ standard + 18.3.2.2. + + + +
+
+ +
+ Valid Expressions + + In addition to the expressions defined in Assignable the + following expressions must be valid. + + Any operations which result in integers which cannot be represented + as some Numeric type will throw an exception. + General + + + + + + + + + Expression + + Return Value + + + + + + std::numeric_limits<T>.is_bounded + + + true + + + + std::numeric_limits<T>.is_integer + + true + + + + std::numeric_limits<T>.is_specialized + + + true + + + +
+ + + Unary Operators + + + + + + + + + + + Expression + + Return Type + + Semantics + + + + + + -t + + T + + Invert sign + + + + +t + + T + + unary plus - a no op + + + + t-- + + T + + post decrement + + + + t++ + + T + + post increment + + + + --t + + T + + predecrement + + + + ++t + + T + + preincrement + + + + ~ + + T + + complement + + + +
+ + + Binary Operators + + + + + + + + + + + Expression + + Return Type + + Semantics + + + + + + t - u + + V + + Invert sign + + + + t + u + + V + + unary plus - a no op + + + + t * u + + V + + multiply t by u + + + + t / u + + T + + divide t by u + + + + t % u + + T + + t modulus u + + + + t << u + + T + + shift t left u bits + + + + t >> u + + T + + shift t right by ubits + + + + t < u + + bool + + true if t less than u, false otherwise + + + + t <= u + + bool + + true if t less than or equal to u, false otherwise + + + + t > u + + bool + + true if t greater than u, false otherwise + + + + t >= u + + bool + + true if t greathan or equal to u, false otherwise + + + + t == u + + bool + + true if t equal to u, false otherwise + + + + t != u + + bool + + true if t not equal to u, false otherwise + + + + t & u + + bool + + and of t and u padded out max # bits in t, u + + + + t | u + + bool + + or of t and u padded out max # bits in t, u + + + + t ^ u + + V + + exclusive or of t and u padded out max # bits in t, + u + + + + t = u + + T + + assign value of u to t + + + + t += u + + T + + add u to t and assign to t + + + + t -= u + + T + + subtract u from t and assign to t + + + + t *= u + + T + + multiply t by u and assign to t + + + + t /= u + + T + + divide t by u and assign to t + + + + t &= u + + T + + and t with u and assign to t + + + + t <<= u + + T + + left shift the value of t by u bits + + + + t >>= u + + T + + right shift the value of t by u bits + + + + t &= u + + T + + and the value of t with u and assign to t + + + + t |= u + + T + + or the value of t with u and assign to t + + + + t ^= u + + T + + exclusive or the value of t with u and assign to t + + + +
+
+ +
+ Header + + #include + <safe_numerics/include/concepts/numeric.hpp> +
+ +
+ Models + + int, safe_signed_integer<int>, + safe_signed_range<int>, etc. +
+
diff --git a/safe_numerics/doc/boostbook/overflow.xml b/safe_numerics/doc/boostbook/overflow.xml new file mode 100644 index 0000000..7b5cb51 --- /dev/null +++ b/safe_numerics/doc/boostbook/overflow.xml @@ -0,0 +1,59 @@ + + +
+ overflow + +
+ Synopsis + + This function is invoked by the library whenever it is not possible + to produce a result for an arithmetic operation. + + void overflow(char const * const msg); +
+ +
+ Description + + If evironment supports C++ exceptions, this function throws the + exception . + + If the environment does not support C++ exceptions, the user should + implement this function and expect it to be called when appropriate. + Otherwise, function is implemented by the library so that it throws the + standard library exception std::out_of_range(msg). + + boost/config.hpp defines BOOST_NO_EXCEPTIONS + when the environment doesn't support exceptions. It is by checking for the + definition of this macro that the system determines whether or not + exceptions are supported. +
+ +
+ Header + + #include + <boost/safe_numerics/overflow.hpp> +
+ +
+ Example of use + + #include <cstdio> + +void overflow(char const * const msg){ + std::fputs("safe_numerics overflow error:, std::stderr); + std::fputs(msg, std::stderr); + std::fputc('\n', std::stderr); +} +
+ +
+ See Also + + See rationale for more + information on this function +
+
diff --git a/safe_numerics/doc/boostbook/pre-boost.jpg b/safe_numerics/doc/boostbook/pre-boost.jpg new file mode 100644 index 0000000000000000000000000000000000000000..be684e45b1cff0ca3408c195434bdc33e3281a62 GIT binary patch literal 9606 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 MrMmbdi2eUf04y9TG5`Po literal 0 HcmV?d00001 diff --git a/safe_numerics/doc/boostbook/safe.xml b/safe_numerics/doc/boostbook/safe.xml new file mode 100644 index 0000000..9fd1ece --- /dev/null +++ b/safe_numerics/doc/boostbook/safe.xml @@ -0,0 +1,147 @@ + + +
+ safe<T> + +
+ Description + + A safe<T> can be used anywhere a type T is used. + When T is used in operation which overflows, a exception is thrown +
+ +
+ Template Parameters + + + + + + + + + + + + + + Parameter + + Type Requirements + + Description + + + + + + T + + Numeric + + The underlying integer type + + + + +
+ +
+ Model of + + Numeric +
+ +
+ Derived From + + safe_signed_range<T> + (if std::numeric_limits<T>::is_signed == ftrue) + + safe_unsigned_range<T> + (if std::numeric_limits<T>::is_signed == ftrue) +
+ +
+ Notation + + + + + + + + + + Symbol + + Description + + + + + + T + + A type that models the Numeric concept + + + + t + + An object of type T + + + + +
+ +
+ Header + + #include + <boost/safe_numerics/safe_integer.hpp> +
+ +
+ Example of use + + The following program will emit an error message on a machine where + int is only 16 bits but run without problem on a machine where int is 32 + bits. + + #include <boost/numeric/safe.hpp> +#include <iostream> +void f(){ + safe<int> i = 400; + safe<int> j; + try { + j = i * i; + } + catch(...){ + std::cout << "overflow error" << std::endl; + } +} + + +
+ +
+ Notes + + Footnotes (if any) that are referred to by other parts of the + page. +
+ +
+ See Also + + Footnotes (if any) that are referred to by other parts of the + page. +
+
diff --git a/safe_numerics/doc/boostbook/safe_cast.xml b/safe_numerics/doc/boostbook/safe_cast.xml new file mode 100644 index 0000000..92e0e9e --- /dev/null +++ b/safe_numerics/doc/boostbook/safe_cast.xml @@ -0,0 +1,99 @@ + + +
+ safe_cast + +
+ Synopsis + + template<class T, class U> +T safe_cast(const U & u); +
+ +
+ Description + + Converts one Numeric type + to another. Throws an std::out_of_range exception if such a + conversion is not possible without changing the value. +
+ +
+ Type requirements + + + + + + + + + + Type + + Requirements + + + + + + T + + Numeric + + + + U + + Numeric + + + + +
+ +
+ Preconditions + + The value of u can be represented by the type T. If + this is not true, an std::out_of_range exception will be + thrown. +
+ +
+ Complexity + + [Example:] + + O(N log(N)) comparisons (both average and worst-case), where N is + last - first. [2] +
+ +
+ Header + + #include + <boost/numeric/safe_cast.hpp> +
+ +
+ Example of use + + [A code fragment that illustrates how to use the function.] + + #include <boost/numeric/safe_cast.hpp> +#include <boost/numeric/safe_integer.hpp> + +void f(){ + safe_integer<char> i; + unsigned char j; + i = 1; + j = safe_cast<unsigned char>(i); // ok + i = -1; + j = safe_cast<unsigned char>(i); // throws std::out_of_range exception + i = 1024; + j = safe_cast<unsigned char>(i); // throws std::out_of_range exception +} +
+
diff --git a/safe_numerics/doc/boostbook/safe_compare.xml b/safe_numerics/doc/boostbook/safe_compare.xml new file mode 100644 index 0000000..c365886 --- /dev/null +++ b/safe_numerics/doc/boostbook/safe_compare.xml @@ -0,0 +1,94 @@ + + +
+ safe_compare + +
+ Synopsis + + safe_compare is really two functions:. + + template<class T, class U> +bool safe_compare::less_than(const T & lhs, const U & rhs); + +template<class T, class U> +bool safe_compare::greater_than(const T & lhs, const U & rhs); +
+ +
+ Description + + With normal comparison operators, comparison of unsigned types to + signed types will be done by converting the unsigned type to a signed type + before comparing. Unfortunately this is not always possible. Most C++ + compilers will emit an warning message when this is possible but won't + check that an error is made in the conversion. This function guarentees a + correct result regardless of the types of the arguments. +
+ +
+ Type requirements + + [This section lists the requirements that must be satisfied by the + function's template parameters. If the function has no template + parameters, this section can be skipped. Example:] + + + + + + + + + + Type + + Requirements + + + + + + T + + Numeric + + + + U + + Numeric + + + + +
+ +
+ Header + + [A link to the source code where the function header is + defined.] + + #include + <boost/numeric/safe_compare.hpp> +
+ +
+ Example of use + + #include <boost/numeric/safe_compare.hpp> + +void f(){ + int i = -1; + unsigned char i = 0x129; + unsigned int j = 1; + bool result; + result = j < i; // incorrect result + result = safe_compare::less_than(j < i); // correct result +} +
+
diff --git a/safe_numerics/doc/boostbook/safe_numerics.xml b/safe_numerics/doc/boostbook/safe_numerics.xml new file mode 100644 index 0000000..aae6196 --- /dev/null +++ b/safe_numerics/doc/boostbook/safe_numerics.xml @@ -0,0 +1,251 @@ + + + + Safe Numerics + + + + Robert + + Ramey + + + + 2012 + + Robert Ramey + + + + Subject to Boost Software License + + + Safe integer operations + + Numerics + + +
+ Introduction + + Arithmetic operations in C++ are NOT guarenteed to yield a correct + mathematical result. This feature is inherited from the early days of C. + The behavior of int, unsigned int and others + were designed to map closely to the underlying hardware. Computer hardware + implements these types as a fixed number of bits. When the result of + arithmetic operations exceeds this number of bits, the result is undefined + and usually not what the programmer intended. It is incumbent up the C++ + programmer to guarentee that this behavior does not result in incorrect + behavior of the program. This library implements special versions of these + data types which behave exactly like the original ones EXCEPT that the + results of these operations are checked to be sure that an exception will + be thrown anytime an attempt is made to store the result of an undefined + operation. + + Additionally, we define data types safe_signed_range<MIN, + MAX> and safe_unsigned_range<MIN, MAX> which + will throw an exception if an attempt is made to store a result which is + outside the closed range [MIN, MAX] +
+ + + +
+ Notes + + This library really an re-implementation the facilities provided by + David LeBlanc's SafeInt + Library using Boost. I found + this library very well done in every way. My main usage was to run unit + tests for my embedded systems projects on my PC. Still, I had a few + issues. + + + + I was a lot of code in one header - 6400 lines. Very unwieldy to + understand and modify. + + + + I couldn't find separate documentation other than that in the + header file. + + + + I didn't use Boost + conventions for naming. + + + + I required porting to different compilers. + + + + It had a very long license associated with it. + + + + The package I downloaded didn't have a test suite + + + + I believe the original SafeInt + library is not easily found. MSVC 10 has this built in so I seems that + they've decided to make it less attractive to use on other + systems. + + + + This version addresses these issues. It exploits Boost facilities such as template + metaprogramming to reduce the number of lines of source code to + approximately 1500. It exploits the Boost Preprocessor Library to generate + exhaustive tests. + + All concepts, types and functions documented are declared in the + namespace boost::numeric. +
+ +
+ Concepts + + +
+ +
+ Types + + + + + + +
+ +
+ Functions + + + + + + +
+ +
+ Rationale + + + + + Why does a binary operation on two + safe<int> values not necessarily return another + safe type ? + + + + There are a number of + + + + it was hard to implement. + + + + it doesn't really seem necessary. We always do SOMETHING + with result of the operation. This will result in an assignment + or a conversion to some other type where the result will be + validated. + + + + + + + + Why is there no policy driven design for handling + overflows + + The question was - to which type does one apply it to? + Consider the following example: + + safe<int, overflow_policy_1> t1 = 2; +safe<int, overflow_policy_2> t2 = 4; +unsigned int x = t1 - t2; // which policy should be invoked? + + + + + + Why is Boost.Convert not used. + + I couldn't figure out how to use it from the + documentation. + + + +
+ +
+ Change Log + + This is the initial version. +
+ +
+ Acknowledgements + + David + LeBlanc's is the author of SafeInt3 + library which motivated this work +
+ +
+ References + + + + David LeBlanc, Codeplex + SafeInt Page + + + + Daniel Plakosh, Safe + Integer Operations + + + + Omer Katz, SafeInt + code proposal, Boost.SafeInt + + + + Software Engineering Institute, Carnegie Mellon, INT32-C. + Ensure that operations on signed integers do not result in + overflow + + + + Will Dietz, Peng Li,y John Regehr,y and Vikram Adve, Understanding + Integer Overflow in C/C++ + + +
+
diff --git a/safe_numerics/doc/boostbook/safe_signed_range.xml b/safe_numerics/doc/boostbook/safe_signed_range.xml new file mode 100644 index 0000000..4a01ea0 --- /dev/null +++ b/safe_numerics/doc/boostbook/safe_signed_range.xml @@ -0,0 +1,96 @@ + + +
+ safe_signed_range<MIN, MAX> + +
+ Description + + This type holds a integer in the range [MIN, MAX]. It will throw a + std::out_of_range exception for operation which would result + in assigning an integer value outside of this range. +
+ +
+ Template Parameters + + + + + + + + + + + + Parameter + + Requirements + + Description + + + + + + MIN + + must be an integer literal + + The minimum integer value that this type may hold + + + + MAX + + must be an integer literal + + The maximum integer value that this type may hold + + + + + + MIN < MAX + + + + + + +
+ +
+ Model of + + Numeric +
+ +
+ Header + + #include + <boost/safe_numerics/safe_range.hpp> +
+ +
+ Example of use + + #include <safe/numeric/safe_range.hpp> + +void f(){ + boost::numeric::safe_signed_range<7, 24> i; + i = 0; // error + i = 9; // ok + i *= 9; // throws overflow exception +} +
+ +
+ See Also + + std::out_of_range +
+
diff --git a/safe_numerics/doc/boostbook/safe_unsigned_range.xml b/safe_numerics/doc/boostbook/safe_unsigned_range.xml new file mode 100644 index 0000000..2e12ad0 --- /dev/null +++ b/safe_numerics/doc/boostbook/safe_unsigned_range.xml @@ -0,0 +1,97 @@ + + +
+ safe_unsigned_range<MIN, MAX> + +
+ Description + + This type holds a integer in the range [MIN, MAX]. It will throw a + std::out_of_range exception for any operation which would + result in assigning an integer value outside of this range. +
+ +
+ Template Parameters + + + + + + + + + + + + Parameter + + Requirements + + Description + + + + + + MIN + + must be a positive integer literal + + The minimum integer value that this type may hold + + + + MAX + + must be a positive integer literal + + The maximum integer value that this type may hold + + + + + + MIN < MAX + + + + + + +
+ +
+ Model of + + Numeric +
+ +
+ Header + + #include + <safe/numeric/safe_range.hpp> +
+ +
+ Example of use + + #include <safe/numeric/safe_range.hpp> + +void f(){ + boost::numeric::safe_unsigned_range<7, 24> i; + i = 0; // throws out_of_range exception + i = 9; // ok + i *= 9; // throws out_of_range exception + i = -1; // throws out_of_range exception +} +
+ +
+ See Also + + std::out_of_range +
+
diff --git a/safe_numerics/doc/boostbook/tutorial.xml b/safe_numerics/doc/boostbook/tutorial.xml new file mode 100644 index 0000000..d75154a --- /dev/null +++ b/safe_numerics/doc/boostbook/tutorial.xml @@ -0,0 +1,74 @@ + + +
+ Tutorial + +
+ Problem:arithmetic operations can yield in correct results. + + When some operation results in a result which exceeds the capacity + of a data variable to hold it, the result is undefined. This is called + "overflow". Since word size can differ between machines, code which + produces correct results in one set of circumstances may fail when + re-compiled on a machine with different hardware. When this occurs, Most + C++ compilers will continue to execute with no indication that the results + are wrong. It is the programmer's responsabiity to ensure such undefined + behavior is avoided. + + This program demonstrates this problem. The solution is to replace + instances of char type with safe<char> + type. + + +
+ +
+ Problem:Undetected overflow + + A variation of the above is when a value is incremented/decremented + beyond it's domain. This is a common problem with for loops. + + +
+ +
+ Problem:Implicit conversions change data values + + A simple assign or arithment expression will generally convert all + the terms to the same type. Sometimes this can silently change values. For + example, when a signed data variable contains a negative type, assigning + to a unsigned type will be permitted by any C/C++ compiler but will be + treated as large unsigned value. Most modern compilers will emit a compile + time warning when this conversion is performed. The user may then decide + to change some data types or apply a static_cast. This is + less than satisfactory for two reasons: + + + + It may be unwield to change all the types to signed or + unsigned. + + + + Litering one's program with static_cast + makes it more difficult to read. + + + + We may believe that our signed type will never contain a + negative value. If we use a static_cast to suppress the + warning, we'll fail to detect a program error when it is commited. + This is aways a risk with casts. + + + + This solution is the same as the above, Just replace instances of + the int with safe<int>. + + +
+
diff --git a/safe_numerics/doc/html/acknowledgements.html b/safe_numerics/doc/html/acknowledgements.html new file mode 100644 index 0000000..8a5b7f1 --- /dev/null +++ b/safe_numerics/doc/html/acknowledgements.html @@ -0,0 +1,44 @@ + + + +Acknowledgements + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Acknowledgements

+

David + LeBlanc's is the author of SafeInt3 + library which motivated this work

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/boostbook.css b/safe_numerics/doc/html/boostbook.css new file mode 100644 index 0000000..c60e100 --- /dev/null +++ b/safe_numerics/doc/html/boostbook.css @@ -0,0 +1,601 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + http://spirit.sourceforge.net/ + + Distributed under the Boost Software License, Version 1.0. (See accompany- + ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +/*============================================================================= + Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-family: sans-serif; + } + +/*============================================================================= + Paragraphs +=============================================================================*/ + + p + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= + Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 9pt; + } + + pre.synopsis + { + font-size: 9pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + .programlisting, + .screen + { + font-size: 9pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + /* Program listings in tables don't get borders */ + td .programlisting, + td .screen + { + margin: 0pc 0pc 0pc 0pc; + padding: 0pc 0pc 0pc 0pc; + } + +/*============================================================================= + Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font: 140% } + h2 { font: bold 140% } + h3 { font: bold 130% } + h4 { font: bold 120% } + h5 { font: italic 110% } + h6 { font: italic 100% } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 130% } + h5 tt.computeroutput { font-size: 130% } + h6 tt.computeroutput { font-size: 130% } + + +/*============================================================================= + Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= + Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= + Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= + Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= + Copyright footer +=============================================================================*/ + .copyright-footer + { + text-align: right; + font-size: 70%; + } + + .copyright-footer p + { + text-align: right; + font-size: 80%; + } + +/*============================================================================= + Table of contents +=============================================================================*/ + + .toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 80%; + line-height: 1.15; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + + /* Code on toc */ + .toc .computeroutput { font-size: 120% } + +/*============================================================================= + Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + font-size: 9pt; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 80%; + } + + table.simplelist + { + width: auto !important; + margin: 0em !important; + padding: 0em !important; + border: none !important; + } + table.simplelist td + { + margin: 0em !important; + padding: 0em !important; + text-align: left !important; + font-size: 9pt !important; + border: none !important; + } + +/*============================================================================= + Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + font-size: 9pt; /* A little bit smaller than the main text */ + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + p.blurb img + { + padding: 1pt; + } + +/*============================================================================= + Variable Lists +=============================================================================*/ + + div.variablelist + { + margin: 1em 0; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt, + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + + div.variablelist dl dt + { + margin-bottom: 0.2em; + } + + div.variablelist dl dd + { + margin: 0em 0em 0.5em 2em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p, + div.variablelist dl dd p + { + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + +/*============================================================================= + Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + text-align: left + } + +/*============================================================================= + Colors +=============================================================================*/ + + @media screen + { + body { + background-color: #FFFFFF; + color: #000000; + } + + /* Syntax Highlighting */ + .keyword { color: #0000AA; } + .identifier { color: #000000; } + .special { color: #707070; } + .preprocessor { color: #402080; } + .char { color: teal; } + .comment { color: #800000; } + .string { color: teal; } + .number { color: teal; } + .white_bkd { background-color: #FFFFFF; } + .dk_grey_bkd { background-color: #999999; } + + /* Links */ + a, a .keyword, a .identifier, a .special, a .preprocessor + a .char, a .comment, a .string, a .number + { + color: #005a9c; + } + + a:visited, a:visited .keyword, a:visited .identifier, + a:visited .special, a:visited .preprocessor a:visited .char, + a:visited .comment, a:visited .string, a:visited .number + { + color: #9c5a9c; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + } + + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + border: 1px solid #DCDCDC; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #F0F0F0; + border: 1px solid #DCDCDC; + } + + .copyright-footer + { + color: #8F8F8F; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + } + + .programlisting, + .screen + { + border: 1px solid gray; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Table of contents */ + .toc + { + border: 1px solid gray; + } + + .informaltable table, + .table table + { + border: 1px solid gray; + border-collapse: collapse; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid gray; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid gray; + } + + table.simplelist tr td + { + border: none !important; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } + +/*============================================================================= + Images +=============================================================================*/ + + span.inlinemediaobject img + { + vertical-align: middle; + } + +/*============================================================================== + Super and Subscript: style so that line spacing isn't effected, see + http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341 +==============================================================================*/ + +sup, +sub { + height: 0; + line-height: 1; + vertical-align: baseline; + _vertical-align: bottom; + position: relative; + +} + +sup { + bottom: 1ex; +} + +sub { + top: .5ex; +} + diff --git a/safe_numerics/doc/html/change_log.html b/safe_numerics/doc/html/change_log.html new file mode 100644 index 0000000..aba2bed --- /dev/null +++ b/safe_numerics/doc/html/change_log.html @@ -0,0 +1,42 @@ + + + +Change Log + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Change Log

+

This is the initial version.

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/concepts.html b/safe_numerics/doc/html/concepts.html new file mode 100644 index 0000000..53b2e4f --- /dev/null +++ b/safe_numerics/doc/html/concepts.html @@ -0,0 +1,42 @@ + + + +Concepts + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Concepts

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/functions.html b/safe_numerics/doc/html/functions.html new file mode 100644 index 0000000..2f6abd0 --- /dev/null +++ b/safe_numerics/doc/html/functions.html @@ -0,0 +1,46 @@ + + + +Functions + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Functions

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/index.html b/safe_numerics/doc/html/index.html new file mode 100644 index 0000000..7a6a723 --- /dev/null +++ b/safe_numerics/doc/html/index.html @@ -0,0 +1,74 @@ + + + +Safe Numerics + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
Next
+ + + + +

Last revised: , at

+
+
Next
+ + diff --git a/safe_numerics/doc/html/introduction.html b/safe_numerics/doc/html/introduction.html new file mode 100644 index 0000000..1a51dc7 --- /dev/null +++ b/safe_numerics/doc/html/introduction.html @@ -0,0 +1,47 @@ + + + +Introduction + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Introduction

+

Arithmetic operations in C++ are NOT guarenteed to yield the correct + mathematical result. The feature is inherited from the early days of C the + behavior of int, unsigned int and others were designed to map closely to + the underlying hardware. The result is that one cannot know when + the

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/notes.html b/safe_numerics/doc/html/notes.html new file mode 100644 index 0000000..12781f5 --- /dev/null +++ b/safe_numerics/doc/html/notes.html @@ -0,0 +1,66 @@ + + + +Notes + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Notes

+

This library really an re-implementation the facilities provided by + David LeBlanc's SafeInt + Library using Boost. I found + this library very well done in every way. My main usage was to run unit + tests for my embedded systems projects on my PC. Still, I had a few + issues.

+
    +
  • I was a lot of code in one header - 6400 lines. Very unwieldy to + understand and modify.

  • +
  • I couldn't find separate documentation other than that in the + header file.

  • +
  • I didn't use Boost + conventions for naming.

  • +
  • I required porting to different compilers.

  • +
  • It had a very long license associated with it.

  • +
  • I believe the original SafeInt + library is not easily found. MSVC 10 has this built in so I seems that + they've decided to make it less attractive to use on other + systems.

  • +
+

This version addresses these issues. It exploits Boost facilities such as template + metaprogramming to reduce the number of lines of source code. It exploits + the Boost Preprocessor Library to generate exhaustive tests.

+

All concepts, types and functions documented are declared in the + namespace boost::numeric.

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/numeric.html b/safe_numerics/doc/html/numeric.html new file mode 100644 index 0000000..d61b252 --- /dev/null +++ b/safe_numerics/doc/html/numeric.html @@ -0,0 +1,382 @@ + + + +Numeric<T> + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Numeric<T>

+ +
+

+Description

+

A type is Numeric if it has the properties of a number.

+

More specifically, a type T is Numeric if there exists + specialization of std::numeric_limits<T>. See the documentation for + standard library class numeric_limits. The standard library includes such + specializations for all the primitive numeric types. Note that this + concept is distinct from the C++ standard library type traits + is_integral and is_arithmetic. These latter + fullfill the requirement of the concept Numeric. But there are types T + which fullfill this concept for which is_arithmetic<T>::value + == false. For example see + safe_signed_integer<int>.

+
+
+

+Notation

+

[The next two sections, associated types and valid expressions, + present expressions involving types that model the concept being defined. + This section defines the meaning of the variables and identifiers used in + those expressions.]

+
+

Table 1. 

+
++++ + + + + + + + + + + +
+ T, U, V + A type that is a model of the Numeric
+ t, u, v + An object of type modeling Numeric
+
+
+
+
+

+Associated Types

+

[A concept is a set of requirements on some type. Frequently, + however, some of those requirements involve some other type. For example, + one of the Unary Function requirements is that a Unary Function must have + an argument type; if F is a type that models Unary Function and f is an + object of type F, then, in the expression f(x), x must be of F's argument + type. If a concept does not have any such associated types this section + can be eliminated.]

+
+

Table 2. 

+
++++ + + + + +
+ std::numeric_limits<T> + The numeric_limits class template provides a C++ program + with information about various properties of the implementation’s + representation of the arithmetic types. See C++ standard + 18.3.2.2.
+
+
+
+
+

+Valid Expressions

+

In addition to the expressions defined in Assignable the + following expressions must be valid.

+

Any operations which result in integers which cannot be represented + as some Numeric type will throw an exception.

+
+

Table 3. General

+
++++ + + + + + + + + + + + + + + + + + + +
ExpressionReturn Value
std::numeric_limits<T>.is_bounded + true
std::numeric_limits<T>.is_integertrue
std::numeric_limits<T>.is_specialized + true
+
+


+
+

Table 4. Unary Operators

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeSemantics
-tTInvert sign
+tTunary plus - a no op
t--Tpost decrement
t++Tpost increment
--tTpredecrement
++tTpreincrement
~Tcomplement
+
+
+

Table 5. Binary Operators

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeSemantics
t - uVInvert sign
t + uVunary plus - a no op
t * uVmultiply t by u
t / uTdivide t by u
t % uTt modulus u
t << uTshift t left u bits
t >> uTshift t right by ubits
t < ubooltrue if t less than u, false otherwise
t <= ubooltrue if t less than or equal to u, false otherwise
t > ubooltrue if t greater than u, false otherwise
t >= ubooltrue if t greathan or equal to u, false otherwise
t == ubooltrue if t equal to u, false otherwise
t != ubooltrue if t not equal to u, false otherwise
t & ubooland of t and u padded out max # bits in t, u
t | uboolor of t and u padded out max # bits in t, u
t ^ uVexclusive or of t and u padded out max # bits in t, + u
t = uTassign value of u to t
t += uTadd u to t and assign to t
t -= uTsubtract u from t and assign to t
t *= uTmultiply t by u and assign to t
t /= uTdivide t by u and assign to t
t &= uTand t with u and assign to t
t <<= uTleft shift the value of t by u bits
t >>= uTright shift the value of t by u bits
t &= uTand the value of t with u and assign to t
t |= uTor the value of t with u and assign to t
t ^= uTexclusive or the value of t with u and assign to t
+
+
+
+ +
+

+Models

+

Numeric<char>, Numeric<float>, Numeric<unsigned + int>, safe_signed_integer<int> etc.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/pre-boost.jpg b/safe_numerics/doc/html/pre-boost.jpg new file mode 100644 index 0000000000000000000000000000000000000000..be684e45b1cff0ca3408c195434bdc33e3281a62 GIT binary patch literal 9606 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 MrMmbdi2eUf04y9TG5`Po literal 0 HcmV?d00001 diff --git a/safe_numerics/doc/html/rationale.html b/safe_numerics/doc/html/rationale.html new file mode 100644 index 0000000..b648f4f --- /dev/null +++ b/safe_numerics/doc/html/rationale.html @@ -0,0 +1,96 @@ + + + +Rationale + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Rationale

+
+
+
1. Why does an operation on two safe<int> + values not necessarily return another safe type + ? +
+
2. Why is there no policy driven design for handling + overflows +
+
3. Why is Boost.Convert not used. +
+
+ +++ + + + + + + + + + + + + + + + + + +
+

1.

+

Why does an operation on two safe<int> + values not necessarily return another safe type + ?

+

There are a number of

+
    +
  • it was hard to implement.

  • +
  • it doesn't really seem necessary. We always do SOMETHING + with result of the operation. This will result in an assignment + or a conversion to some other type where the result will be + validated.

  • +
  • +
  • +
+
+

2.

+

Why is there no policy driven design for handling + overflows

+

3.

+

Why is Boost.Convert not used.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/rationale/overflow.html b/safe_numerics/doc/html/rationale/overflow.html new file mode 100644 index 0000000..f713c3b --- /dev/null +++ b/safe_numerics/doc/html/rationale/overflow.html @@ -0,0 +1,92 @@ + + + +overflow + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+overflow

+ +
+

+Synopsis

+

This function is invoked by the library whenever it is not possible + to produce a result for an arithmetic operation.

+
void overflow(char const * const msg);
+
+
+

+Description

+

If evironment supports C++ exceptions, this function throws the + exception .

+

If the environment does not support C++ exceptions, the user should + implement this function and expect it to be called when appropriate. + Otherwise, function is implemented by the library so that it throws the + standard library exception std::out_of_range(msg).

+

boost/config.hpp defines BOOST_NO_EXCEPTIONS + when the environment doesn't support exceptions. It is by checking for the + definition of this macro that the system determines whether or not + exceptions are supported.

+
+ +
+

+Example of use

+
#include <cstdio>
+
+void overflow(char const * const msg){
+    std::fputs("safe_numerics overflow error:, std::stderr);
+    std::fputs(msg, std::stderr);
+    std::fputc('\n', std::stderr);
+}
+
+
+

+See Also

+

See rationale for more + information on this function

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/references.html b/safe_numerics/doc/html/references.html new file mode 100644 index 0000000..c42bfc4 --- /dev/null +++ b/safe_numerics/doc/html/references.html @@ -0,0 +1,54 @@ + + + +References + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+

+References

+

+
    +
  1. David LeBlanc, Codeplex + SafeInt Page

  2. +
  3. Daniel Plakosh, Safe + Integer Operations

  4. +
  5. Omer Katz, SafeInt + code proposal, Boost.SafeInt

  6. +
  7. Software Engineering Institute, Carnegie Mellon, INT32-C. + Ensure that operations on signed integers do not result in + overflow

  8. +
  9. Will Dietz, Peng Li,y John Regehr,y and Vikram Adve, Understanding + Integer Overflow in C/C++

  10. +
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/safe_numerics/doc/html/safe.html b/safe_numerics/doc/html/safe.html new file mode 100644 index 0000000..0440e26 --- /dev/null +++ b/safe_numerics/doc/html/safe.html @@ -0,0 +1,160 @@ + + + +safe<T> + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+safe<T>

+ +
+

+Description

+

A safe<T> can be used anywhere a type T is used. + When T is used in operation which overflows, a exception is thrown

+
+
+

+Template Parameters

+

+
+++++ + + + + + + + + + + +
ParameterType RequirementsDescription
TNumeric

The underlying integer type

+
+
+

+Model of

+

Numeric

+
+
+

+Derived From

+

safe_signed_range<T> + (if std::numeric_limits<T>::is_signed == ftrue)

+

safe_unsigned_range<T> + (if std::numeric_limits<T>::is_signed == ftrue)

+
+
+

+Notation

+
+

Table 6. 

+
++++ + + + + + + + + + + +
+ T + A type that is a model of the Numeric
+ t + An object of type modeling Numeric
+
+
+
+ +
+

+Example of use

+

The following program will emit an error message on a machine where + int is only 16 bits but run without problem on a machine where int is 32 + bits.

+
#include <boost/numeric/safe.hpp>
+#include <iostream>
+void f(){
+    safe<int> i = 400;
+    safe<int> j;
+    try {
+        j = i * i;
+    }
+    catch(...){
+       std::cout << "overflow error" << std::endl;
+    }
+}
+
+
+
+
+

+Notes

+

Footnotes (if any) that are referred to by other parts of the + page.

+
+
+

+See Also

+

Footnotes (if any) that are referred to by other parts of the + page.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/safe_cast.html b/safe_numerics/doc/html/safe_cast.html new file mode 100644 index 0000000..44809a7 --- /dev/null +++ b/safe_numerics/doc/html/safe_cast.html @@ -0,0 +1,125 @@ + + + +safe_cast + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+safe_cast

+ +
+

+Synopsis

+
template<class T, class U>
+T safe_cast(const U & u);
+
+
+

+Description

+

Converts one Numeric type + to another. Throws an std::out_of_range exception if such a + conversion is not possible without changing the value.

+
+
+

+Type requirements

+
++++ + + + + + + + + + + + + + + +
TypeRequirements
TNumeric
U Numeric
+
+
+

+Preconditions

+

The value of u can be represented by the type T. If + this is not true, an std::out_of_range exception will be + thrown.

+
+
+

+Complexity

+

[Example:]

+

O(N log(N)) comparisons (both average and worst-case), where N is + last - first. [2]

+
+ +
+

+Example of use

+

[A code fragment that illustrates how to use the function.]

+
#include <boost/numeric/safe_cast.hpp> 
+#include <boost/numeric/safe_integer.hpp> 
+
+void f(){
+    safe_integer<char> i;
+    unsigned char j;
+    i = 1;
+    j = safe_cast<unsigned char>(i);  // ok
+    i = -1;
+    j = safe_cast<unsigned char>(i);  // throws std::out_of_range exception
+    i = 1024;
+    j = safe_cast<unsigned char>(i);  // throws std::out_of_range exception
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/safe_compare.html b/safe_numerics/doc/html/safe_compare.html new file mode 100644 index 0000000..86c4135 --- /dev/null +++ b/safe_numerics/doc/html/safe_compare.html @@ -0,0 +1,117 @@ + + + +safe_compare + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+safe_compare

+ +
+

+Synopsis

+

safe_compare is really two functions:.

+
template<class T, class U>
+bool safe_compare::less_than(const T & lhs, const U & rhs);
+
+template<class T, class U>
+bool safe_compare::greater_than(const T & lhs, const U & rhs);
+
+
+

+Description

+

With normal comparison operators, comparison of unsigned types to + signed types will be done by converting the unsigned type to a signed type + before comparing. Unfortunately this is not always possible. Most C++ + compilers will emit an warning message when this is possible but won't + check that an error is made in the conversion. This function guarentees a + correct result regardless of the types of the arguments.

+
+
+

+Type requirements

+

[This section lists the requirements that must be satisfied by the + function's template parameters. If the function has no template + parameters, this section can be skipped. Example:]

+
++++ + + + + + + + + + + + + + + +
TypeRequirements
TNumeric
U Numeric
+
+
+

+Header

+

[A link to the source code where the function header is + defined.]

+

#include + <boost/numeric/safe_compare.hpp>

+
+
+

+Example of use

+
#include <boost/numeric/safe_compare.hpp>
+
+void f(){
+    int i = -1;
+    unsigned char i = 0x129;
+    unsigned int j = 1;
+    bool result;
+    result = j < i; // incorrect result
+    result = safe_compare::less_than(j < i); // correct result
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/safe_signed_range.html b/safe_numerics/doc/html/safe_signed_range.html new file mode 100644 index 0000000..690f324 --- /dev/null +++ b/safe_numerics/doc/html/safe_signed_range.html @@ -0,0 +1,117 @@ + + + +safe_signed_range<MIN, MAX> + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+safe_signed_range<MIN, MAX>

+ +
+

+Description

+

This type holds a integer in the range [MIN, MAX]. It will throw a + std::out_of_range exception for operation which would result + in assigning an integer value outside of this range.

+
+
+

+Template Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementsDescription
MINmust be an integer literalThe minimum integer value that this type may hold
MAXmust be an integer literalThe maximum integer value that this type may hold
MIN < MAX 
+
+
+

+Model of

+

Numeric

+
+ +
+

+Example of use

+
#include <safe/numeric/safe_range.hpp>
+
+void f(){
+    boost::numeric::safe_signed_integer<7, 24> i;
+    i = 0; // error
+    i = 9; // ok
+    i *= 9; // throws overflow exception
+}
+
+
+

+See Also

+

std::out_of_range

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/safe_unsigned_range.html b/safe_numerics/doc/html/safe_unsigned_range.html new file mode 100644 index 0000000..8bdb2f3 --- /dev/null +++ b/safe_numerics/doc/html/safe_unsigned_range.html @@ -0,0 +1,118 @@ + + + +safe_unsigned_range<MIN, MAX> + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+safe_unsigned_range<MIN, MAX>

+ +
+

+Description

+

This type holds a integer in the range [MIN, MAX]. It will throw a + std::out_of_range exception for operation which would result + in assigning an integer value outside of this range.

+
+
+

+Template Parameters

+
+++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterRequirementsDescription
MINmust be a positive integer literalThe minimum integer value that this type may hold
MAXmust be a positive integer literalThe maximum integer value that this type may hold
MIN < MAX 
+
+
+

+Model of

+

Numeric

+
+ +
+

+Example of use

+
#include <safe/numeric/safe_range.hpp>
+
+void f(){
+    boost::numeric::safe_unsigned_integer<7, 24> i;
+    i = 0; // error
+    i = 9; // ok
+    i *= 9; // throws out_of_range exception
+    i = -1; // throws out_of_range exception
+}
+
+
+

+See Also

+

std::out_of_range

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/tutorial.html b/safe_numerics/doc/html/tutorial.html new file mode 100644 index 0000000..a22ef31 --- /dev/null +++ b/safe_numerics/doc/html/tutorial.html @@ -0,0 +1,46 @@ + + + +Tutorial + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/doc/html/types.html b/safe_numerics/doc/html/types.html new file mode 100644 index 0000000..0921d9b --- /dev/null +++ b/safe_numerics/doc/html/types.html @@ -0,0 +1,46 @@ + + + +Types + + + + + + + + + + + + + + + +
pre-boostHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+ + + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/safe_numerics/examples/example1.cpp b/safe_numerics/examples/example1.cpp new file mode 100644 index 0000000..002e9bf --- /dev/null +++ b/safe_numerics/examples/example1.cpp @@ -0,0 +1,35 @@ +void example1(){ + // problem: undetected erroneous expression evaluation + try{ + char x = 127; + char y = 2; + char z; + // this produces an invalid result ! + z = x + y; + // it is the wrong result !!! + assert(z != 129); + // but assert fails to detect it since C++ implicitly + // converts variables to int before evaluating he expression! + assert(z != x + y); + std::cout << static_cast(z) << " != " << x + y; + detected_msg(false); + } + catch(...){ + assert(false); // never arrive here + } + // solution: replace char with safe + try{ + using namespace boost::numeric; + safe x = 127; + safe y = 2; + safe z; + // rather than producing and invalid result an exception is thrown + z = x + y; + assert(false); // never arrive here + } + catch(std::range_error & e){ + // which can catch here + std::cout << e.what(); + detected_msg(true); + } +} diff --git a/safe_numerics/examples/example2.cpp b/safe_numerics/examples/example2.cpp new file mode 100644 index 0000000..9ea3e1e --- /dev/null +++ b/safe_numerics/examples/example2.cpp @@ -0,0 +1,25 @@ +void example2(){ + // problem: undetected overflow in data type + try{ + int x = INT_MAX; + // the following silently produces an incorrect result + ++x; + //std::cout << x << " != " << -1; + detected_msg(false); + } + catch(...){ + assert(false); // never arrive here + } + // solution: replace int with safe + try{ + using namespace boost::numeric; + safe x = INT_MAX; + // throws exception when result is past maximum possible + ++x; + assert(false); // never arrive here + } + catch(std::range_error & e){ + std::cout << e.what(); + detected_msg(true); + } +} diff --git a/safe_numerics/examples/example3.cpp b/safe_numerics/examples/example3.cpp new file mode 100644 index 0000000..045bb99 --- /dev/null +++ b/safe_numerics/examples/example3.cpp @@ -0,0 +1,25 @@ +void example3(){ + // problem: undetected overflow in data type + try{ + int x = INT_MAX; + // the following silently produces an incorrect result + ++x; + //std::cout << x << " != " << -1; + detected_msg(false); + } + catch(...){ + assert(false); // never arrive here + } + // solution: replace int with safe + try{ + using namespace boost::numeric; + safe x = INT_MAX; + // throws exception when result is past maximum possible + ++x; + assert(false); // never arrive here + } + catch(std::range_error & e){ + std::cout << e.what(); + detected_msg(true); + } +} diff --git a/safe_numerics/examples/example4.cpp b/safe_numerics/examples/example4.cpp new file mode 100644 index 0000000..9524930 --- /dev/null +++ b/safe_numerics/examples/example4.cpp @@ -0,0 +1,31 @@ +#include "../include/safe_compare.hpp" + +void example4(){ + // problem: undetected underflow in data type + try{ + unsigned int x = 0; + // the following silently produces an incorrect result + --x; + // because C implicitly converts mis-matched arguments to int + // the following assert suggests the result is correct + assert(boost::numeric::safe_compare::equal(x, -1)); + // even though it's not !!! + std::cout << x << " != " << -1; + detected_msg(false); + } + catch(...){ + assert(false); // never arrive here + } + // solution: replace unsigned int with safe + try{ + using namespace boost::numeric; + safe x = 0; + // decrement unsigned to less than zero throws exception + --x; + assert(false); // never arrive here + } + catch(std::range_error & e){ + std::cout << e.what(); + detected_msg(true); + } +} diff --git a/safe_numerics/examples/example_test.cpp b/safe_numerics/examples/example_test.cpp new file mode 100644 index 0000000..0c6bceb --- /dev/null +++ b/safe_numerics/examples/example_test.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_compare.hpp" + +void detected_msg(bool detected){ + std::cout << (detected ? ": error detected!" : ": error NOT detected!: ") << std::endl; +} + +#include "example1.cpp" +#include "example2.cpp" +#include "example3.cpp" +#include "example4.cpp" + +int main(int argc, const char * argv[]){ + example1(); + example2(); + example3(); + example4(); +} \ No newline at end of file diff --git a/safe_numerics/include/concept/numeric.hpp b/safe_numerics/include/concept/numeric.hpp new file mode 100644 index 0000000..26e6eb9 --- /dev/null +++ b/safe_numerics/include/concept/numeric.hpp @@ -0,0 +1,28 @@ +#ifndef BOOST_NUMERIC_CONCEPT_NUMERIC_HPP +#define BOOST_NUMERIC_CONCEPT_NUMERIC_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include + +template +struct Numeric { + // if your program traps here, you need to create a + // std::numeric_limits class for your type T. see + // see C++ standard 18.3.2.2 + BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized == true); + BOOST_STATIC_ASSERT(std::numeric_limits::is_bounded == true); + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer == true); +}; + +#endif // BOOST_NUMERIC_CONCEPT_NUMERIC_HPP diff --git a/safe_numerics/include/numeric.hpp b/safe_numerics/include/numeric.hpp new file mode 100644 index 0000000..d62a80b --- /dev/null +++ b/safe_numerics/include/numeric.hpp @@ -0,0 +1,356 @@ +#ifndef BOOST_NUMERIC_NUMERIC_HPP +#define BOOST_NUMERIC_NUMERIC_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "concept/numeric.hpp" +#include "boost/concept/assert.hpp" + +namespace boost { +namespace numeric { + +namespace detail { + template + struct log; + + template + struct log<0, BASE> : public + boost::mpl::integral_c< + boost::intmax_t , + 0 + > + {}; + template + struct log<-1, BASE> : public + boost::mpl::integral_c< + boost::intmax_t , + 0 + > + {}; + + template + struct log : public + boost::mpl::integral_c< + boost::intmax_t , + (1 + log::value ) + > + {}; + + template + struct ulog; + + template + struct ulog<0, BASE> : public + boost::mpl::integral_c< + boost::uintmax_t , + 0 + > + {}; + template + struct ulog : public + boost::mpl::integral_c< + boost::uintmax_t , + (1 + ulog::value) + > + {}; + +} //detail + +template +class safe_signed_range; +template +class safe_unsigned_range; +template +class safe_range_base; + +} // numeric +} // boost + +namespace std { + +template +class numeric_limits< boost::numeric::safe_signed_range > : public + numeric_limits +{ + typedef boost::numeric::safe_signed_range T; +public: + BOOST_STATIC_CONSTEXPR T min() BOOST_NOEXCEPT { return T(MIN); } + BOOST_STATIC_CONSTEXPR T max() BOOST_NOEXCEPT { return T(MAX); } + BOOST_STATIC_CONSTEXPR T lowest() BOOST_NOEXCEPT { return T(MIN); } + + BOOST_STATIC_CONSTANT(int,digits = (boost::numeric::detail::log::value)); // in base 2 + BOOST_STATIC_CONSTANT(int,digits10 = (boost::numeric::detail::log::value)); // in base 10 + BOOST_STATIC_CONSTANT(int,max_digits10 = digits10); +}; + +template +class numeric_limits< boost::numeric::safe_unsigned_range > : public + numeric_limits +{ + typedef boost::numeric::safe_unsigned_range T; +public: + BOOST_STATIC_CONSTEXPR T min() BOOST_NOEXCEPT { return T(MIN); } + BOOST_STATIC_CONSTEXPR T max() BOOST_NOEXCEPT { return T(MAX); } + BOOST_STATIC_CONSTEXPR T lowest() BOOST_NOEXCEPT { return T(MIN); } + + BOOST_STATIC_CONSTEXPR int digits = boost::numeric::detail::ulog::value; // in base 2 + BOOST_STATIC_CONSTEXPR int digits10 = boost::numeric::detail::ulog::value; // in base 10 + BOOST_STATIC_CONSTEXPR int max_digits10 = digits10; +}; + +template +class numeric_limits< boost::numeric::safe_range_base > : public + numeric_limits +{}; + +} // std + +namespace boost { +namespace numeric { + +// can't use is_signed type traits as these are defined ONLY for C++ +// primitive types. They are are not (by design) implemented in terms +// of numeric_limits so they aren't helpful to us. We leave then in the +// boost/numeric namespace to distinguish them form the "official" type +// traits ! +template +struct is_signed : public + boost::mpl::integral_c< + bool, + std::numeric_limits::is_signed + > +{ + BOOST_CONCEPT_ASSERT((Numeric)); +}; +template +struct is_unsigned : public + boost::mpl::integral_c< + bool, + ! std::numeric_limits::is_signed + > +{ + BOOST_CONCEPT_ASSERT((Numeric)); +}; + +// return the number of bits in a type excluding any sign +template +struct digits : public + boost::mpl::integral_c::digits> +{ + BOOST_CONCEPT_ASSERT((Numeric)); +}; + +// return maximum bits in types T and U +template +struct max_digits : public + boost::mpl::max< + digits, + digits + >::type +{}; + +// return the number of bits in a type +template +struct bits : public + boost::mpl::plus< + typename boost::mpl::integral_c::digits>, + typename boost::mpl::integral_c::is_signed> + > +{}; + +// return maximum bits in types T and U +template +struct max_bits : public + boost::mpl::max< + bits, + bits + >::type +{}; + +// return # of bit in the result of an addition of two types +template +struct addition_result_bits : public + boost::mpl::plus< + max_digits, + // if either is signed + typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + // add one guard bit and one sign bit + boost::mpl::integral_c, + // add one guard bit to detect overflow + boost::mpl::integral_c + >::type + > +{}; + +// return smallest type that can hold the sum of types T and U +template +struct addition_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + boost::mpl::min< + bits, + addition_result_bits + >::type::value + >::least, + typename boost::uint_t< + boost::mpl::min< + bits, + addition_result_bits + >::type::value + >::least + >::type type; +}; + +// return # of bit in the result of an subtraction of two types +template +struct subtraction_result_bits : public + boost::mpl::plus< + max_digits, + // add one guard bit and one sign bit + boost::mpl::integral_c + > +{}; + +// return smallest type that can hold the difference of types T and U +template +struct subtraction_result_type { + typedef typename boost::int_t< + boost::mpl::min< + bits, + subtraction_result_bits + >::type::value + >::least type; +}; + +// return # of bits in the result of an product of two types +template +struct multiply_result_bits : public + boost::mpl::plus< + digits, + digits, + // if either is signed + typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + // add one sign bit + boost::mpl::integral_c, + boost::mpl::integral_c + >::type + > +{}; + +// return smallest type that can hold the product of types T and U +template +struct multiply_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + boost::mpl::min< + bits, + multiply_result_bits + >::type::value + >::least, + typename boost::uint_t< + boost::mpl::min< + bits, + multiply_result_bits + >::type::value + >::least + >::type type; +}; + +// return # of bits in the result of an quotient of two types +template +struct division_result_bits : public + boost::mpl::plus< + digits, + // if either is signed + typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + // add one sign bit + boost::mpl::integral_c, + boost::mpl::integral_c + >::type + > +{}; + +// return smallest type that can hold the quotient of types T and U +template +struct division_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + boost::mpl::min< + bits, + division_result_bits + >::type::value + >::least, + typename boost::uint_t< + boost::mpl::min< + bits, + division_result_bits + >::type::value + >::least + >::type type; +}; + +// return the type which results from usage of one the +// operators &, |, ^, <<, >> +template +struct logical_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + max_bits::value + >::least, + typename boost::uint_t< + max_bits::value + >::least + >::type type; +}; + +} // numeric +} // boost + +#endif // BOOST_NUMERIC_NUMERIC_HPP diff --git a/safe_numerics/include/overflow.hpp b/safe_numerics/include/overflow.hpp new file mode 100644 index 0000000..d39035d --- /dev/null +++ b/safe_numerics/include/overflow.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_NUMERIC_SAFE_OVERFLOW_HPP +#define BOOST_NUMERIC_SAFE_OVERFLOW_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include + +namespace boost { +namespace numeric { + +#ifndef BOOST_NO_EXCEPTIONS + inline void overflow(char const * const msg) { + throw std::range_error(msg); + } +#else + void overflow(char const * const msg); +#endif + +} // namespace numeric +} // namespace boost + +#endif // BOOST_NUMERIC_SAFE_OVERFLOW_HPP diff --git a/safe_numerics/include/safe_cast.hpp b/safe_numerics/include/safe_cast.hpp new file mode 100644 index 0000000..917ac3d --- /dev/null +++ b/safe_numerics/include/safe_cast.hpp @@ -0,0 +1,112 @@ +#ifndef BOOST_NUMERIC_SAFE_CAST_HPP +#define BOOST_NUMERIC_SAFE_CAST_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include +#include "numeric.hpp" +#include "overflow.hpp" + +namespace boost { +namespace numeric { +namespace detail { + // simple case when signess are the same. + template + struct safe_cast { + template + inline static T invoke(const U & u){ + if(u > std::numeric_limits::max()) + overflow("safe range overflow"); + if(u < std::numeric_limits::min()) + overflow("safe range underflow"); + return static_cast(u); + } + }; + + // T signed <- U unsigned + template<> + struct safe_cast { + template + struct sbits : public + boost::mpl::min< + typename boost::mpl::integral_c< + int, + std::numeric_limits::digits + >, + typename boost::mpl::plus< + typename boost::mpl::integral_c< + int, + std::numeric_limits::digits + >, + typename boost::mpl::integral_c + > + >::type + {}; + template + inline static T invoke(const U & u){ + // figure # of bits in U + // if that # == maximum supported + if(bits::value == bits::value) + // just cast to signed and + // choke if it's negative + if(static_cast(u) < 0) + overflow("safe range overflow"); + + typedef typename boost::int_t< + sbits::value + >::fast signed_u_type; + + return safe_cast::invoke( + static_cast(u) + ); + } + }; + + // T unsigned <- U signed + template<> + struct safe_cast { + template + inline static T invoke(const U & u){ + if(u < 0) + overflow("safe range underflow"); + + typedef typename boost::uint_t< + boost::mpl::integral_c< + int, + std::numeric_limits::digits + >::value + >::fast unsigned_u_type; + + return safe_cast::invoke( + static_cast(u) + ); + } + }; + +} // detail + +template +T safe_cast(const U & u) { + T t = detail::safe_cast< + boost::numeric::is_signed::value, + boost::numeric::is_signed::value + >::template invoke(u); + return t; +} + +} // numeric +} // boost + +#endif // BOOST_NUMERIC_SAFE_CAST_HPP diff --git a/safe_numerics/include/safe_compare.hpp b/safe_numerics/include/safe_compare.hpp new file mode 100644 index 0000000..40bff79 --- /dev/null +++ b/safe_numerics/include/safe_compare.hpp @@ -0,0 +1,155 @@ +#ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP +#define BOOST_NUMERIC_SAFE_COMPARE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include +#include +#include + +#include "numeric.hpp" + +namespace boost { +namespace numeric { +namespace safe_compare { + namespace detail { + // note make_unsigned needs more research. We use the one + // from boost type_traits. BUT boost type_traits only handles + // C primitives. What we really want is something which works + // for any type T such that std::numeric_limits::is_signed is true. + template + struct make_unsigned { + typedef typename boost::mpl::if_< + boost::is_integral, + typename boost::make_unsigned, + typename boost::mpl::identity + >::type::type type; + }; + // both arguments unsigned or signed + template + struct less_than { + template + static bool invoke(const T & t, const U & u){ + return t < u; + } + }; + + // T unsigned, U signed + template<> + struct less_than { + template + static bool invoke(const T & t, const U & u){ + if(u < 0) + return false; + return less_than::invoke( + t, + static_cast::type &>(u) + ); + } + }; + // T signed, U unsigned + template<> + struct less_than { + template + static bool invoke(const T & t, const U & u){ + if(t < 0) + return true; + return less_than::invoke( + static_cast::type &>(t), + u + ); + } + }; + } // detail + + template + bool less_than(const T & lhs, const U & rhs) { + return detail::less_than< + boost::numeric::is_signed::value, + boost::numeric::is_signed::value + >::template invoke(lhs, rhs); + } + + template + bool greater_than_equal(const T & lhs, const U & rhs) { + return less_than(rhs, lhs); + } + + namespace detail { + // both arguments unsigned or signed + template + struct greater_than { + template + static bool invoke(const T & t, const U & u){ + return t > u; + } + }; + + // T unsigned, U signed + template<> + struct greater_than { + template + static bool invoke(const T & t, const U & u){ + if(u < 0) + return true; + return greater_than::invoke( + t, + static_cast::type &>(u) + ); + } + }; + // T signed, U unsigned + template<> + struct greater_than { + template + static bool invoke(const T & t, const U & u){ + if(t < 0) + return false; + return greater_than::invoke( + static_cast::type &>(t), + u + ); + } + }; + } // detail + + template + bool greater_than(const T & lhs, const U & rhs) { + return detail::greater_than< + boost::numeric::is_signed::value, + boost::numeric::is_signed::value + >::template invoke(lhs, rhs); + } + + template + bool less_than_equal(const T & lhs, const U & rhs) { + return greater_than(rhs, lhs); + } + + template + bool equal(const T & lhs, const U & rhs) { + return ! less_than(lhs, rhs) && ! greater_than(lhs, rhs); + } + + template + bool not_equal(const T & lhs, const U & rhs) { + return ! equal(lhs, rhs); + } + +} // safe_compare +} // numeric +} // boost + +#endif // BOOST_NUMERIC_SAFE_COMPARE_HPP diff --git a/safe_numerics/include/safe_integer.hpp b/safe_numerics/include/safe_integer.hpp new file mode 100644 index 0000000..a4fa215 --- /dev/null +++ b/safe_numerics/include/safe_integer.hpp @@ -0,0 +1,81 @@ +#ifndef BOOST_NUMERIC_SAFE_INTEGER_HPP +#define BOOST_NUMERIC_SAFE_INTEGER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include "safe_range.hpp" + +namespace boost { +namespace numeric { + +namespace detail{ + template + struct safe_integer_base { + typedef typename boost::mpl::if_c< + std::numeric_limits::is_signed, + safe_signed_range< + boost::integer_traits::const_min, + boost::integer_traits::const_max + >, + safe_unsigned_range< + boost::integer_traits::const_min, + boost::integer_traits::const_max + > + >::type type; + }; +} // detail + +template +struct safe : public detail::safe_integer_base::type { + typedef typename detail::safe_integer_base::type base_type; + + // verify that std::numeric_limits has been specialized for this type + BOOST_STATIC_ASSERT_MSG( + std::numeric_limits::is_specialized, + "std::numeric_limits has not been specialized for this type" + ); + // verify that T is an integer type + BOOST_STATIC_ASSERT_MSG( + std::numeric_limits::is_integer, + "T is not an integer type" + ); + safe(){} + + template + safe(const U & u) : + detail::safe_integer_base::type(u) + {} +}; + +} // numeric +} // boost + +#include // BOOST_NOEXCEPT + +namespace std { + +template +class numeric_limits< boost::numeric::safe > : public + numeric_limits +{ + typedef boost::numeric::safe SI; +public: + BOOST_STATIC_CONSTEXPR SI min() BOOST_NOEXCEPT { return numeric_limits::min(); } + BOOST_STATIC_CONSTEXPR SI max() BOOST_NOEXCEPT { return numeric_limits::max(); } + BOOST_STATIC_CONSTEXPR SI lowest() BOOST_NOEXCEPT { return numeric_limits::min(); } +}; + +} // std + +#endif // BOOST_NUMERIC_SAFE_INTEGER_HPP diff --git a/safe_numerics/include/safe_range.hpp b/safe_numerics/include/safe_range.hpp new file mode 100644 index 0000000..6684e81 --- /dev/null +++ b/safe_numerics/include/safe_range.hpp @@ -0,0 +1,795 @@ +#ifndef BOOST_NUMERIC_SAFE_RANGE_HPP +#define BOOST_NUMERIC_SAFE_RANGE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include "numeric.hpp" +#include "safe_compare.hpp" +#include "safe_cast.hpp" +#include "overflow.hpp" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace numeric { + +namespace detail { + template + struct check_addition_overflow{}; + + // both arguments unsigned + template<> + struct check_addition_overflow { + template + static typename addition_result_type::type + add(const T & t, const U & u){ + typedef typename addition_result_type::type result_type; + result_type tmp; + tmp = static_cast(t) + static_cast(u); + if(safe_compare::less_than(tmp, t)) + overflow("safe range addition out of range"); + return tmp; + } + }; + // T unsigned, U signed + template<> + struct check_addition_overflow { + template + static typename addition_result_type::type + add(const T & t, const U & u){ + if(u > 0) + return check_addition_overflow::add(t, u); + return t + u; + } + }; + // T signed, U unsigned + template<> + struct check_addition_overflow { + template + static typename addition_result_type::type + add(const T & t, const U & u){ + if(t > 0) + return check_addition_overflow::add(t, u); + return t + u; + } + }; + // both arguments signed + template<> + struct check_addition_overflow { + template + static typename addition_result_type::type + add(const T & t, const U & u){ + if(t > 0) + check_addition_overflow::add(t, u); + if(u < 0){ + typedef typename addition_result_type::type result_type; + result_type tmp; + tmp = static_cast(t) + static_cast(u); + if(safe_compare::greater_than(tmp, t)) + overflow("safe range addition out of range"); + return tmp; + } + return t + u; + } + }; + + template + struct check_multiplication_overflow; + + // both arguments unsigned + template<> + struct check_multiplication_overflow { + template + static void invoke(const T & t, const U & u){ + char const * const msg = "safe range multiplication out of range"; + typedef boost::uintmax_t accumulator_type; + const int temp_bits = bits::value / 2; + typedef typename boost::uint_t::least temp_type; + + temp_type a = (static_cast(t) >> temp_bits); + temp_type c = (static_cast(u) >> temp_bits); + if(0 != a && 0 != c) + overflow(msg); + + temp_type b = static_cast(t); + if((static_cast(b) * static_cast(c) >> temp_bits) > 0) + overflow(msg); + + temp_type d = static_cast(u); + if(0 != (static_cast(a) * static_cast(d) >> temp_bits)) + overflow(msg); + } + }; + // T unsigned, U signed + template<> + struct check_multiplication_overflow { + template + static void invoke(const T & t, const U & u){ + check_multiplication_overflow::invoke( + t, + u < 0 ? -u : u + ); + } + }; + // T signed, U unsigned + template<> + struct check_multiplication_overflow { + template + static void invoke(const T & t, const U & u){ + check_multiplication_overflow::invoke( + t < 0 ? -t : t, + u + ); + } + }; + // both arguments signed, signed + template<> + struct check_multiplication_overflow { + template + static void invoke(const T & t, const U & u){ + check_multiplication_overflow::invoke( + t < 0 ? -t : t, + u < 0 ? -u : u + ); + } + }; +} // detail + +template< + class Stored, + class Derived +> +class safe_range_base { + Derived & + derived() { + return static_cast(*this); + } + const Derived & + derived() const { + return static_cast(*this); + } + template + Stored validate(const T & t) const { + return derived().validate(t); + } + Stored m_t; +protected: + //////////////////////////////////////////////////////////// + // constructors + // default constructor + safe_range_base() {} + + // copy constructor + safe_range_base(const safe_range_base & t) : + m_t(t.m_t) + {} + template + safe_range_base(const T & t) + { + // verify that this is convertible to the storable type + BOOST_STATIC_ASSERT(( boost::is_convertible::value )); + validate(t); + m_t = static_cast(t); + } + typedef Stored stored_type; +public: + template + Derived & operator=(const T & rhs){ + m_t = validate(rhs); + return derived(); + } + template + Derived & operator+=(const T & rhs){ + *this = *this + rhs; + return derived(); + } + template + Derived & operator-=(const T & rhs){ + *this = *this - rhs; + return derived(); + } + template + Derived & operator*=(const T & rhs){ + *this = *this * rhs; + return derived(); + } + template + Derived & operator/=(const T & rhs){ + *this = *this / rhs; + return derived(); + } + template + Derived & operator%=(const T & rhs){ + *this = *this % rhs; + return derived(); + } + template + Derived & operator|=(const T & rhs){ + *this = *this | rhs; + return derived(); + } + template + Derived & operator&=(const T & rhs){ + *this = *this & rhs; + return derived(); + } + template + Derived & operator^=(const T & rhs){ + *this = *this * rhs; + return derived(); + } + template + Derived & operator>>=(const T & rhs){ + *this = *this >> rhs; + return derived(); + } + template + Derived & operator<<=(const T & rhs){ + *this = *this << rhs; + return derived(); + } + Derived operator++(){ + *this = *this + 1; + return derived(); + } + Derived operator--(){ + *this = *this - 1; + return derived(); + } + Derived operator++(int){ + Derived rvalue = *this; + m_t = validate(*this + 1); + return rvalue; + } + Derived & operator--(int){ + Derived rvalue = *this; + m_t = validate(*this - 1); + return rvalue; + } + Derived operator-() const { + return validate(- m_t); + } + Derived operator~() const { + return validate(~m_t); + } + + ///////////////////////////////////////////////////////////////// + // comparison operators + template + bool operator<(const U & rhs) const { + return safe_compare::less_than(m_t, rhs); + } + template + bool operator>(const U & rhs) const { + return safe_compare::greater_than(m_t, rhs); + } + template + bool operator==(const U & rhs) const { + return safe_compare::equal(m_t, rhs); + } + template + bool inline operator!=(const U & rhs) const { + return ! safe_compare::equal(m_t,rhs); + } + template + bool inline operator>=(const U & rhs) const { + return ! safe_compare::less_than(m_t, rhs); + } + template + bool inline operator<=(const U & rhs) const { + return ! safe_compare::greater_than(m_t, rhs); + } + + ///////////////////////////////////////////////////////////////// + // addition + // case 1 - no overflow possible + template + typename boost::enable_if< + typename boost::mpl::less_equal< + addition_result_bits, + // note presumption that size(boost::uintmax) == size(boost::intmax) + bits + >, + typename addition_result_type::type + >::type + inline operator+(const U & rhs) const { + typedef typename addition_result_type::type result_type; + return static_cast(m_t) + static_cast(rhs); + } + + // case 2 - overflow possible - must be checked at run time + template + typename boost::enable_if< + typename boost::mpl::greater< + addition_result_bits, + // note presumption that size(boost::uintmax) == size(boost::intmax) + bits + >, + typename addition_result_type::type + >::type + inline operator+(const U & rhs) const { + return detail::check_addition_overflow< + boost::numeric::is_signed::value, + boost::numeric::is_signed::value + >::add(m_t, rhs); + } + + ///////////////////////////////////////////////////////////////// + // subtraction + template + typename boost::enable_if< + typename boost::mpl::less_equal< + subtraction_result_bits, + bits + >, + typename subtraction_result_type::type + >::type + inline operator-(const U & rhs) const { + typedef typename subtraction_result_type::type result_type; + return static_cast(m_t) - static_cast(rhs); + } + + template + typename boost::enable_if< + typename boost::mpl::greater< + subtraction_result_bits, + bits + >, + typename subtraction_result_type::type + >::type + inline operator-(const U & rhs) const { + typedef typename subtraction_result_type::type result_type; + result_type tmp; + tmp = static_cast(m_t) - static_cast(rhs); + if(tmp > static_cast(m_t)) + overflow("safe range subtraction out of range"); + return tmp; + } + + ///////////////////////////////////////////////////////////////// + // multiplication + template + typename boost::enable_if< + typename boost::mpl::less_equal< + multiply_result_bits, + // note presumption that size(boost::uintmax) == size(boost::intmax) + bits + >, + typename multiply_result_type::type + >::type + inline operator*(const U & rhs) const { + typedef typename multiply_result_type::type result_type; + return static_cast(m_t) * static_cast(rhs); + } + + // implement multiply larger numbers. This is + // intended to function for all combinations of + // signed/unsigned types when the product exceeds + // the maximum integer size + template + typename boost::enable_if< + typename boost::mpl::greater< + multiply_result_bits, + bits + >, + boost::uintmax_t + >::type + inline operator*(const U & rhs) const { + detail::check_multiplication_overflow< + boost::numeric::is_signed::value, + boost::numeric::is_signed::value + >::invoke(m_t, rhs); + + return static_cast(m_t) * static_cast(rhs); + } + + ///////////////////////////////////////////////////////////////// + // division + // simple case - default rules work + template + typename boost::enable_if< + typename boost::mpl::less_equal< + division_result_bits, + bits + >, + typename division_result_type::type + >::type + inline operator/(const U & rhs) const { + if(0 == rhs) + throw std::domain_error("Divide by zero"); + return safe_cast::type>(m_t / rhs); + } + + // special case - possible overflow + template + typename boost::enable_if< + typename boost::mpl::greater< + division_result_bits, + bits + >, + typename division_result_type::type + >::type + inline operator/(const U & rhs) const { + if(0 == rhs) + throw std::domain_error("Divide by zero"); + return safe_cast::type>(m_t / rhs); + } + + ///////////////////////////////////////////////////////////////// + // modulus + template + typename division_result_type::type + inline operator%(const U & rhs) const { + if(0 == rhs) + throw std::domain_error("Divide by zero"); + return safe_cast::type>(m_t % rhs); + } + + ///////////////////////////////////////////////////////////////// + // logical operators + template + typename logical_result_type::type + inline operator|(const U & rhs) const { + typedef typename logical_result_type::type result_type; + return static_cast(m_t) | static_cast(rhs); + } + template + typename logical_result_type::type + inline operator&(const U & rhs) const { + typedef typename logical_result_type::type result_type; + return static_cast(m_t) & static_cast(rhs); + } + template + typename logical_result_type::type + inline operator^(const U & rhs) const { + typedef typename logical_result_type::type result_type; + return static_cast(m_t) ^ static_cast(rhs); + } + template + Stored inline operator>>(const U & rhs) const { + typedef typename logical_result_type::type result_type; + return static_cast(m_t) >> static_cast(rhs); + } + template + Stored inline operator<<(const U & rhs) const { + typedef typename logical_result_type::type result_type; + return static_cast(m_t) << static_cast(rhs); + } + + ///////////////////////////////////////////////////////////////// + // casting operators for intrinsic integers + operator stored_type () const { + return m_t; + } +}; + +///////////////////////////////////////////////////////////////// +// Note: the following global operators will be only found via +// argument dependent lookup. So they won't conflict any +// other global operators for types in namespaces other than +// boost::numeric + +// These should catch things like U < safe_range_base<...> and implement them +// as safe_range_base<...> >= U which should be handled above. + +///////////////////////////////////////////////////////////////// +// binary operators + +// comparison operators +template +typename boost::enable_if< + boost::is_integral, + bool +>::type +operator<(const T & lhs, const safe_range_base & rhs) { + return rhs >= lhs; +} +template +typename boost::enable_if< + boost::is_integral, + bool +>::type +inline operator>(const T & lhs, const safe_range_base & rhs) { + return rhs <= lhs; +} +template +typename boost::enable_if< + boost::is_integral, + bool +>::type +inline operator==(const T & lhs, const safe_range_base & rhs) { + return rhs == lhs; +} +template +typename boost::enable_if< + boost::is_integral, + bool +>::type +inline operator!=(const T & lhs, const safe_range_base & rhs) { + return rhs != rhs; +} +template +typename boost::enable_if< + boost::is_integral, + bool +>::type +inline operator>=(const T & lhs, const safe_range_base & rhs) { + return rhs < lhs; +} +template +typename boost::enable_if< + boost::is_integral, + bool +>::type +inline operator<=(const T & lhs, const safe_range_base & rhs) { + return rhs > lhs; +} + +// addition +template +typename boost::enable_if< + boost::is_integral, + typename addition_result_type::type +>::type +inline operator+(const T & lhs, const safe_range_base & rhs) { + return rhs + lhs; +} + +// subtraction +template +typename boost::enable_if< + boost::is_integral, + typename subtraction_result_type::type +>::type +inline operator-(const T & lhs, const safe_range_base & rhs) { + typename subtraction_result_type::type tmp; + tmp = rhs - lhs; + return - tmp; +} + +// multiplication +template +typename boost::enable_if< + boost::is_integral, + typename multiply_result_type::type +>::type +inline operator*(const T & lhs, const safe_range_base & rhs) { + return rhs * lhs; +} + +// division +// special case - possible overflow +template +typename boost::enable_if< + boost::is_integral, + typename division_result_type::type +>::type +inline operator/(const T & lhs, const safe_range_base & rhs) { + if(safe_compare::equal(0, rhs)) + throw std::domain_error("Divide by zero"); + return static_cast< + typename division_result_type::type + >(lhs / static_cast(rhs)); +} + +// modulus +template +typename boost::enable_if< + boost::is_integral, + typename division_result_type::type +>::type +inline operator%(const T & lhs, const safe_range_base & rhs) { + if(safe_compare::equal(0, rhs)) + throw std::domain_error("Divide by zero"); + return static_cast< + typename division_result_type::type + >(lhs % static_cast(rhs)); +} + +// logical operators +template +typename boost::enable_if< + boost::is_integral, + typename multiply_result_type::type +>::type +inline operator|(const T & lhs, const safe_range_base & rhs) { + return rhs | lhs; +} +template +typename boost::enable_if< + boost::is_integral, + typename logical_result_type::type +>::type +inline operator&(const T & lhs, const safe_range_base & rhs) { + return rhs & lhs; +} +template +typename boost::enable_if< + boost::is_integral, + typename logical_result_type::type +>::type +inline operator^(const T & lhs, const safe_range_base & rhs) { + return rhs ^ lhs; +} + +///////////////////////////////////////////////////////////////// +// higher level types implemented in terms of safe_range_base + +namespace detail { + template< + boost::intmax_t MIN, + boost::intmax_t MAX + > + struct signed_stored_type { + // double check that MIN < MAX + typedef typename boost::int_t< + boost::mpl::max< + typename boost::numeric::detail::log, + typename boost::numeric::detail::log + >::type::value + >::least type; + }; + template< + boost::uintmax_t MIN, + boost::uintmax_t MAX + > + struct unsigned_stored_type { + // calculate max(abs(MIN, MAX)) + typedef typename boost::uint_t< + boost::mpl::max< + typename boost::numeric::detail::ulog, + typename boost::numeric::detail::ulog + >::type::value + >::least type; + }; +} // detail + +///////////////////////////////////////////////////////////////// +// safe_signed_range + +template< + boost::intmax_t MIN, + boost::intmax_t MAX +> +class safe_signed_range : public + safe_range_base< + typename detail::signed_stored_type::type, + safe_signed_range + > +{ + BOOST_STATIC_ASSERT_MSG( + MIN < MAX, + "minimum must be less than maximum" + ); +public: + typedef typename boost::numeric::safe_range_base< + typename detail::signed_stored_type::type, + safe_signed_range + > base; + + typedef typename detail::signed_stored_type::type stored_type; + template + stored_type validate(const T & t) const { + const boost::intmax_t tx = t; + if(MAX < tx + || MIN > tx + ) + overflow("safe range out of range"); + return static_cast(t); + } + safe_signed_range(){} + + template + safe_signed_range(const T & t) : + base(t) + {} +}; + +template< + boost::intmax_t MIN, + boost::intmax_t MAX +> +std::ostream & operator<<(std::ostream & os, const safe_signed_range & t){ + return os << static_cast::stored_type &>(t); +} + +template< + boost::intmax_t MIN, + boost::intmax_t MAX +> +std::istream & operator>>(std::istream & is, safe_signed_range & t){ + typename safe_signed_range::stored_type tx; + is >> tx; + t = tx; + return is; +} + +///////////////////////////////////////////////////////////////// +// safe_unsigned_range + +template< + boost::uintmax_t MIN, + boost::uintmax_t MAX +> +class safe_unsigned_range : public + safe_range_base< + typename detail::unsigned_stored_type::type, + safe_unsigned_range + > +{ + BOOST_STATIC_ASSERT_MSG( + MIN < MAX, + "minimum must be less than maximum" + ); +public: + typedef typename boost::numeric::safe_range_base< + typename detail::unsigned_stored_type::type, + safe_unsigned_range + > base; + typedef typename detail::unsigned_stored_type::type stored_type; + template + stored_type validate(const T & t) const { + const boost::uintmax_t tx = t; + if(MAX < tx + || MIN > tx + ) + overflow("safe range out of range"); + return static_cast(t); + } + safe_unsigned_range(){} + + template + safe_unsigned_range(const T & t) : + base(t) + {} +}; + +template< + boost::uintmax_t MIN, + boost::uintmax_t MAX +> +std::ostream & operator<<(std::ostream & os, const safe_unsigned_range & t){ + return os << static_cast::stored_type &>(t); +} + +template< + boost::uintmax_t MIN, + boost::uintmax_t MAX +> +std::istream & operator>>(std::istream & is, safe_unsigned_range & t){ + typename safe_unsigned_range::stored_type tx; + is >> tx; + t = tx; + return is; +} + +} // numeric +} // boost + +#endif // BOOST_NUMERIC_SAFE_RANGE_HPP diff --git a/safe_numerics/tests/test.cpp b/safe_numerics/tests/test.cpp new file mode 100644 index 0000000..f44ccbd --- /dev/null +++ b/safe_numerics/tests/test.cpp @@ -0,0 +1,87 @@ +#include "../include/safe_range.hpp" + +void test1(){ + boost::numeric::safe_signed_range<-64, 63> x, y, z; + x = 1; + y = 2; + z = 3; + z = x + y; + z = x - y; + short int yi, zi; + zi = x; + typedef boost::mpl::print< + boost::numeric::addition_result_bits< + boost::numeric::safe_signed_range<-64, 63>, + int + >::type + >::type t1; + typedef boost::mpl::print< + boost::numeric::bits< + boost::numeric::safe_signed_range<-64, 63> + >::type + >::type t2; + typedef boost::mpl::print< + boost::numeric::bits< + int + >::type + >::type t3; + + zi = x + yi; + z = x + yi; +} + +void test2(){ + boost::numeric::safe_unsigned_range<0, 64> x, y, z; + x = 1; + y = 2; + z = 3; + z = x + y; + z = x - y; + int yi, zi; + zi = x; + zi = x + yi; + z = x + yi; +} + +void test3(){ + boost::numeric::safe_int x, y, z; + x = 1; + y = 2; + z = 3; + z = x + y; + z = x - y; + int yi, zi; + zi = x; + zi = x + yi; + z = x + yi; +} + +void test4(){ + boost::numeric::safe_unsigned_int x, y, z; + x = 1; + y = 2; + z = 3; + z = x + y; + z = x - y; + unsigned int yi, zi; + zi = x; + zi = x + yi; + z = x + yi; + zi = x + y; +} + +#include + +void test5(){ + boost::numeric::safe_integer x, y, z; + x = 1; + y = 2; + z = 3; + z = x + y; + z = x - y; + boost::uint64_t yi, zi; + zi = x; + zi = x + yi; + z = x + yi; + zi = x + y; +} diff --git a/safe_numerics/tests/test.hpp b/safe_numerics/tests/test.hpp new file mode 100644 index 0000000..b5f4c4a --- /dev/null +++ b/safe_numerics/tests/test.hpp @@ -0,0 +1,116 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_cast.hpp" + +#define VALUES (20, ( \ + 0x10, \ + 0x20, \ + 0x7f, \ + 0x80, \ + 0xff, \ + 0x1000, \ + 0x2000, \ + 0x7fff, \ + 0x8000, \ + 0xffff, \ + 0x10000000, \ + 0x20000000, \ + 0x7fffffff, \ + 0x80000000, \ + 0xffffffff, \ + 0x100000000000, \ + 0x200000000000, \ + 0x7fffffffffff, \ + 0x80000000ffff, \ + 0xffffffffffff \ +)) +/**/ + +inline unsigned int +count_bits(boost::uintmax_t t){ + unsigned int i = 0; + while(t != 0){ + ++i; + t >>= 1; + } + return i; +} + +inline unsigned int +count_bits(boost::intmax_t t){ + if(t < 0) + t = -t; + unsigned int i = 0; + while(t != 0){ + ++i; + t >>= 1; + } + return i; +} + +#define EACH_VALUE2(z, l, list) \ + BOOST_PP_EXPAND( \ + TESTX \ + BOOST_PP_LIST_TO_TUPLE( \ + BOOST_PP_LIST_CONS( \ + BOOST_PP_ARRAY_ELEM(l, VALUES), \ + list \ + ) \ + ) \ + ) \ +/**/ + +#define EACH_VALUE1(z, k, types) \ + BOOST_PP_REPEAT( \ + BOOST_PP_ARRAY_SIZE(VALUES), \ + EACH_VALUE2, \ + BOOST_PP_LIST_CONS( \ + BOOST_PP_ARRAY_ELEM(k, VALUES), \ + types \ + ) \ + ) \ +/**/ + +#define EACH_TYPE2(i, j) \ + BOOST_PP_REPEAT( \ + BOOST_PP_ARRAY_SIZE(VALUES), \ + EACH_VALUE1, \ + (i, (j, BOOST_PP_NIL)) \ + ) \ +/**/ + +#define EACH_TYPE1(i) \ + EACH_TYPE2(i, boost::int8_t) \ + EACH_TYPE2(i, boost::uint8_t) \ + EACH_TYPE2(i, boost::int16_t) \ + EACH_TYPE2(i, boost::uint16_t) \ + EACH_TYPE2(i, boost::int32_t) \ + EACH_TYPE2(i, boost::uint32_t) \ + EACH_TYPE2(i, boost::int64_t) \ + EACH_TYPE2(i, boost::uint64_t) \ +/**/ + +#define TEST \ + EACH_TYPE1(boost::int8_t) \ + EACH_TYPE1(boost::uint8_t) \ + EACH_TYPE1(boost::int16_t) \ + EACH_TYPE1(boost::uint16_t) \ + EACH_TYPE1(boost::int32_t) \ + EACH_TYPE1(boost::uint32_t) \ + EACH_TYPE1(boost::int64_t) \ + EACH_TYPE1(boost::uint64_t) \ +/**/ + diff --git a/safe_numerics/tests/test_add.cpp b/safe_numerics/tests/test_add.cpp new file mode 100644 index 0000000..d023267 --- /dev/null +++ b/safe_numerics/tests/test_add.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2012 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) + +bool test_add1(); +bool test_add2(); +bool test_add3(); + +int main(int argc, char * argv[]){ + bool result = true; + result = test_add1(); + result &= test_add2(); + result &= test_add3(); + return ! result ; +} diff --git a/safe_numerics/tests/test_add.hpp b/safe_numerics/tests/test_add.hpp new file mode 100644 index 0000000..a48ade2 --- /dev/null +++ b/safe_numerics/tests/test_add.hpp @@ -0,0 +1,178 @@ +#ifndef TEST_ADD_HPP +#define TEST_ADD_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_cast.hpp" +#include "../include/safe_compare.hpp" + +#include "test.hpp" + +template +bool test_add( + V v1, + V v2, + const char *at1, + const char *at2, + const char *av1, + const char *av2 +){ + bool success; + + T1 t1; + try{ + t1 = boost::numeric::safe_cast(v1); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "constructed invalid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + } + else{ + if(! boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + && ! boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "failed to construct valid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + return true; + } + + T2 t2; + try{ + t2 = boost::numeric::safe_cast(v2); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "constructed invalid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(!boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + && !boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "failed to construct valid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + return true; + } + + V result; + try{ + result = t1 + t2; + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(result != v1 + v2){ + std::cout + << "failed to detect error in addition " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(boost::numeric::safe_compare::greater_than_equal( + boost::numeric::bits::value, + std::max(count_bits(v1),count_bits(v2)) + )){ + std::cout + << "erroneously detected error in addition " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + return true; // correct result +} + +template +struct add_result { + typedef typename boost::mpl::if_< + boost::mpl::or_< + boost::numeric::is_signed, + boost::numeric::is_signed + >, + boost::intmax_t, + boost::uintmax_t + >::type type; +}; + +#define TEST_IMPL(a, b, c, d) \ + rval &= test_add( \ + (static_cast::type>(a)), \ + (static_cast::type>(b)), \ + BOOST_PP_STRINGIZE(d), \ + BOOST_PP_STRINGIZE(c), \ + BOOST_PP_STRINGIZE(b), \ + BOOST_PP_STRINGIZE(a) \ + ); \ +/**/ + +#endif // TEST_ADD_HPP diff --git a/safe_numerics/tests/test_add1.cpp b/safe_numerics/tests/test_add1.cpp new file mode 100644 index 0000000..c670746 --- /dev/null +++ b/safe_numerics/tests/test_add1.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_add.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_add1(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_add2.cpp b/safe_numerics/tests/test_add2.cpp new file mode 100644 index 0000000..e35b3ce --- /dev/null +++ b/safe_numerics/tests/test_add2.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2012 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 "test_add.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + d \ + ) \ +/**/ + +bool test_add2(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} + diff --git a/safe_numerics/tests/test_add3.cpp b/safe_numerics/tests/test_add3.cpp new file mode 100644 index 0000000..95671ec --- /dev/null +++ b/safe_numerics/tests/test_add3.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2012 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 "test_add.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + c, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_add3(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} + diff --git a/safe_numerics/tests/test_conversion.cpp b/safe_numerics/tests/test_conversion.cpp new file mode 100644 index 0000000..f74bff4 --- /dev/null +++ b/safe_numerics/tests/test_conversion.cpp @@ -0,0 +1,180 @@ +// Copyright (c) 2012 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../include/safe_cast.hpp" +#include "../include/safe_integer.hpp" + +#define TYPES (8, ( \ + boost::int8_t, \ + boost::uint8_t, \ + boost::int16_t, \ + boost::uint16_t, \ + boost::int32_t, \ + boost::uint32_t, \ + boost::int64_t, \ + boost::uint64_t \ +)) + +#define VALUES (20, ( \ + 0x10, \ + 0x20, \ + 0x7f, \ + 0x80, \ + 0xff, \ + 0x1000, \ + 0x2000, \ + 0x7fff, \ + 0x8000, \ + 0xffff, \ + 0x10000000, \ + 0x20000000, \ + 0x7fffffff, \ + 0x80000000, \ + 0xffffffff, \ + 0x100000000000, \ + 0x200000000000, \ + 0x7fffffffffff, \ + 0x80000000ffff, \ + 0xffffffffffff \ +)) + +// test conversion +template +bool test_conversion(V v, const char *a1, const char *a2, const char *a3){ + bool success; + boost::numeric::safe t2; + /* test conversion constructor */ + try{ + t2 = v; + success = true; + } + catch(std::range_error e){ + success = false; + } + if(success){ + if(t2 > std::numeric_limits::max() + || t2 < std::numeric_limits::min()){ + std::cout + << "failed to detect error in construction " + << a1 << ' ' << a2 + << std::endl; + return false; + } + } + else{ + if(v <= std::numeric_limits::max() + && v >= std::numeric_limits::min()){ + std::cout + << "erroneasly detected error in construction " + << a1 << ' ' << a2 + << std::endl; + return false; + } + return true; // correctly detected error + } + + T1 t1; + try{ + //t1 = t2; + t1 = boost::numeric::safe_cast(t2); + success = true; + } + catch(std::range_error e){ + success = false; + } + if(success){ + if(t1 > std::numeric_limits::max() + || t1 < std::numeric_limits::min()){ + std::cout + << "failed to detect error in conversion " + << a1 << ' ' << a2 << ' ' << a3 + << std::endl; + return false; + } + } + else{ + if(t2 <= std::numeric_limits::max() + && t2 >= std::numeric_limits::min()){ + std::cout + << "erroneasly detected error in conversion " + << a1 << ' ' << a2 << ' ' << a3 + << std::endl; + return false; + } + return true; // correctly detected error + } + return true; // passed test +} + +template +struct test_value { + typedef typename boost::mpl::if_< + boost::is_signed, + boost::intmax_t, + boost::uintmax_t + >::type type; +}; + +#define TEST_CONVERSION(T1, T2, v) \ + test_conversion( \ + static_cast::type>(v), \ + BOOST_PP_STRINGIZE(T1), \ + BOOST_PP_STRINGIZE(T2), \ + BOOST_PP_STRINGIZE(v) \ + ); + +#define TEST(z, k, ij) \ + TEST_CONVERSION( \ + BOOST_PP_ARRAY_ELEM( \ + BOOST_PP_TUPLE_ELEM(2, 0, ij),\ + TYPES \ + ), \ + BOOST_PP_ARRAY_ELEM( \ + BOOST_PP_TUPLE_ELEM(2, 1, ij),\ + TYPES \ + ), \ + BOOST_PP_ARRAY_ELEM(k, VALUES) \ + ) + +#define EACH_VALUE(z, j, i) \ + BOOST_PP_REPEAT( \ + BOOST_PP_ARRAY_SIZE(VALUES), \ + TEST, \ + (i, j) \ + ) \ +/**/ + +#define EACH_TYPE1(z, i, x) \ + BOOST_PP_REPEAT( \ + BOOST_PP_ARRAY_SIZE(TYPES), \ + EACH_VALUE, \ + i \ + ) \ +/**/ + +int main(int argc, char *argv[]){ + BOOST_PP_REPEAT( + BOOST_PP_ARRAY_SIZE(TYPES), + EACH_TYPE1, + x + ) + /* + TEST(0, 0, (0, 1)); + TEST_CONVERSION(boost::uint8_t, boost::uint8_t, 0x80) + */ + return 0; +} diff --git a/safe_numerics/tests/test_divide.cpp b/safe_numerics/tests/test_divide.cpp new file mode 100644 index 0000000..316f666 --- /dev/null +++ b/safe_numerics/tests/test_divide.cpp @@ -0,0 +1,11 @@ +bool test_divide1(); +bool test_divide2(); +bool test_divide3(); + +int main(int argc, char * argv[]){ + bool result = true; + result = test_divide1(); + result &= test_divide2(); + result &= test_divide3(); + return ! result ; +} diff --git a/safe_numerics/tests/test_divide.hpp b/safe_numerics/tests/test_divide.hpp new file mode 100644 index 0000000..53a3c13 --- /dev/null +++ b/safe_numerics/tests/test_divide.hpp @@ -0,0 +1,178 @@ +#ifndef TEST_DIVIDE_HPP +#define TEST_DIVIDE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_cast.hpp" +#include "../include/safe_compare.hpp" + +#include "test.hpp" + +template +bool test_divide( + V v1, + V v2, + const char *at1, + const char *at2, + const char *av1, + const char *av2 +){ + bool success; + + T1 t1; + try{ + t1 = boost::numeric::safe_cast(v1); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "constructed invalid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + } + else{ + if(! boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + && ! boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "failed to construct valid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + return true; + } + + T2 t2; + try{ + t2 = boost::numeric::safe_cast(v2); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "constructed invalid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(!boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + && !boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "failed to construct valid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + return true; + } + + V result; + try{ + result = t1 / t2; + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(result != v1/v2){ + std::cout + << "failed to detect error in division " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(boost::numeric::safe_compare::greater_than_equal( + boost::numeric::bits::value, + std::max(count_bits(v1),count_bits(v2)) + )){ + std::cout + << "erroneously detected error in division " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + return true; // correct result +} + +template +struct divide_result { + typedef typename boost::mpl::if_< + boost::mpl::or_< + boost::numeric::is_signed, + boost::numeric::is_signed + >, + boost::intmax_t, + boost::uintmax_t + >::type type; +}; + +#define TEST_IMPL(a, b, c, d) \ + rval &= test_divide( \ + (static_cast::type>(a)), \ + (static_cast::type>(b)), \ + BOOST_PP_STRINGIZE(d), \ + BOOST_PP_STRINGIZE(c), \ + BOOST_PP_STRINGIZE(b), \ + BOOST_PP_STRINGIZE(a) \ + ); \ +/**/ + +#endif // TEST_DIVIDE_HPP \ No newline at end of file diff --git a/safe_numerics/tests/test_divide1.cpp b/safe_numerics/tests/test_divide1.cpp new file mode 100644 index 0000000..dfa58c2 --- /dev/null +++ b/safe_numerics/tests/test_divide1.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_divide.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_divide1(){ + bool rval = true; + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + return rval; +} diff --git a/safe_numerics/tests/test_divide2.cpp b/safe_numerics/tests/test_divide2.cpp new file mode 100644 index 0000000..e1fae7f --- /dev/null +++ b/safe_numerics/tests/test_divide2.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_divide.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + d \ + ) \ +/**/ + +bool test_divide2(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_divide3.cpp b/safe_numerics/tests/test_divide3.cpp new file mode 100644 index 0000000..253e66b --- /dev/null +++ b/safe_numerics/tests/test_divide3.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_divide.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + c, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_divide3(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_misc.cpp b/safe_numerics/tests/test_misc.cpp new file mode 100644 index 0000000..720e3b5 --- /dev/null +++ b/safe_numerics/tests/test_misc.cpp @@ -0,0 +1,7 @@ +#include +#include +#include +#include "../include/safe_integer.hpp" + +BOOST_STATIC_ASSERT(boost::is_integral::value); +BOOST_STATIC_ASSERT(boost::is_integral >::value); diff --git a/safe_numerics/tests/test_modulus.cpp b/safe_numerics/tests/test_modulus.cpp new file mode 100644 index 0000000..929afd3 --- /dev/null +++ b/safe_numerics/tests/test_modulus.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2012 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) + +bool test_modulus1(); +bool test_modulus2(); +bool test_modulus3(); + +int main(int argc, char * argv[]){ + bool result = true; + result = test_modulus1(); + result &= test_modulus2(); + result &= test_modulus3(); + return ! result ; +} diff --git a/safe_numerics/tests/test_modulus.hpp b/safe_numerics/tests/test_modulus.hpp new file mode 100644 index 0000000..33715bd --- /dev/null +++ b/safe_numerics/tests/test_modulus.hpp @@ -0,0 +1,178 @@ +#ifndef TEST_MODULUS_HPP +#define TEST_MODULUS_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_cast.hpp" +#include "../include/safe_compare.hpp" + +#include "test.hpp" + +template +bool test_modulus( + V v1, + V v2, + const char *at1, + const char *at2, + const char *av1, + const char *av2 +){ + bool success; + + T1 t1; + try{ + t1 = boost::numeric::safe_cast(v1); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "constructed invalid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + } + else{ + if(! boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + && ! boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "failed to construct valid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + return true; + } + + T2 t2; + try{ + t2 = boost::numeric::safe_cast(v2); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "constructed invalid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(!boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + && !boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "failed to construct valid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + return true; + } + + V result; + try{ + result = t1 % t2; + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(result != v1 % v2){ + std::cout + << "failed to detect error in modulus " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(boost::numeric::safe_compare::greater_than_equal( + boost::numeric::bits::value, + std::max(count_bits(v1),count_bits(v2)) + )){ + std::cout + << "erroneously detected error in modulus " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + return true; // correct result +} + +template +struct modulus_result { + typedef typename boost::mpl::if_< + boost::mpl::or_< + boost::numeric::is_signed, + boost::numeric::is_signed + >, + boost::intmax_t, + boost::uintmax_t + >::type type; +}; + +#define TEST_IMPL(a, b, c, d) \ + rval &= test_modulus( \ + (static_cast::type>(a)), \ + (static_cast::type>(b)), \ + BOOST_PP_STRINGIZE(d), \ + BOOST_PP_STRINGIZE(c), \ + BOOST_PP_STRINGIZE(b), \ + BOOST_PP_STRINGIZE(a) \ + ); \ +/**/ + +#endif // TEST_MODULUS_HPP diff --git a/safe_numerics/tests/test_modulus1.cpp b/safe_numerics/tests/test_modulus1.cpp new file mode 100644 index 0000000..93b5335 --- /dev/null +++ b/safe_numerics/tests/test_modulus1.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_modulus.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_modulus1(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_modulus2.cpp b/safe_numerics/tests/test_modulus2.cpp new file mode 100644 index 0000000..cbd7f7d --- /dev/null +++ b/safe_numerics/tests/test_modulus2.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_modulus.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + d \ + ) \ +/**/ + +bool test_modulus2(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_modulus3.cpp b/safe_numerics/tests/test_modulus3.cpp new file mode 100644 index 0000000..b411998 --- /dev/null +++ b/safe_numerics/tests/test_modulus3.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_modulus.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + c, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_modulus3(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_multiply.cpp b/safe_numerics/tests/test_multiply.cpp new file mode 100644 index 0000000..c219701 --- /dev/null +++ b/safe_numerics/tests/test_multiply.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2012 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) + +bool test_multiply1(); +bool test_multiply2(); +bool test_multiply3(); + +int main(int argc, char * argv[]){ + bool result = true; + result = test_multiply1(); + result &= test_multiply2(); + result &= test_multiply3(); + return ! result ; +} diff --git a/safe_numerics/tests/test_multiply.hpp b/safe_numerics/tests/test_multiply.hpp new file mode 100644 index 0000000..1c64912 --- /dev/null +++ b/safe_numerics/tests/test_multiply.hpp @@ -0,0 +1,174 @@ +#ifndef TEST_MULTIPLY_HPP +#define TEST_MULTIPLY_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_cast.hpp" +#include "../include/safe_compare.hpp" + +#include "test.hpp" + +template +bool test_multiply( + V v1, + V v2, + const char *at1, + const char *at2, + const char *av1, + const char *av2 +){ + bool success; + + T1 t1; + try{ + t1 = boost::numeric::safe_cast(v1); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "constructed invalid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + } + else{ + if(! boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + && ! boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "failed to construct valid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + return true; + } + + T2 t2; + try{ + t2 = boost::numeric::safe_cast(v2); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "constructed invalid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(! boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + && ! boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "failed to construct valid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + return true; + } + + V result; + try{ + result = t1 * t2; + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(result != v1 * v2){ + std::cout + << "failed to detect error in multiplication " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(64 >= count_bits(v1) + count_bits(v2)){ + std::cout + << "erroneously detected error in multiplication " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + return true; // correct result +} + +template +struct multiply_result { + typedef typename boost::mpl::if_< + boost::mpl::or_< + boost::numeric::is_signed, + boost::numeric::is_signed + >, + boost::intmax_t, + boost::uintmax_t + >::type type; +}; + +#define TEST_IMPL(a, b, c, d) \ + rval &= test_multiply( \ + (static_cast::type>(a)), \ + (static_cast::type>(b)), \ + BOOST_PP_STRINGIZE(d), \ + BOOST_PP_STRINGIZE(c), \ + BOOST_PP_STRINGIZE(b), \ + BOOST_PP_STRINGIZE(a) \ + ); \ +/**/ + +#endif // TEST_MODULUS_HPP diff --git a/safe_numerics/tests/test_multiply1.cpp b/safe_numerics/tests/test_multiply1.cpp new file mode 100644 index 0000000..97cc3c9 --- /dev/null +++ b/safe_numerics/tests/test_multiply1.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_multiply.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_multiply1(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_multiply2.cpp b/safe_numerics/tests/test_multiply2.cpp new file mode 100644 index 0000000..4a74d28 --- /dev/null +++ b/safe_numerics/tests/test_multiply2.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_multiply.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + d \ + ) \ +/**/ + +bool test_multiply2(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_multiply3.cpp b/safe_numerics/tests/test_multiply3.cpp new file mode 100644 index 0000000..db1a2ff --- /dev/null +++ b/safe_numerics/tests/test_multiply3.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_multiply.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + c, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_multiply3(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_numeric.cpp b/safe_numerics/tests/test_numeric.cpp new file mode 100644 index 0000000..68e287b --- /dev/null +++ b/safe_numerics/tests/test_numeric.cpp @@ -0,0 +1,230 @@ +// Copyright (c) 2012 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 "../include/numeric.hpp" + +#include +#include +#include +#include + +#include +#include +//#include + +BOOST_MPL_ASSERT(( boost::numeric::is_signed )); +BOOST_MPL_ASSERT_NOT(( boost::numeric::is_signed )); +BOOST_MPL_ASSERT_RELATION(8, ==, boost::numeric::bits::value); +BOOST_MPL_ASSERT_RELATION(16, ==, (boost::numeric::max_bits::value)); +BOOST_MPL_ASSERT_RELATION(16, ==, (boost::numeric::max_bits::value)); + +//////////////////////////////////////////////////////////// +// addition of various types of integers + +template +struct addition_display { + BOOST_MPL_ASSERT_RELATION(boost::numeric::bits::value, >=, B); +}; + +// note we have to break this into two separate macros to avoid +// having gcc flag a compile error +#define TEST_ADDITION1(T, U) \ + BOOST_MPL_ASSERT_RELATION( \ + (boost::integer_traits< \ + addition_result_type::type \ + >::const_max), \ + >=, \ + boost::integer_traits::const_max \ + + boost::integer_traits::const_max \ + ); \ + { \ + typedef boost::mpl::print< \ + addition_display< \ + T, \ + U, \ + addition_result_type::type, \ + addition_result_bits::value \ + > \ + >::type tdef; \ + } \ +/**/ +#define TEST_ADDITION2(T, U) \ + BOOST_MPL_ASSERT_RELATION( \ + (boost::integer_traits< \ + addition_result_type::type \ + >::const_min), \ + <=, \ + boost::integer_traits::const_min \ + + boost::integer_traits::const_min \ + ); \ + { \ + typedef boost::mpl::print< \ + addition_display< \ + T, \ + U, \ + addition_result_type::type, \ + addition_result_bits::value \ + > \ + >::type tdef; \ + } \ +/**/ + +void add(){ + using namespace boost::numeric; + TEST_ADDITION1(boost::int8_t, boost::int8_t) + TEST_ADDITION1(boost::int16_t, boost::int8_t) + TEST_ADDITION1(boost::uint8_t, boost::uint8_t) + TEST_ADDITION1(boost::uint16_t, boost::uint8_t) + TEST_ADDITION1(boost::uint16_t, boost::int8_t) + TEST_ADDITION1(boost::int16_t, boost::uint8_t) + + TEST_ADDITION2(boost::int8_t, boost::int8_t) + TEST_ADDITION2(boost::int16_t, boost::int8_t) + TEST_ADDITION2(boost::uint8_t, boost::uint8_t) + TEST_ADDITION2(boost::uint16_t, boost::uint8_t) + TEST_ADDITION2(boost::uint16_t, boost::int8_t) + TEST_ADDITION2(boost::int16_t, boost::uint8_t) +} + +//////////////////////////////////////////////////////////// +// subtraction of various types of integers + +template +struct subtraction_display {}; + +#if 1 +// note we have to break this into two separate macros to avoid +// having gcc flag a compile error +#define TEST_SUBTRACTION1(T, U) \ + BOOST_MPL_ASSERT_RELATION( \ + (boost::integer_traits< \ + subtraction_result_type::type \ + >::const_max), \ + >=, \ + boost::integer_traits::const_max \ + + boost::integer_traits::const_max \ + ); \ + { \ + typedef boost::mpl::print< \ + subtraction_display< \ + T, \ + U, \ + subtraction_result_type::type, \ + subtraction_result_bits::value \ + > \ + >::type tdef; \ + } \ +/**/ +#define TEST_SUBTRACTION2(T, U) \ + BOOST_MPL_ASSERT_RELATION( \ + (boost::integer_traits< \ + subtraction_result_type::type \ + >::const_min), \ + <=, \ + boost::integer_traits::const_min \ + + boost::integer_traits::const_min \ + ); \ + { \ + typedef boost::mpl::print< \ + subtraction_display< \ + T, \ + U, \ + subtraction_result_type::type, \ + subtraction_result_bits::value \ + > \ + >::type tdef; \ + } \ +/**/ + +void subtract(){ + using namespace boost::numeric; + TEST_SUBTRACTION1(boost::int8_t, boost::int8_t) + TEST_SUBTRACTION1(boost::int16_t, boost::int8_t) + TEST_SUBTRACTION1(boost::uint8_t, boost::uint8_t) + TEST_SUBTRACTION1(boost::uint16_t, boost::uint8_t) + TEST_SUBTRACTION1(boost::uint16_t, boost::int8_t) + TEST_SUBTRACTION1(boost::int16_t, boost::uint8_t) + + TEST_SUBTRACTION2(boost::int8_t, boost::int8_t) + TEST_SUBTRACTION2(boost::int16_t, boost::int8_t) + TEST_SUBTRACTION2(boost::uint8_t, boost::uint8_t) + TEST_SUBTRACTION2(boost::uint16_t, boost::uint8_t) + TEST_SUBTRACTION2(boost::uint16_t, boost::int8_t) + TEST_SUBTRACTION2(boost::int16_t, boost::uint8_t) +} + +#endif + +//////////////////////////////////////////////////////////// +// multiplication of various types of integers + +// note - this test is not really correct. What is really needed +// is compile time integer interval arithmetic - which we don't +// have. Addition is trivial - see above - but multiplication +// is more challanging. So, for now, this test fails to detect +// implementation errors in calculation of ranges of the result +// of multiplications + +template +struct multiply_display {}; + +#define TEST_MULTIPLICATION1(T, U) \ + BOOST_MPL_ASSERT_RELATION( \ + (boost::integer_traits< \ + multiply_result_type::type \ + >::const_max), \ + >=, \ + boost::integer_traits::const_max \ + * boost::integer_traits::const_max \ + ); \ + { \ + typedef boost::mpl::print< \ + multiply_display< \ + T, \ + U, \ + multiply_result_type::type, \ + multiply_result_bits::value \ + > \ + >::type tdef; \ + } \ +/**/ +#define TEST_MULTIPLICATION2(T, U) \ + BOOST_MPL_ASSERT_RELATION( \ + (boost::integer_traits< \ + multiply_result_type::type \ + >::const_min), \ + <=, \ + boost::integer_traits::const_min \ + + boost::integer_traits::const_min \ + ); \ + { \ + typedef boost::mpl::print< \ + multiply_display< \ + T, \ + U, \ + multiply_result_type::type, \ + multiply_result_bits::value \ + > \ + >::type tdef; \ + } \ +/**/ + +void multiply(){ + using namespace boost::numeric; + TEST_MULTIPLICATION1(boost::int8_t, boost::int8_t) + TEST_MULTIPLICATION1(boost::int16_t, boost::int8_t) + TEST_MULTIPLICATION1(boost::uint8_t, boost::uint8_t) + TEST_MULTIPLICATION1(boost::uint16_t, boost::uint8_t) + TEST_MULTIPLICATION1(boost::uint16_t, boost::int8_t) + TEST_MULTIPLICATION1(boost::int16_t, boost::uint8_t) + + TEST_MULTIPLICATION2(boost::int8_t, boost::int8_t) + TEST_MULTIPLICATION2(boost::int16_t, boost::int8_t) + TEST_MULTIPLICATION2(boost::uint8_t, boost::uint8_t) + TEST_MULTIPLICATION2(boost::uint16_t, boost::uint8_t) + TEST_MULTIPLICATION2(boost::uint16_t, boost::int8_t) + TEST_MULTIPLICATION2(boost::int16_t, boost::uint8_t) +} diff --git a/safe_numerics/tests/test_subtract.cpp b/safe_numerics/tests/test_subtract.cpp new file mode 100644 index 0000000..bf52a50 --- /dev/null +++ b/safe_numerics/tests/test_subtract.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2012 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) + +bool test_subtract1(); +bool test_subtract2(); +bool test_subtract3(); + +int main(int argc, char * argv[]){ + bool result = true; + result = test_subtract1(); + result &= test_subtract2(); + result &= test_subtract3(); + return ! result ; +} diff --git a/safe_numerics/tests/test_subtract.hpp b/safe_numerics/tests/test_subtract.hpp new file mode 100644 index 0000000..be0be05 --- /dev/null +++ b/safe_numerics/tests/test_subtract.hpp @@ -0,0 +1,178 @@ +#ifndef TEST_SUBTRACT_HPP +#define TEST_SUBTRACT_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2012 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 +#include +#include +#include + +#include "../include/safe_integer.hpp" +#include "../include/safe_cast.hpp" +#include "../include/safe_compare.hpp" + +#include "test.hpp" + +template +bool test_subtract( + V v1, + V v2, + const char *at1, + const char *at2, + const char *av1, + const char *av2 +){ + bool success; + + T1 t1; + try{ + t1 = boost::numeric::safe_cast(v1); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "constructed invalid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + } + else{ + if(! boost::numeric::safe_compare::greater_than( + v1, + std::numeric_limits::max() + ) + && ! boost::numeric::safe_compare::less_than( + v1, + std::numeric_limits::min() + ) + ){ + std::cout + << "failed to construct valid value " + << at1 << ' ' << av1 + << std::endl; + return false; + } + return true; + } + + T2 t2; + try{ + t2 = boost::numeric::safe_cast(v2); + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + || boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "constructed invalid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(!boost::numeric::safe_compare::greater_than( + v2, + std::numeric_limits::max() + ) + && !boost::numeric::safe_compare::less_than( + v2, + std::numeric_limits::min() + )){ + std::cout + << "failed to construct valid value " + << at2 << ' ' << av2 + << std::endl; + return false; + } + return true; + } + + V result; + try{ + result = t1 - t2; + success = true; + } + catch(std::range_error){ + success = false; + } + if(success){ + if(result != v1 - v2){ + std::cout + << "failed to detect error in subtraction " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + else{ + if(boost::numeric::safe_compare::greater_than_equal( + boost::numeric::bits::value, + std::max(count_bits(v1),count_bits(v2)) + )){ + std::cout + << "erroneously detected error in subtraction " + << at1 << ' ' << at2 << ' ' << av1 << ' ' << av2 + << std::endl; + return false; + } + } + return true; // correct result +} + +template +struct subtract_result { + typedef typename boost::mpl::if_< + boost::mpl::or_< + boost::numeric::is_signed, + boost::numeric::is_signed + >, + boost::intmax_t, + boost::uintmax_t + >::type type; +}; + +#define TEST_IMPL(a, b, c, d) \ + rval &= test_subtract( \ + (static_cast::type>(a)), \ + (static_cast::type>(b)), \ + BOOST_PP_STRINGIZE(d), \ + BOOST_PP_STRINGIZE(c), \ + BOOST_PP_STRINGIZE(b), \ + BOOST_PP_STRINGIZE(a) \ + ); \ +/**/ + +#endif // TEST_SUBTRACT_HPP diff --git a/safe_numerics/tests/test_subtract1.cpp b/safe_numerics/tests/test_subtract1.cpp new file mode 100644 index 0000000..d42c8b0 --- /dev/null +++ b/safe_numerics/tests/test_subtract1.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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 "test_subtract.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_subtract1(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} diff --git a/safe_numerics/tests/test_subtract2.cpp b/safe_numerics/tests/test_subtract2.cpp new file mode 100644 index 0000000..eee4d1d --- /dev/null +++ b/safe_numerics/tests/test_subtract2.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2012 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 "test_subtract.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + boost::numeric::safe, \ + d \ + ) \ +/**/ + +bool test_subtract2(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} + diff --git a/safe_numerics/tests/test_subtract3.cpp b/safe_numerics/tests/test_subtract3.cpp new file mode 100644 index 0000000..a9330a5 --- /dev/null +++ b/safe_numerics/tests/test_subtract3.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2012 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 "test_subtract.hpp" + +#define TESTX(a, b, c, d) \ + TEST_IMPL( \ + a, \ + b, \ + c, \ + boost::numeric::safe \ + ) \ +/**/ + +bool test_subtract3(){ + bool rval = true; + #pragma message("0") + EACH_TYPE1(boost::int8_t); + #pragma message("1") + EACH_TYPE1(boost::uint8_t); + #pragma message("2") + EACH_TYPE1(boost::int16_t); + #pragma message("3") + EACH_TYPE1(boost::uint16_t); + #pragma message("4") + EACH_TYPE1(boost::int32_t); + #pragma message("5") + EACH_TYPE1(boost::uint32_t); + #pragma message("6") + EACH_TYPE1(boost::int64_t); + #pragma message("7") + EACH_TYPE1(boost::uint64_t); + return rval; +} + diff --git a/safe_numerics/tests/vcide/example_test.vcproj b/safe_numerics/tests/vcide/example_test.vcproj new file mode 100644 index 0000000..3eec192 --- /dev/null +++ b/safe_numerics/tests/vcide/example_test.vcproj @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/safe_numerics.sln b/safe_numerics/tests/vcide/safe_numerics.sln new file mode 100644 index 0000000..f530794 --- /dev/null +++ b/safe_numerics/tests/vcide/safe_numerics.sln @@ -0,0 +1,99 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_add", "test_add.vcproj", "{4393B586-DBB1-40B9-AE5D-A1D9E459ACD2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_conversion", "test_conversion.vcproj", "{0E0D4BCF-507C-413C-9B8C-E8C972209F8B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_divide", "test_divide.vcproj", "{21DF917A-7E09-4F06-B599-0CD7E231F06E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_modulus", "test_modulus.vcproj", "{3DE806F0-9703-4EF8-A57F-07DC922074D2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_multiply", "test_multiply.vcproj", "{AF3D6B8E-EFF2-41C5-8FCE-9060BCD63974}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_subtract", "test_subtract.vcproj", "{B914598A-A377-4DFB-A3E7-DA1D0F3C4E37}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{06D85C87-845D-4C48-BC6F-2D2C5127AA81}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library Headers", "Library Headers", "{98484F4D-80EE-431E-8B13-6DC167B628E1}" + ProjectSection(SolutionItems) = preProject + ..\..\include\numeric.hpp = ..\..\include\numeric.hpp + ..\..\include\overflow.hpp = ..\..\include\overflow.hpp + ..\..\include\safe_cast.hpp = ..\..\include\safe_cast.hpp + ..\..\include\safe_compare.hpp = ..\..\include\safe_compare.hpp + ..\..\include\safe_integer.hpp = ..\..\include\safe_integer.hpp + ..\..\include\safe_range.hpp = ..\..\include\safe_range.hpp + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "concept", "concept", "{95FF13B8-F33D-4F01-8E98-628666082703}" + ProjectSection(SolutionItems) = preProject + ..\..\include\concept\numeric.hpp = ..\..\include\concept\numeric.hpp + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_numeric", "test_numeric.vcproj", "{239CF7B4-DB8F-43D0-BC2B-D6FDFC0D4EDF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Example", "Example", "{64AAA74D-6F56-4C20-9287-989918B52012}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_test", "example_test.vcproj", "{3E51E3C4-2F74-4470-8DE9-8B79D1F30FA8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_safe_range", "test_safe_range.vcproj", "{6DBF6AE0-095C-4508-9420-FB2CD1B8BA3D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4393B586-DBB1-40B9-AE5D-A1D9E459ACD2}.Debug|Win32.ActiveCfg = Debug|Win32 + {4393B586-DBB1-40B9-AE5D-A1D9E459ACD2}.Debug|Win32.Build.0 = Debug|Win32 + {4393B586-DBB1-40B9-AE5D-A1D9E459ACD2}.Release|Win32.ActiveCfg = Release|Win32 + {4393B586-DBB1-40B9-AE5D-A1D9E459ACD2}.Release|Win32.Build.0 = Release|Win32 + {0E0D4BCF-507C-413C-9B8C-E8C972209F8B}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E0D4BCF-507C-413C-9B8C-E8C972209F8B}.Debug|Win32.Build.0 = Debug|Win32 + {0E0D4BCF-507C-413C-9B8C-E8C972209F8B}.Release|Win32.ActiveCfg = Release|Win32 + {0E0D4BCF-507C-413C-9B8C-E8C972209F8B}.Release|Win32.Build.0 = Release|Win32 + {21DF917A-7E09-4F06-B599-0CD7E231F06E}.Debug|Win32.ActiveCfg = Debug|Win32 + {21DF917A-7E09-4F06-B599-0CD7E231F06E}.Debug|Win32.Build.0 = Debug|Win32 + {21DF917A-7E09-4F06-B599-0CD7E231F06E}.Release|Win32.ActiveCfg = Release|Win32 + {21DF917A-7E09-4F06-B599-0CD7E231F06E}.Release|Win32.Build.0 = Release|Win32 + {3DE806F0-9703-4EF8-A57F-07DC922074D2}.Debug|Win32.ActiveCfg = Debug|Win32 + {3DE806F0-9703-4EF8-A57F-07DC922074D2}.Debug|Win32.Build.0 = Debug|Win32 + {3DE806F0-9703-4EF8-A57F-07DC922074D2}.Release|Win32.ActiveCfg = Release|Win32 + {3DE806F0-9703-4EF8-A57F-07DC922074D2}.Release|Win32.Build.0 = Release|Win32 + {AF3D6B8E-EFF2-41C5-8FCE-9060BCD63974}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF3D6B8E-EFF2-41C5-8FCE-9060BCD63974}.Debug|Win32.Build.0 = Debug|Win32 + {AF3D6B8E-EFF2-41C5-8FCE-9060BCD63974}.Release|Win32.ActiveCfg = Release|Win32 + {AF3D6B8E-EFF2-41C5-8FCE-9060BCD63974}.Release|Win32.Build.0 = Release|Win32 + {B914598A-A377-4DFB-A3E7-DA1D0F3C4E37}.Debug|Win32.ActiveCfg = Debug|Win32 + {B914598A-A377-4DFB-A3E7-DA1D0F3C4E37}.Debug|Win32.Build.0 = Debug|Win32 + {B914598A-A377-4DFB-A3E7-DA1D0F3C4E37}.Release|Win32.ActiveCfg = Release|Win32 + {B914598A-A377-4DFB-A3E7-DA1D0F3C4E37}.Release|Win32.Build.0 = Release|Win32 + {239CF7B4-DB8F-43D0-BC2B-D6FDFC0D4EDF}.Debug|Win32.ActiveCfg = Debug|Win32 + {239CF7B4-DB8F-43D0-BC2B-D6FDFC0D4EDF}.Debug|Win32.Build.0 = Debug|Win32 + {239CF7B4-DB8F-43D0-BC2B-D6FDFC0D4EDF}.Release|Win32.ActiveCfg = Release|Win32 + {239CF7B4-DB8F-43D0-BC2B-D6FDFC0D4EDF}.Release|Win32.Build.0 = Release|Win32 + {3E51E3C4-2F74-4470-8DE9-8B79D1F30FA8}.Debug|Win32.ActiveCfg = Debug|Win32 + {3E51E3C4-2F74-4470-8DE9-8B79D1F30FA8}.Debug|Win32.Build.0 = Debug|Win32 + {3E51E3C4-2F74-4470-8DE9-8B79D1F30FA8}.Release|Win32.ActiveCfg = Release|Win32 + {3E51E3C4-2F74-4470-8DE9-8B79D1F30FA8}.Release|Win32.Build.0 = Release|Win32 + {6DBF6AE0-095C-4508-9420-FB2CD1B8BA3D}.Debug|Win32.ActiveCfg = Debug|Win32 + {6DBF6AE0-095C-4508-9420-FB2CD1B8BA3D}.Debug|Win32.Build.0 = Debug|Win32 + {6DBF6AE0-095C-4508-9420-FB2CD1B8BA3D}.Release|Win32.ActiveCfg = Release|Win32 + {6DBF6AE0-095C-4508-9420-FB2CD1B8BA3D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {0E0D4BCF-507C-413C-9B8C-E8C972209F8B} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {21DF917A-7E09-4F06-B599-0CD7E231F06E} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {3DE806F0-9703-4EF8-A57F-07DC922074D2} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {AF3D6B8E-EFF2-41C5-8FCE-9060BCD63974} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {B914598A-A377-4DFB-A3E7-DA1D0F3C4E37} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {4393B586-DBB1-40B9-AE5D-A1D9E459ACD2} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {239CF7B4-DB8F-43D0-BC2B-D6FDFC0D4EDF} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {6DBF6AE0-095C-4508-9420-FB2CD1B8BA3D} = {06D85C87-845D-4C48-BC6F-2D2C5127AA81} + {95FF13B8-F33D-4F01-8E98-628666082703} = {98484F4D-80EE-431E-8B13-6DC167B628E1} + {3E51E3C4-2F74-4470-8DE9-8B79D1F30FA8} = {64AAA74D-6F56-4C20-9287-989918B52012} + EndGlobalSection +EndGlobal diff --git a/safe_numerics/tests/vcide/test_add.vcproj b/safe_numerics/tests/vcide/test_add.vcproj new file mode 100644 index 0000000..52f84ee --- /dev/null +++ b/safe_numerics/tests/vcide/test_add.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_comparison.vcproj b/safe_numerics/tests/vcide/test_comparison.vcproj new file mode 100644 index 0000000..5a6288f --- /dev/null +++ b/safe_numerics/tests/vcide/test_comparison.vcproj @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_conversion.vcproj b/safe_numerics/tests/vcide/test_conversion.vcproj new file mode 100644 index 0000000..8243a02 --- /dev/null +++ b/safe_numerics/tests/vcide/test_conversion.vcproj @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_divide.vcproj b/safe_numerics/tests/vcide/test_divide.vcproj new file mode 100644 index 0000000..0c5e179 --- /dev/null +++ b/safe_numerics/tests/vcide/test_divide.vcproj @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_modulus.vcproj b/safe_numerics/tests/vcide/test_modulus.vcproj new file mode 100644 index 0000000..c6eea2e --- /dev/null +++ b/safe_numerics/tests/vcide/test_modulus.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_multiply.vcproj b/safe_numerics/tests/vcide/test_multiply.vcproj new file mode 100644 index 0000000..c2273e3 --- /dev/null +++ b/safe_numerics/tests/vcide/test_multiply.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_numeric.vcproj b/safe_numerics/tests/vcide/test_numeric.vcproj new file mode 100644 index 0000000..81acfac --- /dev/null +++ b/safe_numerics/tests/vcide/test_numeric.vcproj @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/safe_numerics/tests/vcide/test_subtract.vcproj b/safe_numerics/tests/vcide/test_subtract.vcproj new file mode 100644 index 0000000..d761bc9 --- /dev/null +++ b/safe_numerics/tests/vcide/test_subtract.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +