Skip to content

Commit

Permalink
documentation update
Browse files Browse the repository at this point in the history
  • Loading branch information
Artur Bać committed Mar 6, 2024
1 parent aeb7b3e commit 8dbe4d6
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 20 deletions.
35 changes: 35 additions & 0 deletions docs/bitwise_operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

## Bitwise Operations in FixedMath

The FixedMath library includes support for bitwise operations on fixed-point numbers (`fixed_t`), carefully implemented to preserve the integrity of fixed-point arithmetic while providing essential functionality.

### Right Shift Operator

- **`operator >> (fixed_t l, int r) noexcept`**: This function applies the bitwise right shift operation to a `fixed_t` value. If the shift count `r` is non-negative, the function performs the shift operation and returns the result. If `r` is negative, it returns NaN to indicate an invalid operation. This ensures that the operation only proceeds under valid conditions.

### Left Shift Operator

- **`operator << (fixed_t l, int r) noexcept`**: The bitwise left shift operation is more complex due to the need to handle the sign bit correctly in a fixed-point context. If the shift count `r` is non-negative, it performs the shift while maintaining the sign bit of the original value. This is achieved by:
- Shifting the unsigned representation of the value left by `r` bits.
- Clearing any bits that overflow into the sign bit area to avoid corrupting the sign.
- Preserving the original sign bit of the `fixed_t` value.

### Safety and Correctness

Both operators incorporate checks to ensure that shift operations are only performed with non-negative shift counts, adhering to the principles of safety and precision that characterize fixed-point arithmetic in the FixedMath library. This approach prevents undefined or unexpected behavior that could arise from attempting to shift by negative counts or risking overflow/underflow conditions.

### Usage Example

```cpp
fixed_t a = ...; // Initialize with some value

// Right shift operation
fixed_t result_right_shift = a >> 2; // Shifts `a` right by 2 bits

// Left shift operation
fixed_t result_left_shift = a << 3; // Shifts `a` left by 3 bits, maintaining the sign bit
```

### Note on Bitwise Operations

While bitwise operations on fixed-point numbers can be useful, it's essential to use them judiciously, especially considering the potential for altering the numeric value in ways that are not directly analogous to integer arithmetic due to the fixed-point representation.
46 changes: 46 additions & 0 deletions docs/conversion_between_fixed_and_arithmetic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

## Conversion between Fixed and Arithmetic Types in FixedMath

The FixedMath library provides seamless conversion mechanisms between fixed-point numbers (`fixed_t`) and standard arithmetic types (integers and floating-point numbers). These conversions ensure that fixed-point arithmetic integrates well with the broader C++ type system, allowing for efficient and type-safe operations across different numeric types.

### Conversion from `fixed_t` to Arithmetic Types

- **`fixed_to_arithmetic<arithmetic_type>(fixed_t value) noexcept`**: Converts a `fixed_t` value to a specified arithmetic type (`arithmetic_type`). The function discriminates between integral and floating-point types, using the most appropriate conversion method for each case:
- For integral types, it converts the `fixed_t` value to the corresponding integral conversion.
- For floating-point types, it converts the `fixed_t` value to the corresponding floating-point conversion.

- **`fixed_t::operator arithmetic_type() const noexcept`**: A type conversion operator that allows a `fixed_t` object to be automatically converted to an arithmetic type when required. This leverages the `fixed_to_arithmetic` template function internally to perform the conversion.

### Conversion from Arithmetic Types to `fixed_t`

- **`arithmetic_to_fixed<arithmetic_type>(arithmetic_type value) noexcept`**: Provides a clear interface for converting arithmetic types to `fixed_t`.

### Examples of Use

Conversion from `fixed_t` to arithmetic types:

```cpp
fixed_t fixedValue = 2.5_fix; // Initialize with some fixed-point value

// Convert to an integer
int intValue = fixed_to_arithmetic<int>(fixedValue);

// Convert to a floating-point
double doubleValue = fixedValue; // Implicitly uses fixed_t::operator double() const
```

Conversion from arithmetic types to `fixed_t`:

```cpp
int intInput = 5;
// Convert from integer to fixed_t
fixed_t fixedFromInt = arithmetic_to_fixed(intInput);

double doubleInput = 2.5;
// Convert from floating-point to fixed_t
fixed_t fixedFromDouble = arithmetic_to_fixed(doubleInput);

fixedFromDouble = static_cast<double>(arithmetic_to_fixed(doubleInput));
```

