2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
gbx_math.c
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
(c) 2000-2009 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
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
|
2009-08-17 12:41:51 +02:00
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 17:41:49 +01:00
|
|
|
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, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#define __GBX_MATH_C
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
#include "gb_common.h"
|
|
|
|
#include "gbx_math.h"
|
|
|
|
|
|
|
|
/* This is a twisted generalized feedback shift register
|
|
|
|
that generates pseudo-random numbers.
|
|
|
|
|
|
|
|
Source code from the paper of Yann Guidon
|
|
|
|
in March edition of GNU/Linux Magazine France
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define CRC32_STD 0x04C11DB7
|
|
|
|
#define GFSR_SIZE 15
|
|
|
|
|
|
|
|
static uint GFSR_table[GFSR_SIZE];
|
|
|
|
static uint GFSR_temp;
|
|
|
|
static uint GFSR_index;
|
|
|
|
|
|
|
|
static void GFSR_init(uint seed)
|
|
|
|
{
|
|
|
|
int i = 0, j;
|
|
|
|
uint t = seed;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
t ^= (t >> 5) ^ (t << 1);
|
|
|
|
j = t >> 31;
|
|
|
|
t <<= 1;
|
|
|
|
if (j)
|
|
|
|
t ^= CRC32_STD;
|
|
|
|
GFSR_table[i++] = t;
|
|
|
|
}
|
|
|
|
while (i < GFSR_SIZE);
|
|
|
|
|
|
|
|
GFSR_temp = GFSR_table[GFSR_SIZE - 1];
|
|
|
|
GFSR_index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint GFSR_random(void)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
|
|
|
|
GFSR_temp ^= GFSR_table[GFSR_index];
|
|
|
|
|
|
|
|
t = GFSR_temp;
|
|
|
|
GFSR_temp <<= 1;
|
|
|
|
if (t < 0)
|
|
|
|
GFSR_temp ^= CRC32_STD;
|
|
|
|
|
|
|
|
GFSR_table[GFSR_index] = GFSR_temp;
|
|
|
|
|
|
|
|
if (++GFSR_index >= GFSR_SIZE)
|
|
|
|
GFSR_index = 0;
|
|
|
|
|
|
|
|
return GFSR_temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
//static long seed = 1;
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
double frac(double x)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
x = fabs(x);
|
|
|
|
return x - floor(x);
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
int lsgn(int x)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
return ((x > 0) ? 1 : ((x < 0) ? (-1) : 0));
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
int llsgn(int64_t x)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
return ((x > 0) ? 1 : ((x < 0) ? (-1) : 0));
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
/*int64_t llabs(int64_t x)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
return ((x < 0) ? (-x) : x);
|
2008-01-17 22:39:26 +01:00
|
|
|
}*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
int fsgn(double x)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
return ((x > 0) ? 1 : ((x < 0) ? (-1) : 0));
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
double fix(double x)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
if (x >= 0)
|
|
|
|
return floor(x);
|
|
|
|
else
|
|
|
|
return -floor(fabs(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
double frexp10(double x, int *exp)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
long double l, f;
|
|
|
|
|
|
|
|
if (x == 0.0)
|
|
|
|
{
|
|
|
|
*exp = 0;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
l = modfl(log10l(fabsl(x)), &f);
|
2008-03-21 02:15:44 +01:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
if (f == 0.0)
|
|
|
|
l = x;
|
|
|
|
else
|
|
|
|
l = powl(10, l);
|
|
|
|
|
|
|
|
if (x < 0.0) l = -l;
|
|
|
|
|
|
|
|
while (l >= 1.0)
|
|
|
|
{
|
|
|
|
l /= 10.0;
|
|
|
|
f++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*exp = (int)f;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
void randomize(bool set, uint seed)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
if (!set && gettimeofday(&tv, NULL) == 0)
|
|
|
|
seed = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
|
|
|
|
|
//GFSR_init(0x1A2B3C4D);
|
|
|
|
GFSR_init(seed);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
double rnd(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
/*seed = 16807L * (seed % 127773L) - 2836L * (seed / 127773L);
|
|
|
|
if (seed <= 0) seed += 2147483647;
|
|
|
|
|
|
|
|
return (double)seed / 2147483648.0;*/
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
uint64_t val;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
val = GFSR_random();
|
|
|
|
val <<= 32;
|
|
|
|
val |= GFSR_random();
|
|
|
|
|
2009-05-15 19:57:29 +02:00
|
|
|
return (double)val / 18446744073709551616.0; //0xFFFFFFFFFFFFFFFFULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-24 03:02:05 +01:00
|
|
|
#if defined(OS_FREEBSD) || defined(OS_OPENBSD)
|
|
|
|
|
|
|
|
double exp10(double x)
|
|
|
|
{
|
|
|
|
return pow(10, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
double log2(double x)
|
|
|
|
{
|
|
|
|
return log(x) / M_LN2;
|
|
|
|
}
|
|
|
|
|
|
|
|
double exp2(double x)
|
|
|
|
{
|
|
|
|
return pow(2, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-03-05 02:20:09 +01:00
|
|
|
#if defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(ARCH_ARM) || defined(OS_CYGWIN)
|
2009-12-24 03:02:05 +01:00
|
|
|
|
|
|
|
long double log10l(long double x)
|
|
|
|
{
|
|
|
|
return log10((double) x);
|
|
|
|
}
|
|
|
|
|
|
|
|
long double fabsl(long double x)
|
|
|
|
{
|
|
|
|
return fabs((double) x);
|
|
|
|
}
|
|
|
|
|
|
|
|
long double powl(long double x, long double y)
|
|
|
|
{
|
|
|
|
return pow((double) x, (double) y);
|
|
|
|
}
|
|
|
|
|
|
|
|
long double modfl(long double x, long double *iptr)
|
|
|
|
{
|
|
|
|
double val;
|
|
|
|
return modf((double)x, &val);
|
|
|
|
*iptr = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
void MATH_init(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
randomize(FALSE, 0);
|
|
|
|
}
|