Index: base/numerics/README.md |
diff --git a/base/numerics/README.md b/base/numerics/README.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5509daf11b68b154bce8a698cddcc686fc2ef7d9 |
--- /dev/null |
+++ b/base/numerics/README.md |
@@ -0,0 +1,249 @@ |
+# `base/numerics` |
+ |
+This directory contains templates providing well-defined semantics for safely |
+handling a variety of numeric operations, including most common arithmetic |
+operations and conversions. |
+ |
+The public API is broken out into the following header files: |
+ |
+* `checked_math.h` contains the `CheckedNumeric` template class and helper |
+ functions for performing arithmetic and conversion operations that detect |
+ errors and boundary conditions (e.g. overflow, truncation, etc.). |
+* `clamped_math.h` contains the `ClampedNumeric` template class and |
+ helper functions for performing fast, clamped (i.e. non-sticky saturating) |
+ arithmetic operations and conversions. |
+* `safe_conversions.h` contains the `StrictNumeric` template class and |
+ a collection of custom casting templates and helper functions for safely |
+ converting between a range of numeric types. |
+* `safe_math.h` includes all of the previously mentioned headers. |
+ |
+[TOC] |
+ |
+## Conversion functions and `StrictNumeric<>` in `safe_conversions.h` |
+ |
+This header includes a collection of helper `constexpr` templates for safely |
+performing a range of conversions, assignments, and tests. |
+ |
+### Safe casting templates |
+ |
+* `as_signed()` - Returns the supplied integral value as a signed type of |
+ the same width. |
+* `as_unsigned()` - Returns the supplied integral value as an unsigned type |
+ of the same width. |
dcheng
2017/06/28 07:25:06
I think I'm being unimaginative, but to me, I'm no
jschuh
2017/06/28 12:32:37
There's a number of places where we require a sign
dcheng
2017/06/30 07:39:30
Hmm... I guess they just don't feel very "safe mat
|
+* `checked_cast<>()` - Analogous to `static_cast<>` for numeric types, except |
+ that by default it will trigger a crash on an out-of-bounds conversion (e.g. |
+ overflow, underflow, NaN to integral) or a compile error if the conversion |
+ error can be detected at compile time. The crash handler can be overridden |
+ to perform a behavior other than crashing. |
+* `saturated_cast<>()` - Analogous to `static_cast` for numeric types, except |
+ that it returns a saturated result when the specified numeric conversion |
+ would otherwise overflow or underflow. An NaN source returns 0 by |
+ default, but can be overridden to return a different result. |
+* `strict_cast<>()` - Analogous to `static_cast` for numeric types, except |
+ this causes a compile failure if the destination type is not large |
+ enough to contain any value in the source type. It performs no runtime |
+ checking and thus introduces no runtime overhead. |
+ |
+### Other helper and conversion functions |
+ |
+* `IsValueInRangeForNumericType<>()` - A convenience function that returns |
+ true if the type supplied to the template parameter can represent the value |
+ passed as an argument to the function. |
+* `IsValueNegative()` - A convenience function that will accept any |
+ arithmetic type as an argument and will return whether the value is less |
+ than zero. Unsigned types always return false. |
+* `SafeUnsignedAbs()` - Returns the absolute value of the supplied integer |
+ parameter as an unsigned result (thus avoiding an overflow if the value |
+ is the signed, two's complement minimum). |
+ |
+### `StrictNumeric<>` |
+ |
+`StrictNumeric<>` is a wrapper type that performs assignments and copies via |
+the `strict_cast` template, and can perform valid arithmetic comparisons |
+across any range of arithmetic types. `StrictNumeric` is the return type for |
+values extracted from a `CheckedNumeric` class instance. The raw numeric value |
+is extracted via `static_cast` to the underlying type or any type with |
+sufficient range to represent the underlying type. |
+ |
+* `MakeStrictNum()` - Creates a new `StrictNumeric` from the underlying type |
+ of the supplied arithmetic or StrictNumeric type. |
+* `SizeT` - Alias for `StrictNumeric<size_t>`. |
+ |
+## `CheckedNumeric<>` in `checked_math.h` |
+ |
+`CheckedNumeric<>` implements all the logic and operators for detecting integer |
+boundary conditions such as overflow, underflow, and invalid conversions. |
+The `CheckedNumeric` type implicitly converts from floating point and integer |
+data types, and contains overloads for basic arithmetic operations (i.e.: `+`, |
+`-`, `*`, `/` for all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers). |
+Type promotions are a slightly modified version of the [standard C/C++ numeric |
+promotions |
+](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions) |
+with the two differences being that there is no default promotion to int |
+and bitwise logical operations always return an unsigned of the wider type. |
+ |
+### Members |
+ |
+The unary negation, increment, and decrement operators are supported, along |
+with the following unary arithmetic methods, which return a new |
+`CheckedNumeric` as a result of the operation: |
+ |
+* `Abs()` - Absolute value. |
+* `UnsignedAbs()` - Absolute value as an equal-width unsigned underlying type |
+ (valid for only integral types). |
+* `Max()` - Returns whichever is greater of the current instance or argument. |
+ The underlying return type is whichever has the greatest magnitude. |
+* `Min()` - Returns whichever is lowest of the current instance or argument. |
+ The underlying return type is whichever has can represent the lowest |
+ number in the smallest width (e.g. int8_t over unsigned, int over |
+ int8_t, and float over int). |
+ |
+The following are for converting `CheckedNumeric` instances: |
+ |
+* `type` - The underlying numeric type. |
+* `AssignIfValid()` - Assigns the underlying value to the supplied |
+ destination pointer if the value is currently valid and within the |
+ range supported by the destination type. Returns true on success. |
+* `Cast<>()` - Instance method returning a `CheckedNumeric` derived from |
+ casting the current instance to a `CheckedNumeric` of the supplied |
+ destination type. |
+ |
+*** aside |
+The following member functions return a `StrictNumeric`, which is valid for |
+comparison and assignment operations, but will trigger a compile failure on |
+attempts to assign to a type of insufficient range. The underlying value can |
+be extracted by an explicit `static_cast` to the underlying type or any type |
+with sufficient range to represent the underlying type. |
+*** |
+ |
+* `IsValid()` - Returns true if the underlying numeric value is valid (i.e. |
+ has not wrapped or saturated and is not the result of an invalid |
+ conversion). |
+* `ValueOrDie()` - Returns the underlying value. If the state is not valid |
+ this call will trigger a crash by default (but may be overridden by |
+ supplying an alternate handler to the template). |
+* `ValueOrDefault()` - Returns the current value, or the supplied default if |
+ the state is not valid (but will not crash). |
+ |
+**Comparison operators are explicitly not provided** for `CheckedNumeric` |
+types because they could result in a crash if the type is not in a valid state. |
+Patterns like the following should be used instead: |
+ |
+```cpp |
+CheckedNumeric<size_t> checked_size = untrusted_input_value; |
+checked_size += HEADER LENGTH; |
+if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) { |
+ \\ Do stuff on success... |
+} else { |
+ \\ Handle an error... |
+} |
+``` |
+ |
+### Non-member helper functions |
+ |
+The following variadic convenience functions, which accept standard arithmetic |
+or `CheckedNumeric` types, perform arithmetic operations, and return a |
+`CheckedNumeric` result. The supported functions are: |
+ |
+* `CheckAdd()` - Addition. |
+* `CheckSub()` - Subtraction. |
+* `CheckMul()` - Multiplication. |
+* `CheckDiv()` - Division. |
+* `CheckMod()` - Modulus (integer only). |
+* `CheckLsh()` - Left integer shift (integer only). |
+* `CheckRsh()` - Right integer shift (integer only). |
+* `CheckAnd()` - Bitwise AND (integer only with unsigned result). |
+* `CheckOr()` - Bitwise OR (integer only with unsigned result). |
+* `CheckXor()` - Bitwise XOR (integer only with unsigned result). |
+* `CheckMax()` - Maximum of supplied arguments. |
+* `CheckMin()` - Minimum of supplied arguments. |
+ |
+The following wrapper functions can be used to avoid the template |
+disambiguator syntax when converting a destination type. |
+ |
+* `IsValidForType<>()` in place of: `a.template IsValid<>()` |
+* `ValueOrDieForType<>()` in place of: `a.template ValueOrDie<>()` |
+* `ValueOrDefaultForType<>()` in place of: `a.template ValueOrDefault<>()` |
+ |
+The following general utility methods is are useful for converting from |
+arithmetic types to `CheckedNumeric` types: |
+ |
+* `MakeCheckedNum()` - Creates a new `CheckedNumeric` from the underlying type |
+ of the supplied arithmetic or directly convertible type. |
+ |
+## `ClampedNumeric<>` in `clamped_math.h` |
+ |
+`ClampedNumeric<>` implements all the logic and operators for clamped |
+(non-sticky saturating) arithmetic operations and conversions. The |
+`ClampedNumeric` type implicitly converts back and forth between floating point |
+and integer data types, saturating on assignment as appropriate. It contains |
+overloads for basic arithmetic operations (i.e.: `+`, `-`, `*`, `/` for |
+all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers) along with comparison |
+operators for arithmetic types of any size. Type promotions are a slightly |
+modified version of the [standard C/C++ numeric promotions |
+](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions) |
+with the two differences being that there is no default promotion to int and |
+bitwise logical operations always return an unsigned of the wider type. |
+ |
+*** aside |
+Most arithmetic operations saturate normally, to the numeric limit in the |
+direction of the sign. The potentially unusual cases are: |
+ |
+* **Division:** Division by zero returns the saturated limit in the direction |
+ of sign of the dividend (first argument). |
+* **Modulus:** Division by zero returns the dividend (first argument). |
+* **Left shift:** Non-zero values saturate in the direction of the signed |
+ limit (max/min). 0 shifted any amount results in 0. |
+* **Right shift:** Negative values saturate to -1. Positive or 0 saturates |
+ to 0. |
+* **Bitwise operations:** No saturation; bit pattern is identical to |
+ non-saturated bitwise operations. |
+*** |
+ |
+### Members |
+ |
+The unary negation, increment, and decrement operators are supported, along |
+with the following unary arithmetic methods, which return a new |
+`ClampedNumeric` as a result of the operation: |
+ |
+* `Abs()` - Absolute value. |
+* `UnsignedAbs()` - Absolute value as an equal-width unsigned underlying type |
+ (valid for only integral types). |
+* `Max()` - Returns whichever is greater of the current instance or argument. |
+ The underlying return type is whichever has the greatest magnitude. |
+* `Min()` - Returns whichever is lowest of the current instance or argument. |
+ The underlying return type is whichever has can represent the lowest |
+ number in the smallest width (e.g. int8_t over unsigned, int over |
+ int8_t, and float over int). |
+ |
+The following are for converting `ClampedNumeric` instances: |
+ |
+* `type` - The underlying numeric type. |
+* `Cast<>()` - Instance method returning a `ClampedNumeric` derived from |
+ casting the current instance to a `ClampedNumeric` of the supplied |
+ destination type. |
+ |
+### Non-member helper functions |
+ |
+The following variadic convenience functions, which accept standard arithmetic |
+or `ClampedNumeric` types, perform arithmetic operations, and return a |
+`ClampedNumeric` result. The supported functions are: |
+ |
+* `ClampAdd()` - Addition. |
+* `ClampSub()` - Subtraction. |
+* `ClampMul()` - Multiplication. |
+* `ClampDiv()` - Division. |
+* `ClampMod()` - Modulus (integer only). |
+* `ClampLsh()` - Left integer shift (integer only). |
+* `ClampRsh()` - Right integer shift (integer only). |
+* `ClampAnd()` - Bitwise AND (integer only with unsigned result). |
+* `ClampOr()` - Bitwise OR (integer only with unsigned result). |
+* `ClampXor()` - Bitwise XOR (integer only with unsigned result). |
+* `ClampMax()` - Maximum of supplied arguments. |
+* `ClampMin()` - Minimum of supplied arguments. |
+ |
+The following is a general utility method that is useful for converting |
+to a `ClampedNumeric` type: |
+ |
+* `MakeClampedNum()` - Creates a new `ClampedNumeric` from the underlying type |
+ of the supplied arithmetic or directly convertible type. |