These conversion functions and operators ensure that working with fixed-point numbers in a mixed arithmetic context is both natural and efficient, maintaining type safety and precision across conversions.
21 changes: 10 additions & 11 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

The FixedMath library provides a comprehensive suite for fixed-point arithmetic operations, optimized for performance and precision. It includes basic arithmetic operations, trigonometric functions, conversion utilities, and more.



## Main Type

- [`struct fixed_t`](fixed_t.md): The main type used in calculations.
Expand All @@ -18,48 +16,49 @@ The FixedMath library provides a comprehensive suite for fixed-point arithmetic

### Addition

See [documentation of addition](addition.md) for more details.

See our [full documentation of addition](addition.md) for more details.

- `auto fixed_addition(supported_type1 lh, supported_type2 rh) noexcept` : Returns the result of the addition of two arguments.
- `auto operator +(supported_type1 l, supported_type2 r) noexcept` : Operator overload for addition.
- `fixed_t &operator +=(fixed_t &l, supported_type r) noexcept`: Addition assignment.

### Subtraction

- `auto fixed_substract(supported_type1 lh, supported_type2 rh) noexcept`: Returns the result of the subtraction of two arguments.
See [documentation of subtraction](subtraction.md) for more details.

- `auto operator -(supported_type1 l, supported_type2 r) noexcept`: Operator overload for subtraction.
- `fixed_t & operator -=(fixed_t &lh, supported_type rh) noexcept`: Subtraction assignment.

### Multiplication

See our [full documentation of multiplication](multiplication.md) for more details.
See [documentation of multiplication](multiplication.md) for more details.

- `auto fixed_multiply(supported_type1 lh, supported_type2 rh) noexcept`: Returns the result of the multiplication of two arguments.
- `auto operator *(supported_type1 lh, supported_type2 rh) noexcept`: Operator overload for multiplication.
- `fixed_t & operator *=(fixed_t &lh, supported_type rh) noexcept`: Multiplication assignment.

### Division

See our [full documentation of division](division.md) for more details.
See [documentation of division](division.md) for more details.

- `auto fixed_division(supported_type1 lh, supported_type2 rh) noexcept`: Returns the result of the division of two arguments.
- `auto operator /(supported_type1 lh, supported_type2 rh) noexcept`: Operator overload for division.
- `fixed_t & operator /=(fixed_t &lh, supported_type rh) noexcept`: Division assignment.

## Bitwise Operations

See [documentation of bitwise operations](bitwise_operations.md) for more details.

- `fixed_t operator >>(fixed_t l, int r) noexcept`: Shifts right the value of `l` by `r` digits.
- `fixed_t operator <<(fixed_t l, int r) noexcept`: Shifts left the value of `l` by `r` digits.

## Conversion Operations

See [documentation of conversion between fixed and arithmetic types](conversion_between_fixed_and_arithmetic.md) for more details.

- `fixed_t arithmetic_to_fixed(arithmetic_type value) noexcept`: Converts any floating point or integral value into a fixed point.
- `arithmetic_type fixed_to_arithmetic(fixed_t value) noexcept`: Converts `fixed_t` into any floating point or integral type.

## Trigonometric Functions

- `fixed_t sin(fixed_t rad) noexcept`: Returns the sine of `rad` in radians.
- [`fixed_t sin(fixed_t rad) noexcept`](sine.md): Returns the sine of `rad` in radians.
- `fixed_t cos(fixed_t rad) noexcept`: Returns the cosine of `rad` in radians.
- `fixed_t tan(fixed_t rad) noexcept`: Returns the tangent of `rad`.
- `fixed_t asin(fixed_t x) noexcept`: Returns the arc sine of `x`.
Expand Down
96 changes: 96 additions & 0 deletions docs/sine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

## Sine Function in FixedMath

The FixedMath library provides an implementation for the sine function using Maclaurin series expansion, a form of the Taylor series centered at zero. This method is chosen for its efficiency in computing trigonometric functions within a fixed range of input values, ensuring both accuracy and performance.

### Implementation Details

The sine function's implementation involves normalizing the input angle to a specific range and then calculating the sine using a truncated series expansion. Here's an overview of the process:

- **Normalization**: The input angle (`rad`) is normalized to the range \(-\frac{\phi}{2}\) to \(3\frac{\phi}{2}\), where \(\phi\) represents the value of pi in the fixed-point format. This normalization ensures the angle is within the optimal range for the Maclaurin series calculation.

- **Maclaurin Series for Sine**: The sine of the angle is computed as:

