diff --git a/doc/boostbook/accu/accu.pdf b/doc/boostbook/accu/accu.pdf index 3755efd..891968f 100644 Binary files a/doc/boostbook/accu/accu.pdf and b/doc/boostbook/accu/accu.pdf differ diff --git a/doc/boostbook/accu/accu_logo.png b/doc/boostbook/accu/accu_logo.png new file mode 100644 index 0000000..45039df Binary files /dev/null and b/doc/boostbook/accu/accu_logo.png differ diff --git a/doc/boostbook/accu/db2fo.xsl b/doc/boostbook/accu/db2fo.xsl index 7885597..93c494b 100644 --- a/doc/boostbook/accu/db2fo.xsl +++ b/doc/boostbook/accu/db2fo.xsl @@ -12,10 +12,10 @@ blue +--> 0pt 1 @@ -123,6 +124,7 @@ General default options go here: 2 left +0 http://svn.boost.org/svn/boost/trunk/doc/src/images/ http://svn.boost.org/svn/boost/trunk/doc/src/images/callouts/ diff --git a/doc/boostbook/accu/db2html.xsl b/doc/boostbook/accu/db2html.xsl index 7a5b041..89db3e1 100644 --- a/doc/boostbook/accu/db2html.xsl +++ b/doc/boostbook/accu/db2html.xsl @@ -14,7 +14,7 @@ Override boost book implemenation of header.navigation with our own
- Library Documentation Index + Library Documentation Index

Safe Numerics

