mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
102 lines
2.6 KiB
C
102 lines
2.6 KiB
C
/*
|
|
* Copyright (C) 2018 Eistec AB
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @defgroup sys_frac Fractional integer operations
|
|
* @ingroup sys
|
|
*
|
|
* This header provides some functions for scaling integers by fractions, while
|
|
* preserving as many bits as possible.
|
|
*
|
|
* The implementation requires that @ref frac_t is initialized properly, either
|
|
* by calling @ref frac_init, which will compute the algorithm parameters at
|
|
* runtime, or via a precomputed initializer.
|
|
*
|
|
* Precomputing the frac_t values can be done via the application found in
|
|
* `tests/sys/frac-config` in the RIOT tree.
|
|
*
|
|
* ### Numeric precision
|
|
*
|
|
* The algorithm will under certain circumstances give an incorrectly rounded
|
|
* result, more precisely, the result may sometimes be rounded up instead of
|
|
* rounded down when the product in the numerator, @$p = x * num@$, would
|
|
* result in @$p >= 2^{31}@$. Fortunately, the relative error of this rounding
|
|
* mistake is small.
|
|
*
|
|
* This tradeoff is a design choice to make the algorithm faster.
|
|
*
|
|
* @see Libdivide homepage: http://libdivide.com/
|
|
*
|
|
* @file
|
|
* @ingroup sys
|
|
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
|
* @{
|
|
*/
|
|
|
|
#ifndef FRAC_H
|
|
#define FRAC_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief frac descriptor for fraction consisting of two 32 bit integers
|
|
*/
|
|
typedef struct {
|
|
uint32_t frac; /**< fraction */
|
|
uint8_t shift; /**< exponent */
|
|
} frac_t;
|
|
|
|
/**
|
|
* @brief Compute greatest common divisor of @p u and @p v
|
|
*
|
|
* @param[in] u first operand
|
|
* @param[in] v second operand
|
|
*
|
|
* @return Greatest common divisor of @p u and @p v
|
|
*/
|
|
uint32_t gcd32(uint32_t u, uint32_t v);
|
|
|
|
/**
|
|
* @brief Initialize frac_t struct
|
|
*
|
|
* This function computes the mathematical parameters used by the frac algorithm.
|
|
*
|
|
* @note If @p num > @p den, the result from @ref frac_scale modulo 2**32.
|
|
*
|
|
* @pre @p den must not be 0
|
|
*
|
|
* @param[out] frac pointer to frac descriptor to initialize
|
|
* @param[in] num numerator
|
|
* @param[in] den denominator
|
|
*/
|
|
void frac_init(frac_t *frac, uint32_t num, uint32_t den);
|
|
|
|
/**
|
|
* @brief Scale a 32 bit integer by a 32/32 rational number
|
|
*
|
|
* @param[in] frac scaling fraction
|
|
* @param[in] x unscaled integer
|
|
*
|
|
* @return (x * frac) % 2**32, avoiding truncation
|
|
*/
|
|
static inline uint32_t frac_scale(const frac_t *frac, uint32_t x)
|
|
{
|
|
uint32_t scaled = ((uint64_t)frac->frac * x) >> frac->shift;
|
|
return scaled;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
/** @} */
|
|
#endif /* FRAC_H */
|