\[ \sin(x) = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots \]

However, to optimize performance, the series is simplified and truncated, with the error kept below a certain threshold. The implementation uses a series expansion with a reduced number of divisions for efficiency:

\[ x \left( 1 - x^2 \left( \frac{1}{6} - \frac{x^2}{120} \left( 1 - \frac{x^2}{42} \right) \right) \right) \]

This approximation not only simplifies the computation but also significantly reduces the computational overhead by minimizing the number of division operations required.

### Key Functions

- **`sin_range(fixed_t rad) noexcept`**: Normalizes the input angle into the correct range for the sine calculation.

- **`sin(fixed_t rad) noexcept`**: Calculates the sine of the given angle in radians using the optimized Maclaurin series expansion.

### Example Usage

```cpp
fixed_t rad = ...; // some angle in radians
fixed_t sin_value = sin(rad); // calculates sine of rad
```

This sine function implementation ensures high accuracy for angles within the normalized range, making it suitable for various applications requiring trigonometric calculations in fixed-point arithmetic.

## Optimization Process: Reduction of Divisions

The implementation details reveal an innovative approach to reducing the computational cost associated with division operations in the series expansion. By reorganizing the equation and strategically applying mathematical properties, the number of divisions is significantly reduced, enhancing the function's performance while maintaining accuracy. This optimization is particularly beneficial in environments where division operations are costly in terms of processing time.

The sine function's optimization involves a step-by-step transformation of the Maclaurin series to reduce the number of division operations required.

The series of transformations applied to the sine function calculation is as follows:

1. Initial Equation:
\[ x \left( 1 - x^2 \left( 1 - x^2 \left( 1 - x^2 \cdot rac{1}{42}
ight) \cdot rac{1}{20}
ight) \cdot rac{1}{6}
ight) \]

2. Reduction of Division Operations 1:
\[ x \left( 1 - x^2 \left( 1 - x^2 \left( 1 - x^2 \cdot \left( rac{1}{2} \cdot rac{1}{21}
ight)
ight) \cdot \left( rac{1}{4} \cdot rac{1}{5}
ight)
ight) \cdot \left( rac{1}{2} \cdot rac{1}{3}
ight)
ight) \]

3. Reduction of Division Operations 2:
\[ x \left( 1 - x^2 \left( 1 - x^2 \cdot rac{1}{21} \left( 21 - x^2 \cdot rac{1}{2}
ight) \cdot rac{1}{4} \cdot rac{1}{5}
ight) \cdot rac{1}{2} \cdot rac{1}{3}
ight) \]

4. Reduction of Division Operations 3:
\[ x \left( 1 - x^2 \left( 1 - x^2 \cdot rac{1}{105} \left( 21 - x^2 \cdot rac{1}{2}
ight) \cdot rac{1}{4}
ight) \cdot rac{1}{2} \cdot rac{1}{3}
ight) \]

5. Consolidation of Terms:
\[ x \left( 1 - x^2 \cdot rac{1}{630} \left( 105 - x^2 \left( 21 - x^2 \cdot rac{1}{2}
ight) \cdot rac{1}{4}
ight) \cdot rac{1}{2}
ight) \]

6. Further Consolidation:
\[ x \left( rac{3 \cdot 5 \cdot 21 - x^2 \left( 5 \cdot 21 - x^2 \left( 21 - x^2 \cdot rac{1}{2}
ight) \cdot rac{1}{4}
ight) \cdot rac{1}{2} }{3 \cdot 5 \cdot 21}
ight) \]

7. Final Equation before Simplification:
\[ x \left( rac{315 - x^2 \left( 105 - x^2 \left( 21 - x^2 \cdot rac{1}{2}
ight) \cdot rac{1}{4}
ight) \cdot rac{1}{2} }{315}
ight) \]

8. Simplified Final Equation:
\[ x \left( rac{315 - x^2 \left( 105 - x^2 \left( 42 - x^2
ight) \cdot rac{1}{8}
ight) \cdot rac{1}{2} }{315}
ight) \]

This step-by-step approach highlights the methodical reduction in division operations, leading to the final, optimized equation used for calculating the sine function in the FixedMath library.
44 changes: 44 additions & 0 deletions docs/subtraction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

## Subtraction in FixedMath

The FixedMath library precisely manages the subtraction of fixed-point numbers (`fixed_t`), ensuring accuracy and robustness across various operations. This includes support for mixed-type arithmetic involving `fixed_t`, integers, and floating-point numbers.

### Core Subtraction Functionality