diff --git a/doc/boostbook/accu/makehtml.sh b/doc/boostbook/accu/makehtml.sh index 8ec715a..2514a44 100755 --- a/doc/boostbook/accu/makehtml.sh +++ b/doc/boostbook/accu/makehtml.sh @@ -2,7 +2,9 @@ if test x = x$BOOST_ROOT then echo BOOST_ROOT not set fi +mkdir html +xsltproc --xinclude --nonet bb2db.xsl accu.xml > accudocbook4.xml xsltproc --nonet db2html.xsl accudocbook4.xml -cp ../pre-boost.jpg ../html -cp $BOOST_ROOT/doc/src/boostbook.css ../html -cp -R $BOOST_ROOT/doc/html/images ../html +cp accu_logo.png html +cp $BOOST_ROOT/doc/src/boostbook.css html +cp -R $BOOST_ROOT/doc/html/images html diff --git a/doc/boostbook/acknowledgements.xml b/doc/boostbook/acknowledgements.xml new file mode 100644 index 0000000..1d6fa47 --- /dev/null +++ b/doc/boostbook/acknowledgements.xml @@ -0,0 +1,50 @@ + + +
+ Acknowledgements + + This library would never have been created without inspiration, + collaboration and constructive criticism from multiple sources. + + + + David LaBlanc + + + This library is inspired by David LeBlanc's SafeInt + Library . I found this library very well done in every way + and useful in my embedded systems work. This motivated me to take to + the "next level". + + + + + Andrzej + Krzemienski + + + Andrzej Commented and reviewed the library as it was + originally posted on the Boost Library Incubator. + The the consequent back and forth motivated me to invest more effort + in developing documentation and examples to justify the utility, + indeed the necessity, for this library. He also noted many errors in + code, documentation, and tests. Without his interested and effort, I + do not believe the library would have progressed beyond it's initial + stages. + + + + + Boost + + + As always, the Boost Developer's mailing list has been the + source of many useful observations from potential users and + constructive criticism from very knowledgeable developers. + + + +
diff --git a/doc/boostbook/eliminate_runtime_penalty.xml b/doc/boostbook/eliminate_runtime_penalty.xml index dc1b85f..b9c10e7 100644 --- a/doc/boostbook/eliminate_runtime_penalty.xml +++ b/doc/boostbook/eliminate_runtime_penalty.xml @@ -73,16 +73,15 @@ safe; The standard C++ type promotion rules are consistent with the - default "native" type - promotion policy. Up until now, we've focused on detecting when - this happens and invoking an interrupt or other kind of error - handler. + default native + type promotion policy. Up until now, we've focused on detecting when this + happens and invoking an interrupt or other kind of error handler. But now we look at another option. Using the "automatic" type - promotion policy, we can change the rules of C++ arithmetic for - safe types to something like the following: + linkend="safe_numerics.promotion_policy.models.automatic">automatic + type promotion policy, we can change the rules of C++ arithmetic for safe + types to something like the following: @@ -110,17 +109,17 @@ long z = (long)x + (long)y; // can never overflow One could do this by editing his code manually, but such a task would be tedious, error prone, and leave the resulting code hard to read and verify. Using the "automatic" - type promotion policy will achieve the equivalent result - without these problems + linkend="safe_numerics.promotion_policy.models.automatic">automatic + type promotion policy will achieve the equivalent result without + these problems Since the result type is guaranteed to hold the result, there is no need to check for errors - they can't happen !!! The usage of "trap_exception" - exception policy enforces this guarantee + linkend="safe_numerics.exception_policy.models.trap_exception">trap_exception + exception policy enforces this guarantee @@ -150,8 +149,8 @@ long z = (long)x + (long)y; // can never overflow Depending on the application, it should be rare to generate error checking code, and even more rare to actually invoke it. Any such instances are detected by the "trap_exception" - exception policy . + linkend="safe_numerics.exception_policies.trap_exception">trap_exception + exception policy. This small example illustrates how to use automatic type promotion to eliminate all runtime penalty. @@ -171,14 +170,16 @@ z = <long>[-4294967296,4294967294] = 2147483649 display the underlying type and its range as well as current value. Note that: - automatic type promotion policy has rendered the result of the - some of two integers as a long - type. + the automatic + type promotion policy has rendered the result of the some of two + integers as a long type. - our program compiles without error - even when using the - trap_exception exception policy + our program compiles without error - even when using the trap_exception + exception policy @@ -204,9 +205,9 @@ z = <long>[-4294967296,4294967294] = 2147483649 a correct result. But since we trust no one, and since the program could change and the expressions be replaced with other ones, we'll still use the "trap_exception" - exception policy to verify at compile time that what we - "know" to be true is in fact true. + linkend="safe_numerics.exception_policies.trap_exception">trap_exception + exception policy to verify at compile time that what we "know" to be true + is in fact true. @@ -259,38 +260,42 @@ z = <signed char>[-24,82] = 77 - As before, we define a safe_t to reflect our view - of legal values for this program. This uses automatic type promotion - policy as well as trapping exception policy to enforce elimination - of runtime penalties. + As before, we define a type safe_t to reflect our + view of legal values for this program. This uses automatic + type promotion policy as well as trap_exception + exception policy to enforce elimination of runtime penalties. - The function f accepts only safe_t types so there is no need - to check the input values. This performs the functionality of - programming by - contract with no runtime cost. + The function f accepts only arguments of type + safe_t so there is no need to check the input values. + This performs the functionality of programming by contract with no + runtime cost. - In addition we define input_safe_t to be used + In addition, we define input_safe_t to be used when reading variables from the program console. Clearly, these can only be checked at runtime so they use the throw_exception policy. When variables are read from the console they are checked for legal - values. We need no hoc code to do this, as these types are + values. We need no ad hoc code to do this, as these types are guaranteed to contain legal values and will throw an exception when this guarantee is violated. In other words, we automatically get checking of input variables with no additional programming. - On calling of the function f with variables of type - input_safe_t are converted to variables of safe_t. In this - particular example, it can be determined at compile time that - construction of an instance of a safe_t from an input_safe_t can - never fail. Hence, no try/catch block is necessary. The usage of the - trap_exception policy for safe_t types would cause a compile time - error. + On calling of the function f, arguments of type + input_safe_t are converted to values of type + safe_t . In this particular example, it can be + determined at compile time that construction of an instance of a + safe_t from an input_safe_t can never + fail. Hence, no try/catch block is necessary. The usage + of the trap_exception policy for safe_t + types would cause a compile time error. Here is the output from the program when values 12 and 32 are input from the console: diff --git a/doc/boostbook/faq.xml b/doc/boostbook/faq.xml index f5e5405..1a585f4 100644 --- a/doc/boostbook/faq.xml +++ b/doc/boostbook/faq.xml @@ -16,9 +16,9 @@ This surprised me when it was first raised. But some of the feedback I've received makes me thing that it's a widely held view. - The best answer is to consider the cases in the section Tutorials and Motivating - Examples. + Examples section of the library documentation. @@ -33,9 +33,7 @@ counterparts should result in a program that will compile and run as expected. In some cases compile time errors will occur and adjustments to the source code will be required. Typically these will result in - code which is more correct. See drop-in - replacement. + code which is more correct. @@ -61,7 +59,7 @@ similar libraries. Maybe a better word might have been "correct" but that would raise similar concerns. I'm not inclined to change this. I've tried to make it clear in the documentation what the problem that - the library addressed is + the library addressed is. @@ -75,10 +73,10 @@ Actually, I believe that this can/should be applied to any type T which satisfies the type requirement "Numeric" type as defined in the documentation. So there should be specializations - safe<float> et. al. and eventually safe<fixed_decimal> - etc. But the current version of the library only addresses integer - types. Hopefully the library will evolve to match the promise implied - by its name. + safe<float> and related types as well as new types + like safe<fixed_decimal> etc. But the current + version of the library only addresses integer types. Hopefully the + library will evolve to match the promise implied by its name. @@ -113,22 +111,23 @@ - Why do you specialize numeric_limits for "safe" types? Do you - need it? + Why do you specialize numeric_limits for "safe" + types? Do you need it? - safe<T> behaves like a "number" just as int does. It has - max, min, etc Any code which uses numeric limits to test a type T - should works with safe<T>. safe<T> is a drop-in - replacement for T so it has to implement all the operations. + safe<T> behaves like a "number" just as int + does. It has max, min, etc Any code which uses numeric limits to test + a type T should works with safe<T>. + safe<T> is a drop-in replacement for T + so it has to implement all the operations. According to C/C++ standards, unsigned integers cannot overflow - - they are modular integers which "warp around". Yet the safe numerics + - they are modular integers which "wrap around". Yet the safe numerics library detects and traps this behavior as errors. Why is that? @@ -143,9 +142,10 @@ modulus for such an integer would vary depending upon the machine architecture. For these reasons, in the context of this library, an unsigned integer is considered to a representation of a subset of - integers. Note that this decision is consistent with INT30-C, “Ensure - that unsigned integer operations do not wrap” in the CERT C Secure - Coding Standard Seacord. + integers. Note that this decision is consistent with + INT30-C, “Ensure that unsigned integer operations + do not wrap” in the CERT C Secure Coding Standard + Seacord. @@ -156,7 +156,7 @@ The original version of the library used C++11. Feedback from - CPPCon, Boost Library + CPPCon, Boost Library Incubator and Boost developer's mailing list convinced me that I had to address the issue of run-time penalty much more seriously. I resolved to eliminate or minimize it. This led to more elaborate @@ -238,7 +238,7 @@ typedef long int32_t; This example illustrates how this library, implemented with C++14 can be useful in the development of correct code for programs - written in C. + written in C. diff --git a/doc/boostbook/notes.xml b/doc/boostbook/notes.xml index ed61ec2..5c8a288 100644 --- a/doc/boostbook/notes.xml +++ b/doc/boostbook/notes.xml @@ -6,7 +6,7 @@ This library is a re-implementation of the facilities provided by David LeBlanc's SafeInt - Library using C++14 and the Boost + Library using C++14 and the Boost Libraries. 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. @@ -23,8 +23,8 @@ - It didn't use Boost conventions - for naming. + It didn't use Boost + conventions for naming. @@ -41,7 +41,7 @@ This version addresses these issues. It exploits Boost facilities such as template + url="http://www.boost.org">Boost facilities such as template metaprogramming to reduce the number of lines of source code to approximately 4700. It exploits the Boost Preprocessor Library to generate exhaustive tests. diff --git a/doc/boostbook/safe_introduction.xml b/doc/boostbook/safe_introduction.xml index a24e56e..05d1756 100644 --- a/doc/boostbook/safe_introduction.xml +++ b/doc/boostbook/safe_introduction.xml @@ -32,8 +32,8 @@ 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 will not be - arithmetically correct. The following example illustrates this - problem. + arithmetically correct. The following example illustrates just one example + where this causes problems. int f(int x, int y){ // this returns an invalid result for some legal values of x and y ! @@ -41,13 +41,14 @@ } - It is incumbent up the C/C++ programmer to guarantee that this + It is incumbent upon the C/C++ programmer to guarantee that this behavior does not result in incorrect or unexpected operation of the program. There are no language facilities which implement such a guarantee. A programmer needs to examine each expression individually to - know that his program will not return an invalid result.There are a number - of ways to do this. See INT32-C seems to recommend - the following approach: + know that his program will not return an invalid result. There are a + number of ways to do this. In the above instance, + INT32-C seems to recommend the following + approach: int f(int x, int y){ if (((y > 0) && (x > (INT_MAX - y))) @@ -74,12 +75,13 @@ This example addresses only the problem of undefined/erroneous behavior related to overflow of the addition operation as applied to the type int. Similar problems occur with other built-in integer - types such as unsigned, long, etc. And it also applies to other operations - such as subtraction, multiplication etc. . C/C++ often automatically and - silently converts some integer types to others in the course of - implementing binary operations and similar problems occur in this case as - well. Since the problems and their solution are similar, We'll confine the - current discussion to just this example. + types such as unsigned, long, etc. And it also + applies to other operations such as subtraction, multiplication etc. . + C/C++ often automatically and silently converts some integer types to + others in the course of implementing binary operations and similar + problems occur in this case as well. Since the problems and their solution + are similar, We'll confine the current discussion to just this one + example.
@@ -132,16 +134,17 @@ safe<int> f(safe<int> x, safe<int> y){
How It Works - The library implements special versions of int, unsigned, etc. named - safe<int>, safe<unsigned int> etc. - These behave exactly like the underlying types except that expressions using these types fulfill - the above guarantee. These types are meant to be "drop-in" replacements - for the built-in types they are meant to replace. So things which are - legal - such as assigning an signed to unsigned - value are not trapped at compile time - as they are legal C/C++ code. - Instead, they are checked at runtime to trap the case where this (legal) - operation would lead to an arithmetically incorrect result. + The library implements special versions of int, + unsigned, etc. named safe<int>, + safe<unsigned int> etc. These behave exactly like the + underlying types except that expressions + using these types fulfill the above guarantee. These types are meant to be + "drop-in" replacements for the built-in types they are meant to replace. + So things which are legal - such as assignment of a signed to + unsigned value - are not trapped at compile time as they are + legal C/C++ code. Instead, they are checked at runtime to trap the case + where this (legal) operation would lead to an arithmetically incorrect + result. Note that the library addresses arithmetical errors generated by straightforward C/C++ expressions. Some of these arithmetic errors are @@ -212,9 +215,9 @@ safe<int> f(safe<int> x, safe<int> y){ Enforce of other program requirements using ranged integer - types. The library includes types safe_range(Min, Max) - and safe_literal(N). These types can be used to improve - program correctness and performance. + types. The library includes the types safe_range(Min, + Max) and safe_literal(N). These types can be + used to improve program correctness and performance.
@@ -252,7 +255,7 @@ safe<int> f(safe<int> x, safe<int> y){ Enable_if - The safe numerics library is delivered with an exhaustive + The Safe Numerics library is delivered with an exhaustive suite of test programs. Users who choose to run this test suite will also need to install the Boost.Preprocessor library.
diff --git a/doc/html/acknowledgements.html b/doc/html/acknowledgements.html index d337fbd..cf7a935 100644 --- a/doc/html/acknowledgements.html +++ b/doc/html/acknowledgements.html @@ -29,22 +29,19 @@ and useful in my embedded systems work. This motivated me to take to the "next level".

Andrzej - Krzemieński
+ Krzemienski

Andrzej Commented and reviewed the library as it was - originally posted on the Boost - Library Incubator. The the consequent back and forth - motivated me to invest more effort in developing documentation and - examples to justify the utility, indeed the necessity, for this - library. He also noted many errors in code, documentation, and - tests. Without his interested and effort, I do not believe the - library would have progressed beyond it's initial stages.

-
Boost
+ originally posted on the Boost Library Incubator. + The the consequent back and forth motivated me to invest more effort + in developing documentation and examples to justify the utility, + indeed the necessity, for this library. He also noted many errors in + code, documentation, and tests. Without his interested and effort, I + do not believe the library would have progressed beyond it's initial + stages.

+
Boost

As always, the Boost Developer's mailing list has been the source of many useful observations from potential users and - constructive criticism from very knowledgeable developers. Boost - also supplies a widely accepted list of standards and requirements - for quality software. Finally, the Boost infrastructure for testing, - documentation is close to indispensable.

+ constructive criticism from very knowledgeable developers.

diff --git a/doc/html/checked_integer_arithmetic.html b/doc/html/checked_integer_arithmetic.html index 41f3b16..728f631 100644 --- a/doc/html/checked_integer_arithmetic.html +++ b/doc/html/checked_integer_arithmetic.html @@ -21,18 +21,18 @@

Checked Integer Arithmetic

-Synopsis

+Synopsis
// safe casting on primitive types
 template<class R, class T>
 constexpr checked_result<R>
@@ -93,29 +93,29 @@
 
 

-Description

+Description

Perform binary operations on arithmetic types. Return either a valid result or an error code. Under no circumstances should an incorrect result be returned.

-Type requirements

+Type requirements

All template parameters of the functions must model Integer type requirements.

-Complexity

+Complexity

Each function performs one and only one arithmetic operation

-Header

+Header

#include "checked.hpp"

-Example of use

+Example of use

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

#include "checked.hpp"
 
@@ -124,7 +124,7 @@
 
 

-Notes

+Notes

Some compilers have command line switches (e.g. -ftrapv) which enable special behavior such erroneous integer operations are detected at run time. The library has been implemented in such a way that these @@ -134,7 +134,7 @@

-See Also

+See Also

checked_result<typename R>

diff --git a/doc/html/checked_result.html b/doc/html/checked_result.html index 5d46036..f7db9d2 100644 --- a/doc/html/checked_result.html +++ b/doc/html/checked_result.html @@ -21,17 +21,17 @@

checked_result<typename R>

-Description

+Description

checked_result is a wrapper class designed to hold result of some operation. It can hold either the result of the operation or information on why the operation failed to produce a valid result. Note that this type @@ -40,7 +40,7 @@

-Template Parameters

+Template Parameters

The sole template parameter is the return type of some operation.

@@ -66,7 +66,7 @@

-Notation

+Notation
@@ -103,7 +103,7 @@

-Valid Expressions

+Valid Expressions

All expressions are constexpr.

@@ -173,12 +173,12 @@

-Header

+Header

#include "checked_result.hpp"

-Example of use

+Example of use
#include "checked_result.hpp"
 
 template<class R>
@@ -198,7 +198,7 @@
 
 

-See Also

+See Also

ExceptionPolicy

diff --git a/doc/html/concepts.html b/doc/html/concepts.html index bb2ee45..04ee5f7 100644 --- a/doc/html/concepts.html +++ b/doc/html/concepts.html @@ -6,7 +6,7 @@ - + diff --git a/doc/html/eliminate_runtime_penalty/1.html b/doc/html/eliminate_runtime_penalty/1.html index d15a25c..4a91bdc 100644 --- a/doc/html/eliminate_runtime_penalty/1.html +++ b/doc/html/eliminate_runtime_penalty/1.html @@ -32,9 +32,14 @@

So the result of the sum of two integer types may result in another integer type. If the values are large, the result can exceed the size that - the resulting integer type can hold. This is what we call "overflow". - Standard C/C++ does just truncates the result to fit into the result type - - which sometimes will make the result arithmetically incorrect.

+ the resulting integer type can hold. This is what we call "overflow". The + C/C++ standard characterises this as undefined behavior and leaves to + compiler implementors the decision as to how such a situation will be + handled. Usually, this means just truncating the result to fit into the + result type - which sometimes will make the result arithmetically + incorrect. However, depending on the compiler, compile time switch + settings, the such case may result in some sort of run time + exception.

The complete signature for a safe integer type is:

template <
     class T,                  // underlying integer type
@@ -44,18 +49,16 @@
 safe;
 

The standard C++ type promotion rules are consistent with the - default "native" type - promotion policy. Up until now, we've focused on detecting when - this happens and invoking an interrupt or other kind of error - handler.

-

But now we look at another option. Using the "automatic" type - promotion policy, we can change the rules of C++ arithmetic for - safe types to something like the following:

+ default native + type promotion policy. Up until now, we've focused on detecting when this + happens and invoking an interrupt or other kind of error handler.

+

But now we look at another option. Using the automatic + type promotion policy, we can change the rules of C++ arithmetic for safe + types to something like the following:

  • for any C++ numeric type, we know from - std::numeric::limits what the maximum and minimum - values that a variable can be - this defines a closed - interval.

  • + std::numeric_limits what the maximum and minimum values + that a variable can be - this defines a closed interval.

  • For any binary operation on these types, we can calculate the interval of the result at compile time.

  • @@ -69,14 +72,14 @@ long z = (long)x + (long)y; // can never overflow

One could do this by editing his code manually, but such a task would be tedious, error prone, and leave the resulting code - hard to read and verify. Using the "automatic" - type promotion policy will achieve the equivalent result - without these problems

+ hard to read and verify. Using the automatic + type promotion policy will achieve the equivalent result without + these problems

  • Since the result type is guaranteed to hold the result, there is no need to check for errors - they can't happen !!! The usage of - "trap_exception" - exception policy enforces this guarantee

  • + trap_exception + exception policy enforces this guarantee

  • Since there can be no errors, there is no need for try/catch blocks.

  • The only runtime error checking we need to do is when safe @@ -96,8 +99,8 @@ this case, and only this case, is runtime error checking code generated. Depending on the application, it should be rare to generate error checking code, and even more rare to actually invoke it. Any such instances are - detected by the "trap_exception" - exception policy .

    + detected by the trap_exception + exception policy.

    This small example illustrates how to use automatic type promotion to eliminate all runtime penalty.

    #include <iostream>
    @@ -134,11 +137,11 @@ z = <long>[-4294967296,4294967294] = 2147483649
         display the underlying type and its range as well as current value. Note
         that:

      -
    • automatic type promotion policy has rendered the result of the - some of two integers as a long - type.

    • -
    • our program compiles without error - even when using the - trap_exception exception policy

    • +
    • the automatic + type promotion policy has rendered the result of the some of two + integers as a long type.

    • +
    • our program compiles without error - even when using the trap_exception + exception policy

    • We do not need to use try/catch idiom to handle arithmetic errors - we will have none.

    • We only needed to change two lines of code to achieve our diff --git a/doc/html/eliminate_runtime_penalty/2.html b/doc/html/eliminate_runtime_penalty/2.html index 8c4d92f..1a2d210 100644 --- a/doc/html/eliminate_runtime_penalty/2.html +++ b/doc/html/eliminate_runtime_penalty/2.html @@ -24,12 +24,12 @@

      Instead of relying on automatic type promotion, we can just create our own types in such a way that we know they won't overflow. In the example below, we presume we know that the values we want to work with - fall in the closed range of -24,82. So we "know" the program will always - result in a correct result. But since we trust no one, and since the - program could change and the expressions be replaced with other ones, - we'll still use the "trap_exception" - exception policy to verify at compile time that what we - "know" to be true is in fact true.

      + fall in the range [-24,82]. So we "know" the program will always result in + a correct result. But since we trust no one, and since the program could + change and the expressions be replaced with other ones, we'll still use + the trap_exception + exception policy to verify at compile time that what we "know" to be true + is in fact true.

      #include <iostream>
       
       #include "../include/safe_range.hpp"
      @@ -40,10 +40,10 @@
       
       using namespace boost::numeric; // for safe_literal
       
      -// create a type for holding small integers.  We "know" that C++ type
      -// promotion rules will work such that operations on this type
      -// will never overflow. If change the program to break this, the
      -// usage of the trap_exception promotion policy will prevent compilation.
      +// create a type for holding small integers.  We "know" that C++
      +// type promotion rules will work such that addition will never
      +// overflow. If we change the program to break this, the usage
      +// of the trap_exception promotion policy will prevent compilation.
       using safe_t = safe_signed_range<
           -24,
           82,
      @@ -53,8 +53,13 @@
       
       int main(int argc, const char * argv[]){
           std::cout << "example 83:\n";
      -    const safe_signed_literal<2> x;
      -    const safe_signed_literal<2> y;
      +    // the following would result in a compile time error
      +    // since the sum of x and y wouldn't be in the legal
      +    // range for z.
      +    // const safe_signed_literal<20> x;
      +    const safe_signed_literal<10> x;    // no problem
      +    const safe_signed_literal<67> y;
      +
           const safe_t z = x + y;
           std::cout << "x = " << safe_format(x) << std::endl;
           std::cout << "y = " << safe_format(y) << std::endl;
      @@ -62,40 +67,28 @@
           return 0;
       }
       
      -

      which produces the following output.

      -
      example 83:
      -x = <signed char>[-24,82] = 2
      -y = <signed char>[-24,82] = 2
      -z = (x + y) = <int>[-48,164] = 4
      -(x - y) = <int>[-106,106] = 0
      -<int>[-48,164] = 4
        -
      • In this example, standard C++ type promotion rules are used. - These promote operands to int before invoking the addition operation. - So addition operation itself won't overflow. The result of addition is - another unnamed safe type guaranteed to be able to hold the some of - any pair of safe types. In this example the result is a safe type - based on the C++ built-in type of short.

      • -
      • So when we try to assign the result to z we could get an error. - This is because our custom safe_t cannot be guaranteed to - hold the some of all possible pairs of safe_t instances. - We fix the by using an "auto" for the sum.

      • -
      • We now have a problem when we try to initialize our - safe_t variable with an initial literal value. This - operation could overflow at runtime. To our disappointment, our - attempt to fix the problem by using constexpr fails. The - fix for this is to use safe_literal to initialize safe - types. safe_literal is a special safe type which wraps a constant - defined at compile time. It cannot be initialized, assigned to, or - changed. Subject to this restriction, it can participate in safe - arithmetic operations.

      • +
      • safe_signed_range defines a type + which is limited to the indicated range. Out of range assignments + will be detected at compile time if possible (as in this case) or at + run time if necessary.

      • +
      • safe_literal defines a constant with a specific + value. Defining constants in this way enables the library to + correctly anticipate the range of the results of arithmetic + expressions.

      • +
      • The usage of "trap exception" will mean that any assignment to + z which could be outside the legal range will result in a compile + time error.

      • +
      • So if this program compiles, it's guaranteed to return a valid + result.

      -

      We've used simple expressions in this illustration. But since binary - operations on safe types result in other safe types, expressions can be - made arbitrarily elaborate - just as they can be with intrinsic integer - types. That is, safe integer types are drop in replacements for intrinsic - integer types. We are guaranteed never to produce an incorrect result - regardless of how elaborate the expression might be.

      +

      This program produces the following run time + output.

      +
      example 83:
      +x = <signed char>[10,10] = 10
      +y = <signed char>[67,67] = 67
      +z = <signed char>[-24,82] = 77
      +
  • diff --git a/doc/html/eliminate_runtime_penalty/3.html b/doc/html/eliminate_runtime_penalty/3.html index 5b68695..5f07f19 100644 --- a/doc/html/eliminate_runtime_penalty/3.html +++ b/doc/html/eliminate_runtime_penalty/3.html @@ -7,7 +7,7 @@ - +
    @@ -77,29 +77,30 @@ }
      -
    • As before, we define a safe_t to reflect our view - of legal values for this program. This uses automatic type promotion - policy as well as trapping exception policy to enforce elimination - of runtime penalties.

    • -
    • The function f accepts only safe_t types so there is no need - to check the input values. This performs the functionality of - programming by - contract with no runtime cost.

    • -
    • In addition we define input_safe_t to be used +

    • As before, we define a type safe_t to reflect our + view of legal values for this program. This uses automatic + type promotion policy as well as trap_exception + exception policy to enforce elimination of runtime penalties.

    • +
    • The function f accepts only arguments of type + safe_t so there is no need to check the input values. + This performs the functionality of programming by contract with no + runtime cost.

    • +
    • In addition, we define input_safe_t to be used when reading variables from the program console. Clearly, these can only be checked at runtime so they use the throw_exception policy. When variables are read from the console they are checked for legal - values. We need no hoc code to do this, as these types are + values. We need no ad hoc code to do this, as these types are guaranteed to contain legal values and will throw an exception when this guarantee is violated. In other words, we automatically get checking of input variables with no additional programming.

    • -
    • On calling of the function f with variables of type - input_safe_t are converted to variables of safe_t. In this - particular example, it can be determined at compile time that - construction of an instance of a safe_t from an input_safe_t can - never fail. Hence, no try/catch block is necessary. The usage of the - trap_exception policy for safe_t types would cause a compile time - error.

    • +
    • On calling of the function f, arguments of type + input_safe_t are converted to values of type + safe_t . In this particular example, it can be + determined at compile time that construction of an instance of a + safe_t from an input_safe_t can never + fail. Hence, no try/catch block is necessary. The usage + of the trap_exception policy for safe_t + types would cause a compile time error.

    Here is the output from the program when values 12 and 32 are input from the console:

    diff --git a/doc/html/exception_policies/ignore.html b/doc/html/exception_policies/ignore.html index 2354fdd..b40b1f2 100644 --- a/doc/html/exception_policies/ignore.html +++ b/doc/html/exception_policies/ignore.html @@ -22,7 +22,7 @@ ignore_exception
    -Description
    +Description

    This exception policy can be used to just ignore conditions which generate incorrect arithmetic results and continue processing. Programs using this policy along with the native promotion policy @@ -30,19 +30,19 @@

    -Model of
    +Model of

    ExceptionPolicy

    -Header
    +Header

    #include <boost/safe_numerics/exception_policy.hpp>

    -Example of use
    +Example of use
    safe<int, native, ignore_exception> st(4);
    diff --git a/doc/html/exception_policies/no_exception_support.html b/doc/html/exception_policies/no_exception_support.html index b238fd4..21385d6 100644 --- a/doc/html/exception_policies/no_exception_support.html +++ b/doc/html/exception_policies/no_exception_support.html @@ -22,7 +22,7 @@ no_exception_support<O, U = O, R =O, D = O>
    -Description
    +Description

    This exception policy can be used in an environment where one cannot or does not want to use exceptions.

    Parameters are pointers to static functions which are invoked for @@ -33,7 +33,7 @@

    -Template Parameters
    +Template Parameters

    Function objects to be invoked are specified for each error condition are specified via template parameters.

    @@ -79,19 +79,19 @@
    -Model of
    +Model of

    ExceptionPolicy

    -Header
    +Header

    #include <boost/safe_numerics/exception_policy.hpp>

    -Example of use
    +Example of use

    [A code fragment involving the type.]

    void overflow(const char * msg);
     void underflow(const char * msg);
    diff --git a/doc/html/exception_policies/throw_exception.html b/doc/html/exception_policies/throw_exception.html
    index 947fc67..18cd0bd 100644
    --- a/doc/html/exception_policies/throw_exception.html
    +++ b/doc/html/exception_policies/throw_exception.html
    @@ -29,19 +29,19 @@
     
     
    -Model of
    +Model of

    ExceptionPolicy

    -Header
    +Header

    #include <boost/safe_numerics/exception_policies.hpp>

    -Example of use
    +Example of use

    This example is somewhat contrived as throw_exception is the default for safe types. Hence it usually is not necessarily to request it explicitly.

    diff --git a/doc/html/exception_policies/trap_exception.html b/doc/html/exception_policies/trap_exception.html index b92dead..1cf81ad 100644 --- a/doc/html/exception_policies/trap_exception.html +++ b/doc/html/exception_policies/trap_exception.html @@ -22,7 +22,7 @@ trap_exception
    -Description
    +Description

    This exception policy will trap at compile time any operation COULD result in a runtime exception. It can be used in an environment which can tolerate @@ -31,19 +31,19 @@

    -Model of
    +Model of

    ExceptionPolicy

    -Header
    +Header

    #include <boost/safe_numerics/exception_policy.hpp>

    -Example of use
    +Example of use

    The following

    #include "../../include/safe_integer.hpp"
     #include "../../include/automatic.hpp"
    diff --git a/doc/html/exception_policy.html b/doc/html/exception_policy.html
    index c7f09ca..ef9104b 100644
    --- a/doc/html/exception_policy.html
    +++ b/doc/html/exception_policy.html
    @@ -21,15 +21,15 @@
     

    ExceptionPolicy<EP>

    -Description

    +Description

    The exception policy specifies what is to occur when a safe operation cannot return a valid arithmetic result. A type is an ExceptionPolicy if it has functions for handling exceptional events that @@ -37,7 +37,7 @@

    -Notation

    +Notation
    @@ -59,7 +59,7 @@

    -Valid Expressions

    +Valid Expressions

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

    @@ -114,14 +114,14 @@

    -Header

    +Header

    #include <safe_numerics/include/concepts/exception_policy.hpp>

    -Models

    +Models

    The library header <safe_numerics/include/exception_policies.hpp> contains a number of pre-made exception policies:

    This enum holds the information regarding a failed operation.

    -Notation

    +Notation
    @@ -69,7 +69,7 @@

    -Valid Expressions

    +Valid Expressions
    @@ -102,20 +102,20 @@

    -dispatch<EP>(const exception_type & e, const char * +dispatch<EP>(const exception_type & e, const char * msg)

    This function is used to invoke the exception handling policy for a particular exception_type.

    -Synopsis
    +Synopsis
    template<class EP>
     constexpr void
     dispatch<EP>(const exception_type & e, const char * msg);
    -Example of use
    +Example of use
    #include "exception_policy.hpp"
     
     dispatch(overflow_error, "operation resulted in overflow");
    @@ -123,7 +123,7 @@

    -See Also

    +See Also

    ExceptionPolicy

    diff --git a/doc/html/index.html b/doc/html/index.html index 20304bf..af2fd31 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -22,7 +22,7 @@
    @@ -33,7 +33,7 @@
    Problem
    Solution
    -
    Implementation
    +
    How It Works
    Additional Features
    Requirements
    Scope
    @@ -55,7 +55,7 @@
    Using safe_range
    Mixing Approaches
    -
    Notes
    +
    Background
    Type Requirements
    Numeric<T>
    diff --git a/doc/html/integer.html b/doc/html/integer.html index 1112d98..6fa5dd9 100644 --- a/doc/html/integer.html +++ b/doc/html/integer.html @@ -21,16 +21,16 @@

    Integer<T>

    -Description

    +Description

    A type is fulfills the requirements of an Integer if it has the properties of a integer.

    More specifically, a type T is Integer if there exists @@ -47,12 +47,12 @@

    -Refinement of

    +Refinement of

    Numeric

    -Notation

    +Notation
    @@ -72,11 +72,11 @@

    -Valid Expressions

    +Valid Expressions

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

    -

    Table 4. General

    +

    Table 4. General

    @@ -167,13 +167,13 @@

    -Header

    +Header

    #include <safe_numerics/include/concepts/integer.hpp>

    -Models

    +Models

    int, safe<int>, safe_unsigned_range<0, 11>, etc.

    diff --git a/doc/html/interval.html b/doc/html/interval.html index 785e2a3..b9a80c3 100644 --- a/doc/html/interval.html +++ b/doc/html/interval.html @@ -21,28 +21,28 @@

    interval<typename R>

    -Description

    +Description

    A closed arithmetic interval represented by a pair of elements of type R.

    -Template Parameters

    +Template Parameters

    R must model the type requirements Numeric

    -Notation

    +Notation
    @@ -82,7 +82,7 @@

    -Associated Types

    +Associated Types
    @@ -97,7 +97,7 @@

    -Valid Expressions

    +Valid Expressions

    Note that all expressions are constexpr .

    @@ -231,12 +231,12 @@

    -Header

    +Header

    #include "interval.hpp"

    -Example of use

    +Example of use
    #include <iostream>
     #include <cstdint>
     #include <cassert>
    diff --git a/doc/html/introduction.html b/doc/html/introduction.html
    index 79bbfe8..2a28e4d 100644
    --- a/doc/html/introduction.html
    +++ b/doc/html/introduction.html
    @@ -23,7 +23,7 @@
     
    Problem
    Solution
    -
    Implementation
    +
    How It Works
    Additional Features
    Requirements
    Scope
    @@ -44,20 +44,21 @@ 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 will not be - arithmetically correct. The following example illustrates this - problem.

    + arithmetically correct. The following example illustrates just one example + where this causes problems.

    int f(int x, int y){
         // this returns an invalid result for some legal values of x and y !
         return x + y;
     }
     
    -

    It is incumbent up the C/C++ programmer to guarantee that this +

    It is incumbent upon the C/C++ programmer to guarantee that this behavior does not result in incorrect or unexpected operation of the program. There are no language facilities which implement such a - guarantee. A programmer needs to each expression individually to know that - his program will not return an invalid result.There are a number of ways - to do this. See [INT32-C] seems to recommend the - following approach:

    + guarantee. A programmer needs to examine each expression individually to + know that his program will not return an invalid result. There are a + number of ways to do this. In the above instance, + [INT32-C] seems to recommend the following + approach:

    int f(int x, int y){
       if (((y > 0) && (x > (INT_MAX - y))) 
       || ((y < 0) && (x < (INT_MIN - y)))) {
    @@ -80,12 +81,13 @@
     

    This example addresses only the problem of undefined/erroneous behavior related to overflow of the addition operation as applied to the type int. Similar problems occur with other built-in integer - types such as unsigned, long, etc. And it also applies to other operations - such as subtraction, multiplication etc. . C/C++ often automatically and - silently converts some integer types to others in the course of - implementing binary operations and similar problems occur in this case as - well. Since the problems and their solution are similar, We'll confine the - current discussion to just this example.

    + types such as unsigned, long, etc. And it also + applies to other operations such as subtraction, multiplication etc. . + C/C++ often automatically and silently converts some integer types to + others in the course of implementing binary operations and similar + problems occur in this case as well. Since the problems and their solution + are similar, We'll confine the current discussion to just this one + example.

    @@ -128,16 +130,18 @@

    -Implementation

    -

    The library implements special versions of int, unsigned, etc. named - safe<int>, safe<unsigned int> etc. - These behave exactly like the underlying types except that expressions using these types fulfill - the above guarantee. These types are meant to be "drop-in" replacements - for the built-in types they are meant to replace. So things which are - legal - such as assigning an signed to unsigned - value are not trapped at compile time - as they are legal C/C++ code. - Instead, they are checked at runtime to trap the case where this (legal) - operation would lead to an arithmetically incorrect result.

    +How It Works
    +

    The library implements special versions of int, + unsigned, etc. named safe<int>, + safe<unsigned int> etc. These behave exactly like the + underlying types except that expressions + using these types fulfill the above guarantee. These types are meant to be + "drop-in" replacements for the built-in types they are meant to replace. + So things which are legal - such as assignment of a signed to + unsigned value - are not trapped at compile time as they are + legal C/C++ code. Instead, they are checked at runtime to trap the case + where this (legal) operation would lead to an arithmetically incorrect + result.

    Note that the library addresses arithmetical errors generated by straightforward C/C++ expressions. Some of these arithmetic errors are defined as conforming to the C/C++ standards while others are not. So @@ -187,9 +191,9 @@

  • Enforce of other program requirements using ranged integer - types. The library includes types safe_range(Min, Max) and - safe_literal(N). These types can be used to improve program - correctness and performance.

  • + types. The library includes the types safe_range(Min, + Max) and safe_literal(N). These types can be + used to improve program correctness and performance.

    @@ -207,7 +211,7 @@
  • Tribool

  • Enable_if

  • -

    The safe numerics library is delivered with an exhaustive +

    The Safe Numerics library is delivered with an exhaustive suite of test programs. Users who choose to run this test suite will also need to install the Boost.Preprocessor library.

    diff --git a/doc/html/notes.html b/doc/html/notes.html index 33116bd..605936d 100644 --- a/doc/html/notes.html +++ b/doc/html/notes.html @@ -1,7 +1,7 @@ -Notes +Background @@ -19,10 +19,10 @@

    -Notes

    +Background

    This library is a re-implementation of the facilities provided by David LeBlanc's SafeInt - Library using C++14 and the Boost + Library using C++14 and the Boost Libraries. 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.

    @@ -31,13 +31,13 @@ understand, modify and maintain.

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

  • -
  • It didn't use Boost conventions - for naming.

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

  • It required porting to different compilers.

  • It had a very long license associated with it.

  • I could find no test suite for the library.

  • -

    This version addresses these issues. It exploits Boost facilities such as template +

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

    diff --git a/doc/html/numeric.html b/doc/html/numeric.html index e4b1960..e97758f 100644 --- a/doc/html/numeric.html +++ b/doc/html/numeric.html @@ -22,11 +22,11 @@ Numeric<T>

    @@ -45,7 +45,7 @@

    -Notation

    +Notation
    @@ -73,7 +73,7 @@

    -Associated Types

    +Associated Types
    @@ -90,13 +90,13 @@

    -Valid Expressions

    +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 1. General

    +

    Table 1. General

    @@ -134,7 +134,7 @@


    -

    Table 2. Unary Operators

    +

    Table 2. Unary Operators

    @@ -181,7 +181,7 @@

    -

    Table 3. Binary Operators

    +

    Table 3. Binary Operators

    @@ -282,13 +282,13 @@

    -Header

    +Header

    #include <safe_numerics/include/concepts/numeric.hpp>

    -Models

    +Models

    int, float, safe_signed_integer<int>, safe_signed_range<int>, etc.

    diff --git a/doc/html/pending_issues.html b/doc/html/pending_issues.html index 7eb35bd..70aa21c 100644 --- a/doc/html/pending_issues.html +++ b/doc/html/pending_issues.html @@ -32,7 +32,7 @@ converted to the specified integer type. In other words, strtoi already contains some of the functionality that safe<int> provides.

    -
  • Although care was taking to make the library portable, it's +

  • Although care has been taken to make the library portable, it's likely that at least some parts of the implementation - particularly checked arithmetic - depend upon two's complement representation of integers. Hence the library is probably not diff --git a/doc/html/promotion_policies/automatic.html b/doc/html/promotion_policies/automatic.html index 08fe261..1437e95 100644 --- a/doc/html/promotion_policies/automatic.html +++ b/doc/html/promotion_policies/automatic.html @@ -22,24 +22,24 @@ automatic

    -Description
    +Description

    This type contains the functions to return a type with sufficient capacity to hold the result of a given arithmetic operation.

    -Model of
    +Model of

    PromotionPolicy

    -Header
    +Header

    #include <boost/safe_numerics/automatic.hpp>

    -Example of use
    +Example of use

    The following example illustrates the automatic type being passed as a template parameter for the type safe<int>.

    diff --git a/doc/html/promotion_policies/cpp.html b/doc/html/promotion_policies/cpp.html index 8babf41..11b2855 100644 --- a/doc/html/promotion_policies/cpp.html +++ b/doc/html/promotion_policies/cpp.html @@ -22,7 +22,7 @@ cpp<int C, int S, int I, int L, int LL>
    -Description
    +Description

    This policy is used to promote safe types in arithmetic expressions according the standard rules in the C++ standard. But rather than using the native C++ standard types supported by the compiler, it uses types @@ -37,7 +37,7 @@

    -Template Parameters
    +Template Parameters
  • @@ -80,18 +80,18 @@
    -Model of
    +Model of

    PromotionPolicy

    -Header
    +Header

    #include <boost/safe_numerics/cpp.hpp>

    -Example of Use
    +Example of Use

    Consider the following problem. One is developing software which uses a very small microprocessor and a very limited C compiler. The chip is so small, you can't print anything from the code, log, debug or diff --git a/doc/html/promotion_policies/native.html b/doc/html/promotion_policies/native.html index 8ad4fcb..3bcdb9d 100644 --- a/doc/html/promotion_policies/native.html +++ b/doc/html/promotion_policies/native.html @@ -22,7 +22,7 @@ native

    -Description
    +Description

    This type contains the functions to return a safe type corresponding to the C++ type resulting for a given arithmetic operation.

    Usage of this policy with safe types will produce the exact same @@ -33,7 +33,7 @@

    -Model of
    +Model of

    PromotionPolicy

    As an example of how this works consider C++ rules from section 5 of the standard - "usual arithmetic conversions".

    @@ -52,14 +52,14 @@
    -Header
    +Header

    #include <boost/safe_numerics/include/native.hpp>

    -Example of use
    +Example of use

    The following example illustrates the native type being passed as a template parameter for the type safe<int>. This example is slightly contrived in that safe<int> @@ -97,7 +97,7 @@

    -Notes
    +Notes

    See Chapter 5, Expressions, C++ Standard

    diff --git a/doc/html/promotion_policy.html b/doc/html/promotion_policy.html index 49f1f1e..201e6f0 100644 --- a/doc/html/promotion_policy.html +++ b/doc/html/promotion_policy.html @@ -21,15 +21,15 @@

    PromotionPolicy<PP>

    -Description

    +Description

    In C++, arithmetic operations result in types which may or may not be the same as the constituent types. A promotion policy determines the type of the result of an arithmetic operation. For example, in the @@ -44,7 +44,7 @@

    -Notation

    +Notation
    @@ -69,7 +69,7 @@

    -Valid Expressions

    +Valid Expressions

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

    @@ -123,14 +123,14 @@

    -Header

    +Header

    #include <safe_numerics/include/concepts/promotion_policy.hpp>

    -Models

    +Models

    The library contains a number of pre-made promotion policies:

    + The best answer is to consider the examples in the Tutorials and Motivating + Examples section of the library documentation.

    @@ -93,12 +93,11 @@ counterparts should result in a program that will compile and run as expected. In some cases compile time errors will occur and adjustments to the source code will be required. Typically these will result in - code which is more correct. See drop-in - replacement.

    + code which is more correct.

    @@ -109,7 +108,7 @@ @@ -120,11 +119,11 @@ similar libraries. Maybe a better word might have been "correct" but that would raise similar concerns. I'm not inclined to change this. I've tried to make it clear in the documentation what the problem that - the library addressed is

    + the library addressed is.

    @@ -134,14 +133,14 @@ + safe<float> and related types as well as new types + like safe<fixed_decimal> etc. But the current + version of the library only addresses integer types. Hopefully the + library will evolve to match the promise implied by its name.

    @@ -156,7 +155,7 @@ - + - + @@ -202,20 +202,21 @@ modulus for such an integer would vary depending upon the machine architecture. For these reasons, in the context of this library, an unsigned integer is considered to a representation of a subset of - integers. Note that this decision is consistent with INT30-C, “Ensure - that unsigned integer operations do not wrap” in the CERT C Secure - Coding Standard [Seacord].

    + integers. Note that this decision is consistent with + [INT30-C], “Ensure that unsigned integer operations + do not wrap” in the CERT C Secure Coding Standard + [Seacord].

    @@ -288,7 +289,7 @@

    This example illustrates how this library, implemented with C++14 can be useful in the development of correct code for programs - written in C.

    + written in C.

    diff --git a/doc/html/safe.html b/doc/html/safe.html index 36335d8..cc59c50 100644 --- a/doc/html/safe.html +++ b/doc/html/safe.html @@ -21,25 +21,25 @@

    safe<T, PP, EP>

    -Description

    +Description

    A safe<T, PP , EP> can be used anywhere a type T can be used. Any expression which uses this type is guaranteed to return an arithmetically correct value or trap in some way.

    -Notation

    +Notation
    -

    1.

    +

    1.

    Is this really necessary? If I'm writing the program with the requisite care and competence, problems noted in the introduction will @@ -77,12 +77,12 @@

    This surprised me when it was first raised. But some of the feedback I've received makes me thing that it's a widely held view. - The best answer is to consider the cases in the section Tutorials and Motivating - Examples.

    -

    2.

    +

    2.

    Can safe types be used as drop-in replacement for built-in types?

    -

    3.

    +

    3.

    Why is Boost.Convert not used?

    -

    4.

    +

    4.

    Why is the library named "safe ..." rather than something like "checked ..." ?

    -

    5.

    +

    5.

    Given that the library is called "numerics" why is floating point arithmetic not addressed?

    Actually, I believe that this can/should be applied to any type T which satisfies the type requirement "Numeric" type as defined in the documentation. So there should be specializations - safe<float> et. al. and eventually safe<fixed_decimal> - etc. But the current version of the library only addresses integer - types. Hopefully the library will evolve to match the promise implied - by its name.

    -

    6.

    +

    6.

    Isn't putting a defensive check just before any potential undefined behavior is often considered a bad practice?

    -

    7.

    +

    7.

    It looks like the implementation presumes two's complement arithmetic at the hardware level. So this library is not portable - @@ -170,24 +169,25 @@

    -

    8.

    +

    8.

    Why do you specialize numeric_limits for "safe" types? Do you - need it?

    Why do you specialize numeric_limits for "safe" + types? Do you need it?

    safe<T> behaves like a "number" just as int does. It has - max, min, etc Any code which uses numeric limits to test a type T - should works with safe<T>. safe<T> is a drop-in - replacement for T so it has to implement all the operations.

    safe<T> behaves like a "number" just as int + does. It has max, min, etc Any code which uses numeric limits to test + a type T should works with safe<T>. + safe<T> is a drop-in replacement for T + so it has to implement all the operations.

    -

    9.

    +

    9.

    According to C/C++ standards, unsigned integers cannot overflow - - they are modular integers which "warp around". Yet the safe numerics + - they are modular integers which "wrap around". Yet the safe numerics library detects and traps this behavior as errors. Why is that?

    -

    10.

    +

    10.

    Why does the library require C++14?

    The original version of the library used C++11. Feedback from - CPPCon, Boost Library + CPPCon, Boost Library Incubator and Boost developer's mailing list convinced me that I had to address the issue of run-time penalty much more seriously. I resolved to eliminate or minimize it. This led to more elaborate @@ -232,7 +233,7 @@

    -

    11.

    +

    11.

    This is a C++ library - yet you refer to C/C++. Which is it?

    @@ -58,7 +58,7 @@

    -Associated Types

    +Associated Types
    @@ -80,7 +80,7 @@

    -Template Parameters

    +Template Parameters
    @@ -116,13 +116,13 @@

    -Model of

    +Model of

    Integer

    SafeNumeric

    -Valid Expressions

    +Valid Expressions

    Implements all expressions and only those expressions defined by the SafeNumeric type requirements. This, the result type of such an expression will be another @@ -131,13 +131,13 @@

    -Header

    +Header

    #include <boost/safe_numerics/safe_integer.hpp>

    -Examples of use

    +Examples of use

    The most common usage would be safe<T> which uses the default promotion and exception policies. This type is meant to be a "drop-in" replacement of the intrinsic integer types. That is, expressions involving @@ -203,7 +203,7 @@

    -Guarantee correct behavior at compile time.
    +Guarantee correct behavior at compile time.

    In some instance catching an error at run time is not sufficient. We want to be sure that the program can never fail. To achieve this, use the trap_exception exception policy rather than the default throw @@ -227,7 +227,7 @@

    -Adjust type promotion rules.
    +Adjust type promotion rules.

    Another way to avoid arithmetic errors like overflow is to promote types to larger sizes before doing the arithmetic. This can be justified by the observe

    diff --git a/doc/html/safe_literal.html b/doc/html/safe_literal.html index 378d568..7b08929 100644 --- a/doc/html/safe_literal.html +++ b/doc/html/safe_literal.html @@ -22,17 +22,17 @@ safe_signed_literal<Value, PP , EP> and safe_unsigned_literal<Value, PP, EP>

    -Description

    +Description

    A safe type which holds a literal value. This is required to be able to initialize other safe type in such a way that exception code is not generated. It is also useful when creating constexpr versions of safe @@ -41,7 +41,7 @@

    -Associated Types

    +Associated Types
    @@ -63,7 +63,7 @@

    -Template Parameters

    +Template Parameters
    @@ -97,14 +97,14 @@

    -Model of

    +Model of

    Integer

    SafeNumeric

    LiteralType

    -Inherited Valid Expressions

    +Inherited Valid Expressions

    SafeLiteral types are immutable. Hence they only inherit those valid expressions which don't change the value. The excludes assignment, increment, and decrement operators. Other than that, they can be used @@ -112,13 +112,13 @@

    -Header

    +Header

    #include <safe/numeric/safe_literal.hpp>

    -Example of use

    +Example of use
    #include <safe/numeric/safe_literal.hpp>
     
     constexpr boost::numeric::safe_signed_literal<42> x;
    diff --git a/doc/html/safe_numeric_concept.html b/doc/html/safe_numeric_concept.html
    index 8d52273..1c6a8b2 100644
    --- a/doc/html/safe_numeric_concept.html
    +++ b/doc/html/safe_numeric_concept.html
    @@ -21,18 +21,18 @@
     

    SafeNumeric<T>

    -Description

    +Description

    This holds an arithmetic value which can be used as a replacement for built-in C++ arithmetic values. These types differ from their built-in counter parts in that the are guaranteed not to produce invalid arithmetic @@ -40,12 +40,12 @@

    -Refinement of

    +Refinement of

    Numeric

    -Notation

    +Notation
    @@ -94,7 +94,7 @@

    -Valid Expressions

    +Valid Expressions
    @@ -128,14 +128,14 @@ - + - + @@ -203,14 +203,14 @@

    -Complexity Guarantees

    +Complexity Guarantees

    There are no explicit complexity guarantees here. However, it would be very surprising if any implementation were to be more complex that O(0);

    -Invariants

    +Invariants

    The fundamental requirement of a SafeNumeric type is that implements all C++ operations permitted on it's base type in a way the prevents the return of an incorrect arithmetic result. Various implementations of this @@ -220,13 +220,13 @@

    -Header

    +Header

    #include <safe_numerics/include/concepts/safe_numeric.hpp>

    -Models

    +Models

    safe<T>

    safe_signed_range<-11, 11>

    safe_unsigned_range<0, 11>

    diff --git a/doc/html/safe_range.html b/doc/html/safe_range.html index 865652e..1d1cba9 100644 --- a/doc/html/safe_range.html +++ b/doc/html/safe_range.html @@ -22,18 +22,18 @@ safe_signed_range<MIN, MAX, PP, EP> and safe_unsigned_range<MIN, MAX, PP, EP>

    -Description

    +Description

    This type holds a signed or unsigned integer in the closed range [MIN, MAX]. A safe_signed_range<MIN, MAX, PP, EP> or safe_unsigned_range<MIN, MAX, PP, EP> can be used @@ -43,7 +43,7 @@

    -Notation

    +Notation
    prefix_op S unspecified S

    invoke safe C++ operator op and return another - SafeNumeric type.

    invoke safe C++ operator prefix_op and + return another SafeNumeric type.

    S postfix_op unspecified S

    invoke safe C++ operator op and return another - SafeNumeric type.

    invoke safe C++ operator postfix_op + and return another SafeNumeric type.

    s assign_op t
    @@ -62,7 +62,7 @@

    -Associated Types

    +Associated Types
    @@ -84,7 +84,7 @@

    -Template Parameters

    +Template Parameters
    @@ -130,13 +130,13 @@

    -Model of

    +Model of

    Integer

    SafeNumeric

    -Valid Expressions

    +Valid Expressions

    Implements all expressions and only those expressions defined by the SafeNumeric type requirements. This, the result type of such an expression will be another @@ -145,13 +145,13 @@

    -Header

    +Header

    #include <safe/numeric/safe_range.hpp>

    -Example of use

    +Example of use
    #include <safe/numeric/safe_range.hpp>
     
     void f(){
    diff --git a/include/safe_base.hpp b/include/safe_base.hpp
    index 5147806..b5999c2 100644
    --- a/include/safe_base.hpp
    +++ b/include/safe_base.hpp
    @@ -253,15 +253,17 @@ public:
             --(*this);
             return old_t;
         }
    -    safe_base operator-(){ // unary minus
    -        return *this = 0 - *this; // this will check for overflow
    +    // return a safe type. This guarantees that result will
    +    // be checked upon return
    +    constexpr safe_base operator-() const { // unary minus
    +        return 0 - *this; // this will check for overflow
         }
    -    safe_base operator~(){
    +    constexpr safe_base operator~() const {
             static_assert(
                 std::numeric_limits::is_signed,
                 "Bitwise inversion of signed value is an error"
             );
    -        return *this = ~(m_t);
    +        return ~(m_t);
         }
     };
     
    diff --git a/include/safe_base_operations.hpp b/include/safe_base_operations.hpp
    index 195048a..ad3f962 100644
    --- a/include/safe_base_operations.hpp
    +++ b/include/safe_base_operations.hpp
    @@ -183,12 +183,6 @@ struct common_policies {
             "if the promotion policies are different, one must be void!"
         );
     
    -    static_assert(
    -        ! std::is_same::value
    -        || !std::is_same::value,
    -        "at least one promotion polcy must be non void"
    -    );
    -
         static_assert(
             ! (std::is_same::value
             && std::is_same::value),
    diff --git a/include/safe_literal.hpp b/include/safe_literal.hpp
    index 7d359bb..88b45dd 100644
    --- a/include/safe_literal.hpp
    +++ b/include/safe_literal.hpp
    @@ -13,6 +13,8 @@
     // http://www.boost.org/LICENSE_1_0.txt)
     
     #include  // for intmax_t/uintmax_t
    +#include 
    +
     #include "utility.hpp"
     #include "safe_base.hpp"
     #include "safe_base_operations.hpp"
    @@ -94,6 +96,18 @@ public:
         constexpr operator R () const {
             return N;
         }
    +    // return a safe type. This guarantees that result will
    +    // be checked upon return
    +    constexpr safe_literal_impl operator-() const { // unary minus
    +        return 0 - N; // this will check for overflow
    +    }
    +    constexpr safe_literal_impl operator~() const {
    +        static_assert(
    +            std::numeric_limits::is_signed,
    +            "Bitwise inversion of signed value is an error"
    +        );
    +        return ~N;
    +    }
     };
     
     template<
    @@ -108,7 +122,7 @@ using safe_signed_literal = safe_literal_impl<
         E
     >;
     
    -template <
    +template<
         std::uintmax_t N,
         class P = native,
         class E = throw_exception
    @@ -120,6 +134,13 @@ using safe_unsigned_literal = safe_literal_impl<
         E
     >;
     
    +#define safe_literal(n)                               \
    +    boost::mpl::if_c<                                 \
    +        std::numeric_limits>::is_signed>. \
    +        safe_unsigned_literal,               \
    +        safe_signed_literal                  \
    +    >::type
    +
     } // numeric
     } // boost
     
    diff --git a/test/test_z.cpp b/test/test_z.cpp
    index b37dcc4..0702b14 100644
    --- a/test/test_z.cpp
    +++ b/test/test_z.cpp
    @@ -329,7 +329,6 @@ int main(int argc, const char * argv[]){
         return 0;
     }
     
    -#endif
     
     // test safe_literal.
     // can't make this an offcial test yet as we need implement
    @@ -363,3 +362,33 @@ int main(int argc, const char * argv[]){
         return 0;
     }
     
    +#endif
    +
    +auto val()
    +{
    +  return -0xFFFFFFFF;
    +}
    +
    +#include 
    +#include 
    +#include "../include/safe_integer.hpp"
    +#include "../include/safe_literal.hpp"
    +
    +auto val1()
    +{
    +    constexpr boost::numeric::safe x = boost::numeric::safe_unsigned_literal<0xFFFFFFFF>();
    +    return -x;
    +}
    +
    +auto val2()
    +{
    +    return - boost::numeric::safe_unsigned_literal<0xFFFFFFFF>();
    +}
    +
    +int main(){
    +    std::cout << val() << std::endl;
    +    std::cout << val1() << std::endl;
    +    std::cout << val2() << std::endl;
    +}
    +
    +