460 lines
11 KiB
C
Executable File
460 lines
11 KiB
C
Executable File
/**
|
|
* \file fixedmath.h
|
|
* \author Wei Yongming <vincent@minigui.org>
|
|
* \date 2002/01/12
|
|
*
|
|
* \brief This file includes fixed point and three-dimension math routines.
|
|
*
|
|
\verbatim
|
|
|
|
This file is part of MiniGUI, a mature cross-platform windowing
|
|
and Graphics User Interface (GUI) support system for embedded systems
|
|
and smart IoT devices.
|
|
|
|
Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
|
|
Copyright (C) 1998~2002, WEI Yongming
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Or,
|
|
|
|
As this program is a library, any link to this program must follow
|
|
GNU General Public License version 3 (GPLv3). If you cannot accept
|
|
GPLv3, you need to be licensed from FMSoft.
|
|
|
|
If you have got a commercial license of this program, please use it
|
|
under the terms and conditions of the commercial license.
|
|
|
|
For more information about the commercial license, please refer to
|
|
<http://www.minigui.com/en/about/licensing-policy/>.
|
|
|
|
\endverbatim
|
|
*/
|
|
|
|
/*
|
|
* $Id: fixedmath.h 12154 2009-10-15 07:21:34Z weiym $
|
|
*
|
|
* MiniGUI for Linux/uClinux, eCos, uC/OS-II, VxWorks,
|
|
* pSOS, ThreadX, NuCleus, OSE, and Win32.
|
|
*
|
|
* Fixed-point math routins come from Allegro (a gift software)
|
|
* by Shawn Hargreaves and others.
|
|
*/
|
|
|
|
#ifndef _MGUI_MGHAVE_FIXED_MATH_H
|
|
#define _MGUI_MGHAVE_FIXED_MATH_H
|
|
|
|
|
|
#include <errno.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
/* Set up for C function definitions, even when using C++ */
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifdef _MGHAVE_FIXED_MATH
|
|
|
|
/**
|
|
* \addtogroup fns Functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* \addtogroup global_fns Global/general functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* \defgroup fixed_math_fns Fixed point math functions
|
|
*
|
|
* You know that the float point mathematics routines are very
|
|
* expensive. If you do not want precision mathematics result,
|
|
* you can use fixed point. MiniGUI uses a double word (32-bit)
|
|
* integer to represent a fixed point ranged from -32767.0 to
|
|
* 32767.0, and defines some fixed point mathematics routines for
|
|
* your application. Some GDI functions need fixed point
|
|
* math routines, like \a Arc.
|
|
*
|
|
* Example 1:
|
|
*
|
|
* \include fixed_point.c
|
|
*
|
|
* Example 2:
|
|
*
|
|
* \include fixedpoint.c
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* \fn fixed fixsqrt (fixed x)
|
|
* \brief Returns the non-negative square root of a fixed point value.
|
|
*
|
|
* This function returns the non-negative square root of \a x.
|
|
* It fails and sets errno to EDOM, if \a x is negative.
|
|
*
|
|
* \sa fixhypot
|
|
*/
|
|
MG_EXPORT fixed fixsqrt (fixed x);
|
|
|
|
/**
|
|
* \fn fixed fixhypot (fixed x, fixed y)
|
|
* \brief Returns the Euclidean distance from the origin.
|
|
*
|
|
* The function returns the \a sqrt(x*x+y*y). This is the length of
|
|
* the hypotenuse of a right-angle triangle with sides of length \a x and \a y,
|
|
* or the distance of the point \a (x,y) from the origin.
|
|
*
|
|
* \sa fixsqrt
|
|
*/
|
|
MG_EXPORT fixed fixhypot (fixed x, fixed y);
|
|
|
|
/**
|
|
* \fn fixed fixatan (fixed x)
|
|
* \brief Calculates the arc tangent of a fixed point value.
|
|
*
|
|
* This function calculates the arc tangent of \a x; that is the value
|
|
* whose tangent is \a x.
|
|
*
|
|
* \return Returns the arc tangent in radians and the value is
|
|
* mathematically defined to be between -PI/2 and PI/2 (inclusive).
|
|
*
|
|
* \sa fixatan2
|
|
*/
|
|
MG_EXPORT fixed fixatan (fixed x);
|
|
|
|
/**
|
|
* \fn fixed fixatan2 (fixed y, fixed x)
|
|
* \brief Calculates the arc tangent of two fixed point variables.
|
|
*
|
|
* This function calculates the arc tangent of the two variables \a x and \a y.
|
|
* It is similar to calculating the arc tangent of \a y / \a x, except that
|
|
* the signs of both arguments are used to determine the quadrant of the
|
|
* result.
|
|
*
|
|
* \return Returns the result in radians, which is between -PI and PI
|
|
* (inclusive).
|
|
*
|
|
* \sa fixatan
|
|
*/
|
|
MG_EXPORT fixed fixatan2 (fixed y, fixed x);
|
|
|
|
extern MG_EXPORT fixed _cos_tbl[];
|
|
extern MG_EXPORT fixed _tan_tbl[];
|
|
extern MG_EXPORT fixed _acos_tbl[];
|
|
|
|
/************************** inline fixed point math functions *****************/
|
|
/* ftofix and fixtof are used in generic C versions of fixmul and fixdiv */
|
|
|
|
/**
|
|
* \fn fixed ftofix (double x)
|
|
* \brief Converts a float point value to a fixed point value.
|
|
*
|
|
* This function converts the specified float point value \a x to
|
|
* a fixed point value.
|
|
*
|
|
* \note The float point should be ranged from -32767.0 to 32767.0.
|
|
* If it runs out of the range, this function sets \a errno to \a ERANGE.
|
|
*
|
|
* \sa fixtof
|
|
*/
|
|
static inline fixed ftofix (double x)
|
|
{
|
|
if (x > 32767.0) {
|
|
errno = ERANGE;
|
|
return 0x7FFFFFFF;
|
|
}
|
|
|
|
if (x < -32767.0) {
|
|
errno = ERANGE;
|
|
return -0x7FFFFFFF;
|
|
}
|
|
|
|
return (long)(x * 65536.0 + (x < 0 ? -0.5 : 0.5));
|
|
}
|
|
|
|
/**
|
|
* \fn double fixtof (fixed x)
|
|
* \brief Converts a fixed point value to a float point value.
|
|
*
|
|
* This function converts the specified fixed point value \a x to
|
|
* a float point value.
|
|
*
|
|
* \sa ftofix
|
|
*/
|
|
static inline double fixtof (fixed x)
|
|
{
|
|
return (double)x / 65536.0;
|
|
}
|
|
|
|
|
|
/**
|
|
* \fn fixed fixadd (fixed x, fixed y)
|
|
* \brief Returns the sum of two fixed point values.
|
|
*
|
|
* This function adds two fixed point values \a x and \a y, and
|
|
* returns the sum.
|
|
*
|
|
* \param x x,y: Two addends.
|
|
* \param y x,y: Two addends.
|
|
* \return The sum. If the result runs out of range of fixed point,
|
|
* this function sets \a errno to \a ERANGE.
|
|
*
|
|
* \sa fixsub
|
|
*/
|
|
static inline fixed fixadd (fixed x, fixed y)
|
|
{
|
|
fixed result = x + y;
|
|
|
|
if (result >= 0) {
|
|
if ((x < 0) && (y < 0)) {
|
|
errno = ERANGE;
|
|
return -0x7FFFFFFF;
|
|
}
|
|
else
|
|
return result;
|
|
}
|
|
else {
|
|
if ((x > 0) && (y > 0)) {
|
|
errno = ERANGE;
|
|
return 0x7FFFFFFF;
|
|
}
|
|
else
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixsub (fixed x, fixed y)
|
|
* \brief Subtract a fixed point value from another.
|
|
*
|
|
* This function subtracts the fixed point values \a y from the fixed
|
|
* point value \a x, and returns the difference.
|
|
*
|
|
* \param x The minuend.
|
|
* \param y The subtrahend.
|
|
*
|
|
* \return The difference. If the result runs out of range of fixed point,
|
|
* this function sets \a errno to \a ERANGE.
|
|
*
|
|
* \sa fixadd
|
|
*/
|
|
static inline fixed fixsub (fixed x, fixed y)
|
|
{
|
|
fixed result = x - y;
|
|
|
|
if (result >= 0) {
|
|
if ((x < 0) && (y > 0)) {
|
|
errno = ERANGE;
|
|
return -0x7FFFFFFF;
|
|
}
|
|
else
|
|
return result;
|
|
}
|
|
else {
|
|
if ((x > 0) && (y < 0)) {
|
|
errno = ERANGE;
|
|
return 0x7FFFFFFF;
|
|
}
|
|
else
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixmul (fixed x, fixed y)
|
|
* \brief Returns the product of two fixed point values.
|
|
*
|
|
* This function returns the product of two fixed point values \a x and \a y.
|
|
*
|
|
* \param x The faciend.
|
|
* \param y The multiplicato.
|
|
* \return The prodcut. If the result runs out of range of fixed point,
|
|
* this function sets \a errno to \a ERANGE.
|
|
*
|
|
* \sa fixdiv
|
|
*/
|
|
MG_EXPORT fixed fixmul (fixed x, fixed y);
|
|
|
|
/**
|
|
* \fn fixed fixdiv (fixed x, fixed y)
|
|
* \brief Returns the quotient of two fixed point values.
|
|
*
|
|
* This function returns the quotient of two fixed point values \a x and \a y.
|
|
*
|
|
* \param x The dividend.
|
|
* \param y The divisor.
|
|
* \return The quotient. If the result runs out of range of fixed point,
|
|
* this function sets \a errno to \a ERANGE.
|
|
*
|
|
* \sa fixmul
|
|
*/
|
|
MG_EXPORT fixed fixdiv (fixed x, fixed y);
|
|
|
|
/**
|
|
* \fn int fixceil (fixed x)
|
|
* \brief Rounds a fixed point value to the nearest integer.
|
|
*
|
|
* This function rounds the fixed point value \a x to the nearest integer
|
|
* and returns it.
|
|
*
|
|
* \return The rounded integer value.
|
|
*/
|
|
|
|
static inline int fixceil (fixed x)
|
|
{
|
|
if (x > 0x7FFF0000) {
|
|
errno = ERANGE;
|
|
return 0x7FFF;
|
|
}
|
|
|
|
x += 0xFFFF;
|
|
if (x > 0)
|
|
return (x >> 16);
|
|
else
|
|
return ~((~x) >> 16);
|
|
}
|
|
|
|
/**
|
|
* \fn fixed itofix (int x)
|
|
* \brief Converts an integer to a fixed point value.
|
|
*
|
|
* This function converts the integer \a x to a fixed point value.
|
|
*
|
|
* \sa fixtoi
|
|
*/
|
|
static inline fixed itofix (int x)
|
|
{
|
|
return x << 16;
|
|
}
|
|
|
|
/**
|
|
* \fn int fixtoi (fixed x)
|
|
* \brief Converts an fixed point value to an integer.
|
|
*
|
|
* This function converts the fixed point \a x to an integer.
|
|
*
|
|
* \sa itofix
|
|
*/
|
|
static inline int fixtoi (fixed x)
|
|
{
|
|
return (x >> 16) + ((x & 0x8000) >> 15);
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixcos (fixed x)
|
|
* \brief Returns the cosine of a fixed point.
|
|
*
|
|
* This function returns the cosine of the fixed point \a x,
|
|
* where \a x is given in radians.
|
|
*
|
|
* \sa fixacos
|
|
*/
|
|
static inline fixed fixcos (fixed x)
|
|
{
|
|
return _cos_tbl[((x + 0x4000) >> 15) & 0x1FF];
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixsin (fixed x)
|
|
* \brief Returns the sine of a fixed point.
|
|
*
|
|
* This function returns the sine of the fixed point \a x,
|
|
* where \a x is given in radians.
|
|
*
|
|
* \sa fixasin
|
|
*/
|
|
static inline fixed fixsin (fixed x)
|
|
{
|
|
return _cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF];
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixtan (fixed x)
|
|
* \brief Returns the tangent of a fixed point.
|
|
*
|
|
* This function returns the tangent of the fixed point \a x,
|
|
* where \a x is given in radians.
|
|
*
|
|
* \sa fixcos, fixsin
|
|
*/
|
|
static inline fixed fixtan (fixed x)
|
|
{
|
|
return _tan_tbl[((x + 0x4000) >> 15) & 0xFF];
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixacos (fixed x)
|
|
* \brief Calculates and returns the arc cosine of a fixed point.
|
|
*
|
|
* This function calculates the arc cosine of the fixed point \a x;
|
|
* that is the value whose cosine is \a x. If \a x falls outside
|
|
* the range -1 to 1, this function fails and \a errno is set to EDOM.
|
|
*
|
|
* \return Returns the arc cosine in radians and the value is mathematically
|
|
* defined to be between 0 and PI (inclusive).
|
|
*
|
|
* \sa fixcos
|
|
*/
|
|
static inline fixed fixacos (fixed x)
|
|
{
|
|
if ((x < -65536) || (x > 65536)) {
|
|
errno = EDOM;
|
|
return 0;
|
|
}
|
|
|
|
return _acos_tbl[(x+65536+127)>>8];
|
|
}
|
|
|
|
/**
|
|
* \fn fixed fixasin (fixed x)
|
|
* \brief Calculates and returns the arc sine of a fixed point.
|
|
*
|
|
* This function calculates the arc sine of the fixed point \a x;
|
|
* that is the value whose sine is \a x. If \a x falls outside
|
|
* the range -1 to 1, this function fails and \a errno is set to EDOM.
|
|
*
|
|
* \return Returns the arc sine in radians and the value is mathematically
|
|
* defined to be between -PI/2 and PI/2 (inclusive).
|
|
*
|
|
* \sa fixsin
|
|
*/
|
|
static inline fixed fixasin (fixed x)
|
|
{
|
|
if ((x < -65536) || (x > 65536)) {
|
|
errno = EDOM;
|
|
return 0;
|
|
}
|
|
|
|
return 0x00400000 - _acos_tbl[(x+65536+127)>>8];
|
|
}
|
|
|
|
/** @} end of fixed_math_fns */
|
|
|
|
|
|
/** @} end of global_fns */
|
|
|
|
/** @} end of fns */
|
|
|
|
#endif /* _MGHAVE_FIXED_MATH */
|
|
|
|
/* Ends C function definitions when using C++ */
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _MGUI_MGHAVE_FIXED_MATH_H */
|
|
|