2019-09-03 11:58:42 +02:00
|
|
|
//
|
|
|
|
// FloatLib.c
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Created by Slice on 20.06.2018.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "FloatLib.h"
|
|
|
|
#include "IO.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define memcpy(dest,source,count) CopyMem(dest,(void*)source,(UINTN)(count))
|
|
|
|
//#define fabsf(x) ((x >= 0.0f)?x:(-x))
|
|
|
|
#define fabsf(x) FabsF(x)
|
|
|
|
|
|
|
|
//we will assume sqrt(abs(x))
|
|
|
|
float SqrtF(float X)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
struct FloatInt {
|
|
|
|
union {
|
|
|
|
INT32 i;
|
|
|
|
float f;
|
|
|
|
} fi;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
if (X == 0.0f) {
|
|
|
|
return 0.0f;
|
|
|
|
} else if (X < 0.0f) {
|
|
|
|
X = -X;
|
|
|
|
}
|
|
|
|
// struct FloatInt Y;
|
|
|
|
float Yf;
|
|
|
|
Yf = X * 0.3f;
|
|
|
|
// Y.i = Y.i >> 1; // dirty hack - first iteration
|
|
|
|
//do six iterations
|
|
|
|
Yf = Yf * 0.5f + X / (Yf * 2.0f);
|
|
|
|
Yf = Yf * 0.5f + X / (Yf * 2.0f);
|
|
|
|
Yf = Yf * 0.5f + X / (Yf * 2.0f);
|
|
|
|
Yf = Yf * 0.5f + X / (Yf * 2.0f);
|
|
|
|
Yf = Yf * 0.5f + X / (Yf * 2.0f);
|
|
|
|
Yf = Yf * 0.5f + X / (Yf * 2.0f);
|
|
|
|
return Yf;
|
|
|
|
}
|
|
|
|
|
|
|
|
float CosF(float X);
|
|
|
|
|
|
|
|
//we know sin is odd
|
|
|
|
float SinF(float X)
|
|
|
|
{
|
|
|
|
INTN Period;
|
|
|
|
float X2;
|
|
|
|
float Sign = 1.0f;
|
|
|
|
|
|
|
|
if (X < 0.0f) {
|
|
|
|
X = -X;
|
|
|
|
Sign = -1.0f;
|
|
|
|
}
|
|
|
|
Period = (INTN)(X / PI2);
|
|
|
|
X = X - Period * PI2;
|
|
|
|
if (X > PI) {
|
|
|
|
X = X - PI;
|
|
|
|
Sign *= -1.0f;
|
|
|
|
}
|
|
|
|
if (X > PI5) {
|
|
|
|
X = PI - X;
|
|
|
|
}
|
|
|
|
if (X > PI * 0.25f) {
|
|
|
|
return (Sign*CosF(PI5 - X));
|
|
|
|
}
|
|
|
|
X2 = X * X;
|
|
|
|
return (Sign*(X - X2 * X / 6.0f + X2 * X2 * X / 120.0f));
|
|
|
|
}
|
|
|
|
|
|
|
|
//we know cos is even
|
|
|
|
float CosF(float X)
|
|
|
|
{
|
|
|
|
INTN Period;
|
|
|
|
float Sign = 1.0f;
|
|
|
|
float X2;
|
|
|
|
|
|
|
|
if (X < 0.0f) {
|
|
|
|
X = -X;
|
|
|
|
}
|
|
|
|
Period = (INTN)(X / PI2);
|
|
|
|
X = X - Period * PI2;
|
|
|
|
if (X > PI) {
|
|
|
|
X = PI - X;
|
|
|
|
Sign = -1.0f;
|
|
|
|
}
|
|
|
|
if (X > PI5) {
|
|
|
|
X = PI - X;
|
|
|
|
Sign *= -1.0f;
|
|
|
|
}
|
|
|
|
if (X > PI * 0.25f) {
|
|
|
|
return (Sign*SinF(PI5 - X));
|
|
|
|
}
|
|
|
|
X2 = X * X;
|
|
|
|
return (Sign * (1.0f - X2 * 0.5f + X2 * X2 / 24.0f));
|
|
|
|
}
|
|
|
|
|
|
|
|
float TanF(float X)
|
|
|
|
{
|
|
|
|
float Y = CosF(X);
|
|
|
|
if (Y == 0.0f) {
|
|
|
|
Y = 1.0e-37f;
|
|
|
|
}
|
|
|
|
return SinF(X)/Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
float PowF(float x, INTN n)
|
|
|
|
{
|
|
|
|
float Data = x;
|
|
|
|
if (n > 0) {
|
|
|
|
while (n > 0) {
|
|
|
|
Data *= 10.0f;
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (n < 0) {
|
|
|
|
Data *= 0.1f;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Data;
|
|
|
|
}
|
|
|
|
|
|
|
|
float CeilF(float X)
|
|
|
|
{
|
|
|
|
INT32 I = (INT32)X;
|
|
|
|
return (float)(++I);
|
|
|
|
}
|
|
|
|
|
|
|
|
float FloorF(float X)
|
|
|
|
{
|
|
|
|
INT32 I = (INT32)X;
|
|
|
|
return (float)I;
|
|
|
|
}
|
|
|
|
|
|
|
|
float ModF(float X, float Y)
|
|
|
|
{
|
|
|
|
INT32 I = (INT32)(X / Y);
|
|
|
|
return (X - (float)I * Y);
|
|
|
|
}
|
|
|
|
|
|
|
|
float AcosF(float X)
|
|
|
|
{
|
|
|
|
float X2 = X * X;
|
|
|
|
float res = 0.f, Y = 0.f;
|
|
|
|
INTN Sign = 0;
|
|
|
|
|
|
|
|
if (X2 < 0.3f) {
|
|
|
|
Y = X * (1.0f + X2 / 6.0f + X2 * X2 * (3.0f / 40.0f));
|
|
|
|
return (PI5 - Y);
|
|
|
|
} else if (X2 >= 1.0f) {
|
|
|
|
return 0.0f;
|
|
|
|
} else {
|
|
|
|
if (X < 0) {
|
|
|
|
X = -X;
|
|
|
|
Sign = 1;
|
|
|
|
}
|
|
|
|
Y = 1.0f - X; //for X ~ 1
|
|
|
|
X2 = Y * (2.0f + Y * (1.0f / 3.0f + Y * (4.0f / 45.0f + Y / 35.0f))); //Dwight, form.508
|
|
|
|
res = SqrtF(X2);
|
|
|
|
if (Sign) {
|
|
|
|
res = PI - res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
float AtanF(float X) //assume 0.0 < X < 1.0
|
|
|
|
{
|
|
|
|
float Eps = 1.0e-8f;
|
|
|
|
int i = 1;
|
|
|
|
float X2 = X * X;
|
|
|
|
float D = X;
|
|
|
|
float Y = 0.f;
|
|
|
|
float sign = 1.0f;
|
|
|
|
|
|
|
|
if (X > 0.5f) {
|
|
|
|
//make here arctg(1-x)
|
|
|
|
X = 1.0f - D;
|
|
|
|
X2 = X * X;
|
|
|
|
Y = PI4 - X * 0.5f - X2 * 0.25f - X * X2 * 0.25f * ( 1.f / 3.f - X2 * (0.1f + X / 12.f + X2 / 28.f));
|
|
|
|
} else {
|
|
|
|
// Y = X * (1 - X2 * ( 1.0f / 3.0f - X2 * (1.0f / 5.0f - X2 * ( 1.0f / 7.0f))));
|
|
|
|
for (i = 1; i < 50; i += 2) {
|
|
|
|
Y += (D * sign / i);
|
|
|
|
D *= X2;
|
|
|
|
if (D < Eps) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sign = - sign;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Atan2F(float Y, float X) //result -pi..+pi
|
|
|
|
{
|
|
|
|
float sign = (((X >= 0.0f) && (Y < 0.0f)) ||
|
|
|
|
((X < 0.0f) && (Y >= 0.0f)))?-1.0f:1.0f;
|
|
|
|
float PP = 0.f;
|
|
|
|
float res = 0.f;
|
|
|
|
//1,1 = pi4 1,-1=pi34 -1,-1=-pi34 -1,1=-pi4
|
|
|
|
if (X < 0.f) {
|
|
|
|
PP = PI;
|
|
|
|
}
|
|
|
|
X = (X >= 0.0f)?X:(-X);
|
|
|
|
Y = (Y >= 0.0f)?Y:(-Y);
|
|
|
|
if (Y < X) {
|
|
|
|
res = AtanF(Y / X);
|
|
|
|
} else if (X == 0.0f) {
|
|
|
|
res = PI5;
|
|
|
|
} else {
|
|
|
|
res = (PI5 - AtanF(X / Y));
|
|
|
|
}
|
|
|
|
return sign * (res - PP);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
RETURN_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AsciiStrDecimalToUintnS (
|
|
|
|
IN CONST CHAR8 *String,
|
|
|
|
OUT CHAR8 **EndPointer, OPTIONAL
|
|
|
|
OUT UINTN *Data
|
|
|
|
);
|
|
|
|
*/
|
|
|
|
RETURN_STATUS
|
|
|
|
AsciiStrToFloat(IN CONST CHAR8 *String,
|
|
|
|
OUT CHAR8 **EndPointer, OPTIONAL
|
|
|
|
OUT float *Data)
|
|
|
|
{
|
|
|
|
UINTN Temp = 0;
|
|
|
|
INTN Sign = 1;
|
|
|
|
float Mantissa, Ftemp;
|
|
|
|
CHAR8* TmpStr = NULL;
|
|
|
|
RETURN_STATUS Status = RETURN_SUCCESS;
|
|
|
|
if (EndPointer != NULL) {
|
|
|
|
*EndPointer = (CHAR8 *) String;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Ignore the pad spaces (space or tab)
|
|
|
|
//
|
|
|
|
while ((*String == ' ') || (*String == '\t')) {
|
|
|
|
String++;
|
|
|
|
}
|
|
|
|
if (*String == '-') {
|
|
|
|
Sign = -1;
|
|
|
|
String++;
|
|
|
|
} else if (*String == '+') {
|
|
|
|
String++;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AsciiStrDecimalToUintnS(String, &TmpStr, &Temp);
|
|
|
|
Mantissa = (float)Temp;
|
|
|
|
String = TmpStr;
|
|
|
|
if (*String == '.') {
|
|
|
|
String++;
|
|
|
|
Temp = 0;
|
|
|
|
Status = AsciiStrDecimalToUintnS(String, &TmpStr, &Temp);
|
|
|
|
Ftemp = (float)Temp;
|
|
|
|
while (String != TmpStr) {
|
|
|
|
if (*String == '\0') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Ftemp *= 0.1f;
|
|
|
|
String++;
|
|
|
|
}
|
|
|
|
Mantissa += Ftemp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*String == 'E') || (*String == 'e')){
|
|
|
|
INTN ExpSign = 1;
|
|
|
|
String++;
|
|
|
|
if (*String == '-') {
|
|
|
|
ExpSign = -1;
|
|
|
|
String++;
|
|
|
|
} else if (*String == '+') {
|
|
|
|
String++;
|
|
|
|
}
|
|
|
|
Temp = 0;
|
|
|
|
Status = AsciiStrDecimalToUintnS(String, &TmpStr, &Temp);
|
|
|
|
if (Status == RETURN_SUCCESS) {
|
|
|
|
Ftemp = PowF(10.0f, ExpSign * Temp);
|
|
|
|
Mantissa *= Ftemp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*Data = (Sign > 0)?Mantissa:-Mantissa;
|
|
|
|
if (EndPointer != NULL) {
|
|
|
|
*EndPointer = (CHAR8 *) TmpStr;
|
|
|
|
}
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
//Slice - this is my replacement for standard
|
|
|
|
qsort(void* Array, int Num, size_t Size,
|
|
|
|
int (*compare)(void* a, void* b))
|
|
|
|
usage qsort(Array, Num, sizeof(*Array), compare);
|
|
|
|
where for example
|
|
|
|
int compare(void *a, void* b)
|
|
|
|
{
|
|
|
|
if (*(float*)a > *(float*)b) return 1;
|
|
|
|
if (*(float*)a < *(float*)b) return -1;
|
|
|
|
return -0;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
#if 0
|
|
|
|
VOID QuickSort(VOID* Array, INTN Low, INTN High, INTN Size, INTN (*compare)(CONST VOID* a, CONST VOID* b)) {
|
|
|
|
INTN i = Low, j = High;
|
|
|
|
VOID *Med, *Temp;
|
|
|
|
Med = Array + ((Low + High) / 2) * Size; // Central element, just pointer
|
2019-12-21 01:31:49 +01:00
|
|
|
Temp = (__typeof__(Temp))AllocatePool(Size);
|
2019-09-03 11:58:42 +02:00
|
|
|
// Sort around center
|
|
|
|
while (i <= j)
|
|
|
|
{
|
|
|
|
while (compare((const void*)(Array+i*Size), (const void*)Med) == -1) i++;
|
|
|
|
while (compare((const void*)(Array+j*Size), (const void*)Med) == 1) j--;
|
|
|
|
// Change
|
|
|
|
if (i <= j) {
|
|
|
|
memcpy(Temp, Array+i*Size, Size);
|
|
|
|
memcpy(Array+i*Size, Array+j*Size, Size);
|
|
|
|
memcpy(Array+j*Size, Temp, Size);
|
|
|
|
i++;
|
|
|
|
j--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FreePool(Temp);
|
|
|
|
// Recursion
|
|
|
|
if (j > Low) QuickSort(Array, Low, j, Size, compare);
|
|
|
|
if (High > i) QuickSort(Array, i, High, Size, compare);
|
|
|
|
}
|
|
|
|
|
|
|
|
//S must be allocated before use
|
|
|
|
VOID AsciiSPrintFloat(CHAR8* S, INTN N, CHAR8* F, float X)
|
|
|
|
{
|
|
|
|
INTN I, Fract;
|
|
|
|
float D;
|
|
|
|
if (!S) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
I = (INTN)X;
|
|
|
|
D = (float)I;
|
|
|
|
Fract = fabsf((X - D) * 1000000.0f);
|
|
|
|
AsciiSPrint(S, N, "%D.%06D", I, (INTN)Fract);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CHAR16* PoolPrintFloat(float X)
|
|
|
|
{
|
|
|
|
INTN I, Fract;
|
|
|
|
CHAR8 S = ' ';
|
|
|
|
float D;
|
|
|
|
I = (INTN)X;
|
|
|
|
D = (float)I;
|
|
|
|
if (I == 0 && X < 0) {
|
|
|
|
S = '-';
|
|
|
|
}
|
|
|
|
Fract = (INTN)fabsf((X - D) * 1000000.0f);
|
|
|
|
return PoolPrint(L"%c%d.%06d", S, I, Fract);
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT32 seed = 12345;
|
|
|
|
float rndf() //expected 0..1
|
|
|
|
{
|
|
|
|
// UINT16 Rand = 0;
|
|
|
|
// AsmRdRand16(&Rand); //it's a pity panic
|
|
|
|
// return (float)Rand / 65536.f;
|
|
|
|
seed = seed * 214013 + 2531011;
|
|
|
|
float x = (float)seed / 4294967296.0f;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dither(float x, int level)
|
|
|
|
{
|
|
|
|
if (!level) {
|
|
|
|
return (int)x;
|
|
|
|
}
|
|
|
|
int i = (int)(x) * level; //5.1 * 4 = 20.4, 5.8 * 4 = 23.2|i=20
|
|
|
|
float dx = x * level - (float)(i); //0.4, 3.2
|
|
|
|
i /= level;
|
|
|
|
if (dx > rndf() * level) {
|
|
|
|
i += (int)((0.9999f+rndf())*level); //because rndf has mean value 0.5, but (int)rnd=0
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
//there is
|
|
|
|
#if 0
|
|
|
|
BOOLEAN
|
|
|
|
EFIAPI
|
|
|
|
AsmRdRand16 (
|
|
|
|
OUT UINT16 *Rand
|
|
|
|
);
|
|
|
|
#endif
|