new float.c from the Small SDK
This commit is contained in:
parent
8d3dbd803c
commit
6b506b5fa5
|
@ -4,93 +4,378 @@
|
||||||
* Written by Greg Garner (gmg@artran.com)
|
* Written by Greg Garner (gmg@artran.com)
|
||||||
* This file may be freely used. No warranties of any kind.
|
* This file may be freely used. No warranties of any kind.
|
||||||
*
|
*
|
||||||
|
* CHANGES -
|
||||||
|
* 2002-08-27: Basic conversion of source from C++ to C by Adam D. Moss
|
||||||
|
* <adam@gimp.org> <aspirin@icculus.org>
|
||||||
|
* 2003-08-29: Removal of the dynamic memory allocation and replacing two
|
||||||
|
* type conversion functions by macros, by Thiadmer Riemersma
|
||||||
|
* 2003-09-22: Moved the type conversion macros to AMX.H, and simplifications
|
||||||
|
* of some routines, by Thiadmer Riemersma
|
||||||
|
* 2003-11-24: A few more native functions (geometry), plus minor modifications,
|
||||||
|
* mostly to be compatible with dynamically loadable extension
|
||||||
|
* modules, by Thiadmer Riemersma
|
||||||
|
*/
|
||||||
|
#include <stdlib.h> /* for atof() */
|
||||||
|
#include <stdio.h> /* for NULL */
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "amx.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined __BORLANDC__
|
||||||
|
#pragma resource "amxFloat.res"
|
||||||
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#define PI 3.1415926535897932384626433832795
|
||||||
#include <stdlib.h>
|
|
||||||
#include <extdll.h>
|
|
||||||
#include <meta_api.h>
|
|
||||||
#include "amxmod.h"
|
|
||||||
|
|
||||||
inline cell FloatToCell(float fValue) {
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
return *(cell *)((void *)&fValue);
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_float(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = long value to convert to a float
|
||||||
|
*/
|
||||||
|
float fValue;
|
||||||
|
|
||||||
|
/* Convert to a float. Calls the compilers long to float conversion. */
|
||||||
|
fValue = (float) params[1];
|
||||||
|
|
||||||
|
/* Return the cell. */
|
||||||
|
return amx_ftoc(fValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CellToFloat(cell cellValue){
|
/******************************************************************/
|
||||||
return *(float *)((void *)&cellValue);
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
static cell AMX_NATIVE_CALL n_floatstr(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = virtual string address to convert to a float
|
||||||
|
*/
|
||||||
|
char szSource[60];
|
||||||
|
cell *pString;
|
||||||
|
float fNum;
|
||||||
|
int nLen;
|
||||||
|
|
||||||
|
/* They should have sent us 1 cell. */
|
||||||
|
assert(params[0]/sizeof(cell)==1);
|
||||||
|
|
||||||
|
/* Get the real address of the string. */
|
||||||
|
amx_GetAddr(amx,params[1],&pString);
|
||||||
|
|
||||||
|
/* Find out how long the string is in characters. */
|
||||||
|
amx_StrLen(pString, &nLen);
|
||||||
|
if (nLen == 0 || nLen >= sizeof szSource)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Now convert the Small String into a C type null terminated string */
|
||||||
|
amx_GetString(szSource, pString);
|
||||||
|
|
||||||
|
/* Now convert this to a float. */
|
||||||
|
fNum = (float)atof(szSource);
|
||||||
|
|
||||||
|
return amx_ftoc(fNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _float(AMX *,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
return FloatToCell((float)params[1]);
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatmul(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1
|
||||||
|
* params[2] = float operand 2
|
||||||
|
*/
|
||||||
|
float fRes = amx_ctof(params[1]) * amx_ctof(params[2]);
|
||||||
|
return amx_ftoc(fRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _floatstr(AMX *amx,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
int len;
|
#pragma argsused
|
||||||
return FloatToCell((float)atof(get_amxstring(amx,params[1],0,len)));
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatdiv(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float dividend (top)
|
||||||
|
* params[2] = float divisor (bottom)
|
||||||
|
*/
|
||||||
|
float fRes = amx_ctof(params[1]) / amx_ctof(params[2]);
|
||||||
|
return amx_ftoc(fRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _floatmul(AMX *,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
return FloatToCell(CellToFloat(params[1]) * CellToFloat(params[2]));
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatadd(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1
|
||||||
|
* params[2] = float operand 2
|
||||||
|
*/
|
||||||
|
float fRes = amx_ctof(params[1]) + amx_ctof(params[2]);
|
||||||
|
return amx_ftoc(fRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _floatdiv(AMX *,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
return FloatToCell(CellToFloat(params[1]) / CellToFloat(params[2]));
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatsub(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1
|
||||||
|
* params[2] = float operand 2
|
||||||
|
*/
|
||||||
|
float fRes = amx_ctof(params[1]) - amx_ctof(params[2]);
|
||||||
|
return amx_ftoc(fRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _floatadd(AMX *,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
return FloatToCell(CellToFloat(params[1]) + CellToFloat(params[2]));
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
/* Return fractional part of float */
|
||||||
|
static cell AMX_NATIVE_CALL n_floatfract(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
fA = fA - (float)(floor((double)fA));
|
||||||
|
return amx_ftoc(fA);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _floatsub(AMX *,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
return FloatToCell(CellToFloat(params[1]) - CellToFloat(params[2]));
|
#pragma argsused
|
||||||
}
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
/* Return integer part of float, rounded */
|
||||||
|
static cell AMX_NATIVE_CALL n_floatround(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand
|
||||||
|
* params[2] = Type of rounding (long)
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
|
||||||
static cell _floatfract(AMX *,cell *params){
|
switch (params[2])
|
||||||
float fA = CellToFloat(params[1]);
|
{
|
||||||
fA -= (float)(floor((double)fA));
|
case 1: /* round downwards (truncate) */
|
||||||
return FloatToCell(fA);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell _floatround(AMX *,cell *params){
|
|
||||||
float fA = CellToFloat(params[1]);
|
|
||||||
switch (params[2]) {
|
|
||||||
case 1:
|
|
||||||
fA = (float)(floor((double)fA));
|
fA = (float)(floor((double)fA));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2: /* round upwards */
|
||||||
float fValue;
|
fA = (float)(ceil((double)fA));
|
||||||
fValue = (float)(floor((double)fA));
|
|
||||||
if ( (fA>=0) && ((fA-fValue)!=0) )
|
|
||||||
fValue++;
|
|
||||||
fA = fValue;
|
|
||||||
break;
|
break;
|
||||||
default:
|
case 3: /* round towards zero */
|
||||||
|
if ( fA>=0.0 )
|
||||||
|
fA = (float)(floor((double)fA));
|
||||||
|
else
|
||||||
|
fA = (float)(ceil((double)fA));
|
||||||
|
break;
|
||||||
|
default: /* standard, round to nearest */
|
||||||
fA = (float)(floor((double)fA+.5));
|
fA = (float)(floor((double)fA+.5));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (long)fA;
|
return (long)fA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell _floatcmp(AMX *,cell *params){
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
float fA = CellToFloat(params[1]);
|
#pragma argsused
|
||||||
float fB = CellToFloat(params[2]);
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatcmp(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1
|
||||||
|
* params[2] = float operand 2
|
||||||
|
*/
|
||||||
|
float fA, fB;
|
||||||
|
|
||||||
|
fA = amx_ctof(params[1]);
|
||||||
|
fB = amx_ctof(params[2]);
|
||||||
if (fA == fB)
|
if (fA == fB)
|
||||||
return 0;
|
return 0;
|
||||||
else if (fA>fB)
|
else if (fA>fB)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatsqroot(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
fA = (float)sqrt(fA);
|
||||||
|
if (fA < 0)
|
||||||
|
return amx_RaiseError(amx, AMX_ERR_DOMAIN);
|
||||||
|
return amx_ftoc(fA);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatpower(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1 (base)
|
||||||
|
* params[2] = float operand 2 (exponent)
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
float fB = amx_ctof(params[2]);
|
||||||
|
fA = (float)pow(fA, fB);
|
||||||
|
return amx_ftoc(fA);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatlog(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1 (value)
|
||||||
|
* params[2] = float operand 2 (base)
|
||||||
|
*/
|
||||||
|
float fValue = amx_ctof(params[1]);
|
||||||
|
float fBase = amx_ctof(params[2]);
|
||||||
|
if (fValue <= 0.0 || fBase <= 0)
|
||||||
|
return amx_RaiseError(amx, AMX_ERR_DOMAIN);
|
||||||
|
if (fBase == 10.0) // ??? epsilon
|
||||||
|
fValue = (float)log10(fValue);
|
||||||
|
else
|
||||||
|
fValue = (float)(log(fValue) / log(fBase));
|
||||||
|
return amx_ftoc(fValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ToRadians(float angle, int radix)
|
||||||
|
{
|
||||||
|
switch (radix)
|
||||||
|
{
|
||||||
|
case 1: /* degrees, sexagesimal system (technically: degrees/minutes/seconds) */
|
||||||
|
return (float)(angle * PI / 180.0);
|
||||||
|
case 2: /* grades, centesimal system */
|
||||||
|
return (float)(angle * PI / 200.0);
|
||||||
|
default: /* assume already radian */
|
||||||
|
return angle;
|
||||||
|
} /* switch */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatsin(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1 (angle)
|
||||||
|
* params[2] = float operand 2 (radix)
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
fA = ToRadians(fA, params[2]);
|
||||||
|
fA = sinf(fA); // PM: using the float version of sin
|
||||||
|
return amx_ftoc(fA);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatcos(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1 (angle)
|
||||||
|
* params[2] = float operand 2 (radix)
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
fA = ToRadians(fA, params[2]);
|
||||||
|
fA = cosf(fA); // PM: using the float version of cos
|
||||||
|
return amx_ftoc(fA);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floattan(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* params[0] = number of bytes
|
||||||
|
* params[1] = float operand 1 (angle)
|
||||||
|
* params[2] = float operand 2 (radix)
|
||||||
|
*/
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
fA = ToRadians(fA, params[2]);
|
||||||
|
fA = tanf(fA); // PM: using the float version of tan
|
||||||
|
return amx_ftoc(fA);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
/******************************************************************/
|
||||||
|
static cell AMX_NATIVE_CALL n_floatabs(AMX *amx,cell *params)
|
||||||
|
{
|
||||||
|
float fA = amx_ctof(params[1]);
|
||||||
|
fA = (fA >= 0) ? fA : -fA;
|
||||||
|
return amx_ftoc(fA);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMX_NATIVE_INFO float_Natives[] = {
|
AMX_NATIVE_INFO float_Natives[] = {
|
||||||
{ "float", _float },
|
{ "float", n_float },
|
||||||
{ "floatstr", _floatstr },
|
{ "floatstr", n_floatstr },
|
||||||
{ "floatmul", _floatmul },
|
{ "floatmul", n_floatmul },
|
||||||
{ "floatdiv", _floatdiv },
|
{ "floatdiv", n_floatdiv },
|
||||||
{ "floatadd", _floatadd },
|
{ "floatadd", n_floatadd },
|
||||||
{ "floatsub", _floatsub },
|
{ "floatsub", n_floatsub },
|
||||||
{ "floatfract", _floatfract},
|
{ "floatfract", n_floatfract },
|
||||||
{ "floatround", _floatround},
|
{ "floatround", n_floatround },
|
||||||
{ "floatcmp", _floatcmp},
|
{ "floatcmp", n_floatcmp },
|
||||||
{ NULL, NULL }
|
{ "floatsqroot", n_floatsqroot},
|
||||||
|
{ "floatpower", n_floatpower },
|
||||||
|
{ "floatlog", n_floatlog },
|
||||||
|
{ "floatsin", n_floatsin },
|
||||||
|
{ "floatcos", n_floatcos },
|
||||||
|
{ "floattan", n_floattan },
|
||||||
|
{ "floatabs", n_floatabs },
|
||||||
|
{ NULL, NULL } /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int AMXEXPORT amx_FloatInit(AMX *amx)
|
||||||
|
{
|
||||||
|
return amx_Register(amx,float_Natives,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||||
|
#pragma argsused
|
||||||
|
#endif
|
||||||
|
int AMXEXPORT amx_FloatCleanup(AMX *amx)
|
||||||
|
{
|
||||||
|
return AMX_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user