- **`fixed_substracti(fixed_t lh, fixed_t rh) noexcept`**: This function computes the difference between two `fixed_t` values, incorporating checks to prevent anomalous results. It returns NaN to indicate an error when the operation results in an overflow or underflow, especially when subtracting values across different signs that should normally produce a valid range but don't due to fixed-point constraints.

### Type Promotion and Arithmetic

- **Promotion to Double**: For operations that involve a double, the `fixed_t` value is promoted to double precision prior to subtraction, ensuring the operation benefits from the precision of floating-point arithmetic.

- **Promotion to Fixed**: When an arithmetic operation includes types other than `fixed_t`, the non-fixed type is elevated to `fixed_t` using `promote_to_fixed`. This enables the operation to proceed with fixed-point accuracy.

### Subtraction Operator Overloads

- **Operator `-=`**: Adjusts the left-hand operand by subtracting the right-hand operand from it. The right operand can be any arithmetic type, with the operation performed after suitable type promotions to ensure accuracy.

- **Operator `-`**: Implements subtraction between two operands of potentially mixed types. The outcome is either a `fixed_t` or a double, depending on whether any of the operands is a double, to optimize the operation's precision for the given operand types.

### Specialized Subtraction Functions

- **`promoted_double_substract`**: Specially caters to subtraction operations where at least one of the operands is a double, elevating the operation to double precision.

- **`promoted_fixed_substract`**: Facilitates the subtraction of two arithmetic values, promoting them to `fixed_t` as necessary, to ensure the operation is executed within the fixed-point realm.

### Safety and Precision

Subtraction operations in the FixedMath library are crafted with a focus on safety, ensuring that conditions like potential overflows or underflows are managed adeptly, returning NaN in situations where accurate results cannot be guaranteed.

### Usage Example

```cpp
fixed_t a = ...; // Initialize with some value
fixed_t b = ...; // Another fixed_t value
fixed_t result = a - b; // Subtraction of two fixed_t values

int scalar = 5;
fixed_t result2 = a - scalar; // Subtraction with an integer scalar

double d = 2.0;
auto result3 = a - d; // Subtraction with a double, result is promoted to double
```
20 changes: 11 additions & 9 deletions fixed_lib/include/fixedmath/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ namespace fixedmath

rad = detail::sin_range(rad);

// on arm64 condition is compiled as substraction with csel instruction without jump
// on arm64 condition is compiled as subtraction with csel instruction without jump
// mov w9, #9279
// movk w9, #3, lsl #16
// cmp x0, x8
Expand All @@ -761,14 +761,16 @@ namespace fixedmath
fixed_internal result{ mul_<prec_>(x,( one__ - mul_<prec_+1>(x2,( one__ - mul_<prec_+2>(x2,( one__-x2/42))/5))/3)) };
#else
// reduce number of divisions
// { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 42 } } right ) cdot { 1 over 20 } } right ) { 1 over 6 } } right ) }
// { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 2 } { 1 over 21 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) }
// { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over 21 } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) }
// { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over { 5 cdot 21 } } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) }
// { x left ( { 1 - x ^ 2 { 1 over { 3 cdot 5 cdot 21 } } left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) }
// { x left ( { 3 cdot 5 cdot 21 - x ^ 2 left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) { 1 over { 3 cdot 5 cdot 21 } } }
// { x left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) :315 }
// { x left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 42 - x ^ 2 } right ) cdot { 1 over 8 } } right ) { 1 over 2 } } right ) :315 }
/*
{ x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 42 } } right ) cdot { 1 over 20 } } right ) { 1 over 6 } } right ) }
{ x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 2 } { 1 over 21 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) }
{ x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over 21 } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) }
{ x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over { 5 cdot 21 } } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) }
{ x left ( { 1 - x ^ 2 { 1 over { 3 cdot 5 cdot 21 } } left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) }
{ x left ( { 3 cdot 5 cdot 21 - x ^ 2 left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) { 1 over { 3 cdot 5 cdot 21 } } }
{ x left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) :315 }
{ x left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 42 - x ^ 2 } right ) cdot { 1 over 8 } } right ) { 1 over 2 } } right ) :315 }
*/
constexpr fixed_internal _42{ fixed_internal{42}<<prec_};
constexpr fixed_internal _105{ fixed_internal{105}<<(prec_+prec_+3)};
constexpr fixed_internal _315{ fixed_internal{315}<<prec_};
Expand Down

0 comments on commit 8dbe4d6

Please sign in to comment.