doc: add doc for num namespace
This commit is contained in:
@@ -43,6 +43,12 @@
|
||||
|
||||
\li \subpage num__parser
|
||||
|
||||
\li \subpage num__op
|
||||
|
||||
\li \subpage num__safe_cast
|
||||
|
||||
\li \subpage num__safe_op
|
||||
|
||||
\li \subpage patch
|
||||
|
||||
<B>Text Encoding</B>
|
||||
|
||||
30
doc/src/num/op.dox
Normal file
30
doc/src/num/op.dox
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace yycc::num::op {
|
||||
/**
|
||||
|
||||
\page num__op Numeric Operations
|
||||
|
||||
Namespace yycc::num::op provides functions for robust numeric operations inspired by Rust's approach to primitive type operations.
|
||||
|
||||
Currently, this namespace only supports unsigned integer ceiling division, though more operations may be added in the future based on demand.
|
||||
|
||||
\section num__op__div_ceil Ceiling Division
|
||||
|
||||
The \c div_ceil function performs division between two unsigned integers and rounds up the result.
|
||||
It uses a safe algorithm that avoids potential overflow issues that could occur with the traditional formula <TT>(lhs + rhs - 1) / rhs</TT>.
|
||||
|
||||
The function computes: <TT>(lhs % rhs == 0) ? (lhs / rhs) : (lhs / rhs) + 1u</TT>
|
||||
The function prevents division by zero by checking the divisor before performing the operation and throwing a std::logic_error if the divisor is zero.
|
||||
|
||||
Here are some examples showing how to use this function:
|
||||
|
||||
\code
|
||||
#include <yycc/num/op.hpp>
|
||||
|
||||
// Ceiling division examples
|
||||
uint32_t result1 = op::div_ceil(uint32_t(10), uint32_t(3)); // Results in 4
|
||||
uint32_t result2 = op::div_ceil(uint32_t(9), uint32_t(3)); // Results in 3
|
||||
uint32_t result3 = op::div_ceil(uint32_t(1), uint32_t(10)); // Results in 1
|
||||
\endcode
|
||||
|
||||
*/
|
||||
}
|
||||
63
doc/src/num/safe_cast.dox
Normal file
63
doc/src/num/safe_cast.dox
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace yycc::num::safe_cast {
|
||||
/**
|
||||
|
||||
\page num__safe_cast Numeric Safe Casting
|
||||
|
||||
Namespace yycc::num::safe_cast provides functions which safely cast numeric value from one type to another.
|
||||
|
||||
\section num__safe_cast__overview Overview
|
||||
|
||||
When writing C++ code, casting between types with different ranges is very important
|
||||
but greatly easy to make mistakes which finally cause fatal errors.
|
||||
Inspired by Rust's approach to type conversion,
|
||||
this namespace provides safe casting functions that handle potential overflow and underflow issues.
|
||||
|
||||
\section num__safe_cast__functions Functions
|
||||
|
||||
The namespace provides two main functions:
|
||||
\li \c to() - Direct conversion for cases where the destination type can definitely hold the source value
|
||||
which means definitely safe conversions (widening conversions).
|
||||
\li \c try_to() - Attempt conversion and return a Result type that includes error information if the conversion fails
|
||||
which means potentially risky conversions (narrowing conversions).
|
||||
|
||||
The \c try_to function returns a \c std::expected.
|
||||
If the conversion succeeds, the result contains the converted value.
|
||||
If it fails, it contains a error info.
|
||||
|
||||
\section num__safe_cast__examples Examples
|
||||
|
||||
Here are some examples showing how to use the safe casting functions:
|
||||
|
||||
\code
|
||||
#include <yycc/num/safe_cast.hpp>
|
||||
|
||||
// Safe conversion using 'to' function
|
||||
uint32_t val1 = safe_cast::to<uint32_t>(static_cast<int16_t>(123));
|
||||
|
||||
// Potentially risky conversion using 'try_to' function
|
||||
auto result = safe_cast::try_to<int16_t>(static_cast<int32_t>(12345));
|
||||
if (result.has_value()) {
|
||||
auto converted = result.value();
|
||||
// Use converted value
|
||||
} else {
|
||||
// Handle error
|
||||
}
|
||||
\endcode
|
||||
|
||||
\section num__safe_cast__notes Notes
|
||||
|
||||
The safety of conversions is determined at compile time using the \c CAN_SAFE_TO meta-programming concept.
|
||||
However, for variable-length data types (like \c size_t ), the safety determination may vary across platforms,
|
||||
which could affect code portability. For this reason, it would be better to use \c try_to for these types
|
||||
for better robust application on different platforms.
|
||||
|
||||
\section num__safe_cast__limitations Limitations
|
||||
|
||||
This namespace supports safe casting between integral types only.
|
||||
Currently unsupported conversions include:
|
||||
|
||||
\li Floating-point to floating-point conversions
|
||||
\li Floating-point to integer conversions
|
||||
|
||||
*/
|
||||
}
|
||||
86
doc/src/num/safe_op.dox
Normal file
86
doc/src/num/safe_op.dox
Normal file
@@ -0,0 +1,86 @@
|
||||
namespace yycc::num::safe_op {
|
||||
/**
|
||||
|
||||
\page num__safe_op Numeric Safe Arithmetic Operations
|
||||
|
||||
Namespace yycc::num::safe_op provides Rust-like safe arithmetic operations
|
||||
for handling overflow, underflow, and other undefined behaviors in C++.
|
||||
|
||||
\section num__safe_op__overview Overview
|
||||
|
||||
Inspired by Rust's rich set of arithmetic operators,
|
||||
this namespace provides safe arithmetic operations that handle potential overflow, underflow, and other undefined behaviors that commonly occur in C++.
|
||||
It offers multiple strategies for handling arithmetic operations including wrapping, checked, overflowing, saturating, and strict operations.
|
||||
|
||||
\section num__safe_op__operation_types Operation Types
|
||||
|
||||
The namespace provides several families of arithmetic operations:
|
||||
|
||||
\li \c wrapping_* operations: Perform arithmetic with wrapping on overflow/underflow (similar to unsigned integer behavior)
|
||||
\li \c checked_* operations: Return std::optional containing the result, or std::nullopt if overflow/underflow occurs
|
||||
\li \c overflowing_* operations: Return a pair with the result and a boolean indicating whether overflow occurred
|
||||
\li \c saturating_* operations: Clamp the result to the min/max value when overflow/underflow occurs
|
||||
\li \c strict_* operations: Throw exceptions when overflow/underflow occurs
|
||||
\li \c ordinary operations (add, sub, mul, div): Alias to wrapping operations for safe default behavior
|
||||
|
||||
\section num__safe_op__arithmetic_functions Arithmetic Functions
|
||||
|
||||
For each operation type, the namespace provides functions for the four basic arithmetic operations:
|
||||
\li \c _add : Addition
|
||||
\li \c _sub : Subtraction
|
||||
\li \c _mul : Multiplication
|
||||
\li \c _div : Division
|
||||
|
||||
For example, for wrapping operations: \c wrapping_add, \c wrapping_sub, \c wrapping_mul, \c wrapping_div.
|
||||
|
||||
\section num__safe_op__examples Examples
|
||||
|
||||
Here are some examples showing how to use the safe arithmetic functions:
|
||||
|
||||
\code
|
||||
#include <yycc/num/safe_op.hpp>
|
||||
#include <iostream>
|
||||
|
||||
// Wrapping addition - wraps around on overflow
|
||||
uint8_t result1 = safe_op::wrapping_add(uint8_t(200), uint8_t(100)); // Results in 44
|
||||
|
||||
// Checked multiplication - returns std::optional
|
||||
auto result2 = safe_op::checked_mul(int32_t(1000000), int32_t(1000000));
|
||||
if (!result2.has_value()) {
|
||||
std::cout << "Multiplication overflowed!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Result: " << result2.value() << std::endl;
|
||||
}
|
||||
|
||||
// Overflowing subtraction - returns pair of result and overflow flag
|
||||
auto [result3, overflowed] = safe_op::overflowing_sub(int32_t(-10), int32_t(INT32_MIN));
|
||||
if (overflowed) {
|
||||
std::cout << "Subtraction overflowed!" << std::endl;
|
||||
}
|
||||
|
||||
// Saturating multiplication - clamps to min/max on overflow
|
||||
int32_t result4 = safe_op::saturating_mul(int32_t(1000000), int32_t(1000000)); // Clamps to INT32_MAX
|
||||
|
||||
// Ordinary operations - safe defaults without undefined behavior
|
||||
int32_t result5 = safe_op::add(int32_t(10), int32_t(20)); // 30
|
||||
\endcode
|
||||
|
||||
\section num__safe_op__undefined_behaviors Handling of Undefined Behaviors
|
||||
|
||||
This namespace handles several undefined behaviors in C++ arithmetic:
|
||||
\li Signed integer overflow and underflow (e.g. INT_MAX + 1)
|
||||
\li Division by zero
|
||||
\li Performing INT_MIN / -1 division (which would result in a value that doesn't fit in the type)
|
||||
|
||||
For division operations, special care is taken to handle these undefined behaviors appropriately depending on the operation type.
|
||||
|
||||
\section num__safe_op__platform_support Platform Support
|
||||
|
||||
The implementation uses hardware-specific overflow detection functions:
|
||||
\li GCC/Clang: Uses built-in functions like __builtin_add_overflow
|
||||
\li Windows: Uses Windows API functions from \c intsafe.h
|
||||
|
||||
This ensures optimal performance across different platforms.
|
||||
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user