freertos_f407/User/system/sgl/include/sgl_math.h

189 lines
6.1 KiB
C

/* source/include/sgl_math.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __SGL_MATH_H__
#define __SGL_MATH_H__
#include <sgl_types.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define sgl_min(a, b) ((a) < (b) ? (a) : (b))
#define sgl_min3(a, b, c) (sgl_min(sgl_min((a), (b)), (c)))
#define sgl_min4(a, b, c, d) (sgl_min(sgl_min((a), (b)), sgl_min((c), (d))))
#define sgl_max(a, b) ((a) > (b) ? (a) : (b))
#define sgl_max3(a, b, c) (sgl_max(sgl_max((a), (b)), (c)))
#define sgl_max4(a, b, c, d) (sgl_max(sgl_max((a), (b)), sgl_max((c), (d))))
#define sgl_clamp(val, min, max) (sgl_max(min, (sgl_min((val), (max)))))
#define sgl_abs(x) ((x) > 0 ? (x) : (- (x)))
#define sgl_pow2(x) ((x) * (x))
#define sgl_pow3(x) ((x) * (x) * (x))
#define sgl_pow4(x) ((x) * (x) * (x) * (x))
#define sgl_is_pow2(x) (((x) & ((x) - 1)) == 0)
#define sgl_is_even(x) (((x) & 1) == 0)
#define sgl_is_odd(x) ((x) & 1)
#define sgl_swap(a, b) do { (*a) ^= (*b); (*b) ^= (*a); (*a) ^= (*b); } while (0)
#define sgl_mid(a, b) (((a) + (b)) / 2)
#define SGL_FIXED_SHIFT (10)
#define SGL_FIXED_ONE (1 << SGL_FIXED_SHIFT)
#define SGL_FIXED_MASK (SGL_FIXED_ONE - 1)
#define SGL_SIN_FIXED_ONE (32767)
#define SGL_COS_FIXED_ONE (32767)
/**
* @brief Calculate the sine of an angle
* @param angle: Angle in degrees such 0-359
* @return sine of the angle from sin0_90_table
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
int32_t sgl_sin(int16_t angle);
/**
* @brief Calculate the cos of an angle
* @param angle: Angle in degrees such 0-359
* @return cos of the angle from sin0_90_table
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
static inline int32_t sgl_cos(int16_t angle)
{
return sgl_sin(angle + 90);
}
/**
* @brief Calculate x number square root
* @param x: x number
* @retval x number square root
*/
uint16_t sgl_sqrt(uint32_t x);
/**
* @brief Calculate error of the square root for a number.
* @param x The number to calculate the error for.
* @return The error of the square root. [0 ~ 255]
*/
uint8_t sgl_sqrt_error(uint32_t x);
/**
* @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm
* implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm)
*
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @return angle
* @note return angle [-32767 ~ 32767]
*/
int32_t sgl_atan2_raw(int x, int y);
/**
* @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm
* implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm)
*
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @return angle
* @note return angle [0 ~ 359]
*/
uint16_t sgl_atan2_angle(int x, int y);
/**
* @brief Split the length into n parts, with the weight of each part.
* @param weight: The weight of each part.
* @param count: The count of parts.
* @param length: The length to split.
* @param gap: The gap between each part.
* @param out: The length of each part.
* @note The error accumulation method of Bresenham's algorithm
*/
void sgl_split_len(const uint8_t *weight, int count, int16_t length, int16_t gap, int16_t *out);
/**
* @brief Split the length into n parts, with the weight of each part.
* @param length: The length to split.
* @param count: The count of parts.
* @param gap: The gap between each part.
* @param out: The length of each part.
* @note The average method of Bresenham's algorithm
*/
void sgl_split_len_avg(int length, int count, int16_t gap, int16_t *out);
/**
* @brief Calculate whether the x and y coordinates have a component.
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @param xv: The x coordinate of the vector
* @param yv: The y coordinate of the vector
* @return 1: The x and y coordinates have a component. 0: The x and y coordinates do not have a component.
*/
static inline int sgl_xy_has_component( int x, int y, int xv, int yv)
{
return ((x != 0 && ((xv ^ x) < 0)) || (y != 0 && ((yv ^ y) < 0)));
}
/**
* @brief Generate a random number.
* @param none
* @return Random number.
* @note The random number generator is in the range of [0, 32767].
*/
int16_t sgl_rand(void);
/**
* @brief Set the seed of the random number generator.
* @param seed: The seed of the random number generator.
* @return none
*/
void sgl_srand(unsigned int seed);
#ifdef __cplusplus
}
#endif
#endif // !__SGL_MATH_H__