PDA

Ver la versión completa : Libreria de matematicas en punto fijo



Damizean
15/08/2005, 09:43
Ahi teneis una pequeña lib de Fixed Point :3

Si quereis usar variables de 64 bits (long long), definid USE_64_BITS. No es 100% precisa pero rula bastante bien :3


/* File : fixed.h
* Autor : Damizean
* Description : Header for the fixed-point maths library.
* Last update : 14 / 08 / 2005
*/

#ifndef FIXED_H
#define FIXED_H

//--- Declarations -------------------------
#ifdef USE_64_BITS
#define fixed long long
#define fixedshifts 24
#else
#define fixed long
#define fixedshifts 12
#endif

extern fixed MATHS_PI; // 3.1415863037109375
extern fixed MATHS_PI_OVER_2; // 1.57079315185546875
extern fixed MATHS_E; // 2.7182769775390625

extern fixed MATHS_SINK1; // 0.007598876953125
extern fixed MATHS_SINK2; // 0.166046142578125

extern fixed MATHS_COSK1; // 0.0355224609375
extern fixed MATHS_COSK2; // 0.4966888427734375

extern fixed MATHS_TANK1; // 0.2032928466796875
extern fixed MATHS_TANK2; // 0.317535400390625


//--- Methods ------------------------------
void maths_init ();

fixed int_to_fixed ( int value );
fixed float_to_fixed ( float value );
fixed double_to_fixed ( double value );

int fixed_to_int ( fixed value );
float fixed_to_float ( fixed value );
double fixed_to_double ( fixed value );

fixed fixed_add ( fixed pFixed1, fixed pFixed2 );
fixed fixed_sub ( fixed pFixed1, fixed pFixed2 );
fixed fixed_mul ( fixed pFixed1, fixed pFixed2 );
fixed fixed_div ( fixed pFixed1, fixed pFixed2 );

fixed fixed_degtorad ( fixed value );
fixed fixed_radtodeg ( fixed value );

fixed fixed_sin ( fixed value );
fixed fixed_cos ( fixed value );
fixed fixed_tan ( fixed value );
fixed fixed_sqr ( fixed value );
fixed fixed_sqrt ( fixed value );

#endif /* FIXED_H */


/* File : fixed.c
* Autor : Damizean
* Description : Fixed-point maths library.
* Last update : 14 / 08 / 2005
*/

#include "fixed.h"
#include <math.h>

// --- Define variables -----------------------------------------
fixed MATHS_PI;
fixed MATHS_PI_OVER_2;
fixed MATHS_E;

fixed MATHS_SINK1;
fixed MATHS_SINK2;

fixed MATHS_COSK1;
fixed MATHS_COSK2;

fixed MATHS_TANK1;
fixed MATHS_TANK2;

void maths_init ()
{
// --- Init math vars -------
MATHS_PI = double_to_fixed ( 3.14159265f );
MATHS_PI_OVER_2= double_to_fixed ( 1.57079 );
MATHS_E = double_to_fixed ( 2.71827 );

MATHS_SINK1 = double_to_fixed ( 0.00759 );
MATHS_SINK2 = double_to_fixed ( 0.16604 );

MATHS_COSK1 = double_to_fixed ( 0.03552 );
MATHS_COSK2 = double_to_fixed ( 0.49668 );

MATHS_TANK1 = double_to_fixed ( 0.20329 );
MATHS_TANK2 = double_to_fixed ( 0.31753 );
}

// --- Convert variables to fixed point -------------------------
fixed int_to_fixed ( int value )
{
return (fixed) ( value << fixedshifts );
}

fixed float_to_fixed ( float value )
{
return (fixed) ((float) value * ((fixed) 1 << fixedshifts ) );
}

fixed double_to_fixed ( double value )
{
return (fixed) ((double) value * ((fixed) 1 << fixedshifts ) );
}

// --- Convert fixed point to other variables -----------------
int fixed_to_int ( fixed value )
{
return (int) ( value >> fixedshifts );
}

float fixed_to_float ( fixed value )
{
return ( (float) value / (float) ((fixed) 1 << fixedshifts ) );
}

double fixed_to_double ( fixed value )
{
return ( (double) value / (double) ((fixed) 1 << fixedshifts ) );
}

// --- Operations ---------------------------------------
fixed fixed_add ( fixed pFixed1, fixed pFixed2 )
{
return ( pFixed1 + pFixed2 );
}

fixed fixed_sub ( fixed pFixed1, fixed pFixed2 )
{
return ( pFixed1 - pFixed2 );
}

fixed fixed_mul ( fixed pFixed1, fixed pFixed2 )
{
long long tmp;
tmp = ((pFixed1 * pFixed2 ) >> fixedshifts);
return (fixed) tmp;
}

fixed fixed_div ( fixed pFixed1, fixed pFixed2 )
{
long long tmp;
tmp = (pFixed1 << fixedshifts) / pFixed2;
return (fixed) tmp;
}

// --- Others -------------------------------------------
fixed fixed_degtorad ( fixed value )
{
return fixed_mul( value, fixed_div( MATHS_PI,int_to_fixed( 180) ) );
}

fixed fixed_radtodeg ( fixed value )
{
return fixed_mul( value, fixed_div( int_to_fixed( 180 ), MATHS_PI ) );
}

fixed fixed_sin ( fixed value )
{
fixed sign, sqr, result;
sign = 1;

// ---- Set up the range ----------------------
if ( (value > MATHS_PI_OVER_2 ) && ( value <= MATHS_PI ))
{
value = MATHS_PI - value;
} else if ((value > MATHS_PI) && (value <= (MATHS_PI + MATHS_PI_OVER_2)))
{
value = value - MATHS_PI;
sign = -1;
} else if (value > (MATHS_PI + MATHS_PI_OVER_2))
{
value = (MATHS_PI<<1)-value;
sign = -1;
}

// ----- Calculate ----------------------------
sqr = fixed_sqr ( value );
result = MATHS_SINK1;
result = fixed_mul ( result, sqr );
result -= MATHS_SINK2;
result = fixed_mul ( result, sqr );
result += (1 << fixedshifts);
result = fixed_mul ( result, value );

return sign * result;
}

fixed fixed_cos ( fixed value )
{
fixed sign, sqr, result;
sign = 1;

// ---- Set up the range ----------------------
if ( (value > MATHS_PI_OVER_2 ) && ( value <= MATHS_PI ))
{
value = MATHS_PI - value;
sign = -1;
} else if ((value > MATHS_PI_OVER_2) && (value <= (MATHS_PI + MATHS_PI_OVER_2)))
{
value = value - MATHS_PI;
sign = -1;
} else if (value > (MATHS_PI + MATHS_PI_OVER_2))
{
value = (MATHS_PI<<1)-value;
}

// ----- Calculate ----------------------------
sqr = fixed_sqr ( value );
result = MATHS_COSK1;
result = fixed_mul ( result, sqr );
result -= MATHS_COSK2;
result = fixed_mul ( result, sqr );
result += (1 << fixedshifts);

return sign * result;
}

fixed fixed_tan ( fixed value )
{
fixed sqr, result;
sqr = fixed_sqr ( value );
result = MATHS_TANK1;
result = fixed_mul ( result, sqr );
result += MATHS_TANK2;
result = fixed_mul ( result, sqr );
result += (1 << fixedshifts);
result = fixed_mul ( result, value );
return result;
}

fixed fixed_sqr ( fixed value )
{
return fixed_mul( value, value );
}

fixed fixed_sqrt ( fixed value )
{
fixed square = (value + (1 << fixedshifts) ) >> 1;
int i;

for ( i = 0; i < 8; i ++ )
square = (square + fixed_div( value, square ) ) >> 1;
return square;
}

Karkayu
15/08/2005, 10:45
Gracias :saltando:
Siempre vienen bien cosillas como estas.

Un saludo
:brindis:

kmkzk
15/08/2005, 12:45
The Damizean is your friend!!
Gracias! :saltando:

Segata Sanshiro
15/08/2005, 13:32
Parece interesante, qué tipo de cosas se pueden conseguir con esto?

Damizean
21/08/2005, 22:10
Perdon, se me olvidó decir que esta libreria esta directamente basada (y no terminada aun) en esta libreria de punto fijo para java: http://people.csail.mit.edu/hqm/imode/fplib/FP.java.html

Y en cuanto a su utilidad, puede ser usada para hacer operaciones flotantes mucho más rapido que usando punto flotante, desde un juego 2D, hasta 3D o cualquier cosa. :)

Uncanny
22/08/2005, 00:09
Y en cuanto a su utilidad, puede ser usada para hacer operaciones flotantes mucho más rapido que usando punto flotante, desde un juego 2D, hasta 3D o cualquier cosa. :)A ver si la puedo probar con alguna cosa, si es que se me ocurre un ejemplo (fuera de la programación para GP32) para probar como de util podría ser tu librería, eso si, solo ver el codigo parece que como mínimo es interesante y completa :D

Una sugerencia, aunque hayas basado en otra librería, si no es una copia ni una modificación propiamente dicha, es tuya, la puedes poner como si fuera de dominio público (como ahora) pero siempre queda mejor bajo alguna licencia libre, especificada en los comentarios, como esa de Java que indicas que está bajo la Licencia Artística, yo te recomendaría una como la LGPL (http://www.gnu.org/copyleft/lesser.html) que es mejor que usar GPL en el caso de las librerías :)

Damizean
22/08/2005, 00:47
Esta libreria y las librerias que tengo planeadas a hacer a continuacion van a estar lanzadas bajo licencia LGPL. :)

Aunque me acabo de dar cuenta de que hay algunas mejoras que podria aplicar a la lib, así que Stay Tuned

chui
22/08/2005, 11:35
Yo uso estas... 64bit y en assembler de ARM, acelera un co-jon.

mortimor
22/08/2005, 11:48
Chui lo sabe!!!!! :D :musico:

Damizean
22/08/2005, 13:20
Wow, brutal :o

Uncanny
22/08/2005, 14:41
Yo uso estas... 64bit y en assembler de ARM, acelera un co-jon.Ya que creo que tiene algo que ver por la utilidad que puede tener esta librería, Chui ¿podrías decirme en que estado de "usabilidad" está SDL-TinyGL? No lo he probado, solo lo pregunto como curiosidad, ya se que hasta que no salga el SDK y las primeras "unidades de desarrollo" de la GPX2 no sabremos como estará el tema de la programación en 3D, y si podríamos también usar algo como OpenGL ES (aunque solo se pueda con aceleración por software), que es lo más parecido actualmente a TinyGL para sistemas embebidos, con SDL. Hago esta pregunta simplemente porque me parece que sería interesante con vistas a usarlo para la GPX2.

chui
22/08/2005, 15:05
Seguramente estará dicho header en la GPX2, lo saque en su momento de linux-arm... luego adapte un pelin, pero vamos poca cosa.

TinyGL para GP32 literalmente se arrastra, intente usar math-sll, pero no hubo manera, necesita mucha mas precision para funcionar con texturas.
Entiendo que la GPX2 llevara algo a medida para usar la segunda CPU ... sino, mal vamos.

mortimor
22/08/2005, 15:30
Pues yo creo que mas bien sera algo parecido al "mal vamos" :)

chui
22/08/2005, 20:10
Tu bien que lo sabes... no hemos sufrido veces su mierda de GPSDK !!!

Por cierto Morti.... ¿hiciste alguna mejora a la ML_Lib ?

Lo digo, porque la sigo usando en el loader de Fenix para Dreamcast. Si tienes otra version mas estable, rapida o lo que sea... quizas sea el momento.

mortimor
22/08/2005, 22:39
No la toco desde hace siglos (principios de año), está en la version 0.2 inestable (da fallos en algunos casos, el soporte de xpath no esta terminado y los DTDs los carga bien, incluso los externos, pero la validacion esta en pañales). No hay mejoras en la velocidad pero si en el consumo de memoria que lo consegui reducir un poco mas.

Si todo va bien me gustaria terminar la version 0.2 y dejarla definitivamente para finales del mes que viene.

chui
22/08/2005, 23:48
Juas! Cuan abandonao lo tienes... pero no tires la toalla, mirame a mi ahora con Fenix de nuevo :D

A.r.R.c.H.E.r
24/08/2005, 22:40
Juas! Cuan abandonao lo tienes... pero no tires la toalla, mirame a mi ahora con Fenix de nuevo :D


Muy buenas Chui, me gustaria utilizar la libreria que as puesto para un engine 3D que estoy haciendo, pero la verdad no se como meterle mano jejej podrias orientarme un poco de como se utiliza esa libreria?

chui
25/08/2005, 00:37
No es dificil, pero quizas para 3D no tenga toda la precision que te gustaria... al menos a TinyGL no fui capaz :D ... son 32bits para la parte entera y 32bits para la mantisa, no mas !

El uso es sencillote, hasta la puedes usar de dos maneras: si tienes definido USE_FIXED_POINT las operaciones seran en punto fijo y sino esta definido usara doubles... esto esta muy bien para depurar, pq muchas veces no sabes bien lo que estas poniendo.

Lo que tienes que ir convirtiendo es esto:

ORIGINAL


...
double a = 1.0;
double b = sin(a);
double c = b + a;
int i=3;
double d = c + (double) i;
....



PASADO


...
sll a = SLL_CONST_1;
sll b = sllsin(b);
sll c = slladd(b,a);
int i = 3;
sll d = slladd(c, int2sll(i));
...


Asi tienes practicamente todas las operciones:
A + B = slladd(A,B)
A - B = sllsub(A,B)
A * B = sllmul(A,B)
A / B = sllmul(A,B)
pow(A) = sllpow(A)
sqrt(A) = sllsqrt(A)
....

Si te fijas bien en el .h viene explicado todas las operaciones, que no son pocas por otra parte. Y su nomenglatura es como las funciones math.h pero siempre empezando por sll (signed long long = 64bits).

He utilizado una constante fija SLL_CONST_1 que es 1.0; pero si no tienes constante siempre puede usar por ejemplo dbl2sll(3.534), aunque consuma un poco mas. Tienes las constantes principales (0,1,-1,PI,2PI...), si realmente te hace falta otras te puedo explicar como hacer un programilla para sacarte las tuyas propias.

Por cierto, esa version he descubierto un bug en la funcion abs. DESCARGAR YA LA NUEVA VERSION QUE ADJUNTO.

Ahora acabo de portar SDL_gfx, con su rotozoom y todo usando esta maravilla.

una-i
25/08/2005, 01:04
No es dificil, pero quizas para 3D no tenga toda la precision que te gustaria... al menos a TinyGL no fui capaz :D ... son 32bits para la parte entera y 32bits para la mantisa, no mas !
Ahora acabo de portar SDL_gfx, con su rotozoom y todo usando esta maravilla.

Yo creo que para portar un engine con los ojos cerrados lo mismo no te dio precision pero yo mis cosas las estoy preparando directamente el fixed en 32bits usando coordenadas locales de objetos, trasnformaciones a mundo y estoy bastante contento con la resolucion...

Unai

P.D; Muy currada la explicaion del fixed point.... parece qu ela gp sige tirandote fuerte :P

chui
25/08/2005, 01:12
Unai, ya trate de venderte en su dia esta libreria... es muy muy rapida al usar assembler de ARM, completa y en punto fijo de 64bits !!!

Que mas se puede pedir? :-D

Animate, que seguro que no tienes que cambiar tanto.

una-i
25/08/2005, 01:20
Unai, ya trate de venderte en su dia esta libreria... es muy muy rapida al usar assembler de ARM, completa y en punto fijo de 64bits !!!

Que mas se puede pedir? :-D

Animate, que seguro que no tienes que cambiar tanto.

Seguro pero es que ya sabes que la smultiplicacinoe sdel arm cuesta un ciclo por byte != 0 en uno delo operadores eso sube mucho la media de las operacioes ademas me he hecho un afuncion de division la mar de mona

P.D: soy un friki ... tengo que aprobechar en la gp qu eno engo fechas ni entregas ;P


Unai

Damizean
25/08/2005, 02:43
Pues na, visto lo visto usaré la de chui (gracias por venderme la moto)

A.r.R.c.H.E.r
25/08/2005, 16:22
Muy buena explicacion Chui, ahora para ver si yo soy buen entendedor xD a ver si esta traduccion de una funcion es correcta:

Esta es con float:

/** FUNCION PARA APLICAR LA MATRIZ **/
void AplicarMatriz(MATRIZ *m, float x, float y, float z, float *xout, float *yout, float *zout)
{
*xout = x*m->v[0][0] + y*m->v[1][0] + z*m->v[2][0] + 1.0*m->v[3][0];
*yout = x*m->v[0][1] + y*m->v[1][1] + z*m->v[2][1] + 1.0*m->v[3][1];
*zout = x*m->v[0][2] + y*m->v[1][2] + z*m->v[2][2] + 1.0*m->v[3][2];
}

Esta con signed long long:

/** FUNCION PARA APLICAR LA MATRIZ **/
void AplicarMatriz(MATRIZ *m, sll x, sll y, sll z, sll *xout, sll *yout, sll *zout)
{
*xout = slladd(slladd(slladd(sllmul(x, m->v[0][0]), sllmul(y, m->v[1][0]), sllmul(z, m->v[2][0]), sllmul(1.0, m->v[3][0]);
*yout = slladd(slladd(slladd(sllmul(x, m->v[0][1]), sllmul(y, m->v[1][1]), sllmul(z, m->v[2][1]), sllmul(1.0, m->v[3][1]);
*zout = slladd(slladd(slladd(sllmul(x, m->v[0][2]), sllmul(y, m->v[1][2]), sllmul(z, m->v[2][2]), sllmul(1.0, m->v[3][2]);
}

Teoricamente tienen que hacer lo mismo...

chui
25/08/2005, 21:52
Parece que todo esta ok si el tipo de dato m->v[][] es sll tambien.

Como ya t dije se puede compilar sin USE_FIXED_POINT y hacer lo mismo que la funcion original. Por lo que puedes trazar los valores de xout, yout y zout en ambas funcionas para asegurarte.

A.r.R.c.H.E.r
25/08/2005, 22:48
Parece que todo esta ok si el tipo de dato m->v[][] es sll tambien.

Como ya t dije se puede compilar sin USE_FIXED_POINT y hacer lo mismo que la funcion original. Por lo que puedes trazar los valores de xout, yout y zout en ambas funcionas para asegurarte.

Buenas chui, e añadido la libreria al engine3D y cambiado todas las funciones pero al ejecutar me va ala misma velocidad que con floads asi que supongo que esta utilizando gouble, como compilo con la opcion USE_FIXED_POINT??

chui
25/08/2005, 22:53
Lo normal es añadir al Makefile esa opcion de compilacion, osea que tiene que compilar como:
arm-elf-gcc -DUSE_FIXED_POINT patatin pataton patatero


Tambien puedes forzarlo poniendo al principio de 'math-sll.h':
#define USE_FIXED_POINT

Como mas te guste.

A.r.R.c.H.E.r
25/08/2005, 22:56
uoo genial ha acelerado de 4 fps a 11 fps a 66Mhz :) ahora solo me queda solucionar el porque no aparece los graficos en pantalla jajaj


una pregunta... no puedo poner como argumentos un sll no? por ejemplo la rutina que tengo para dibujar lineas me pide las coordenadas tipo int antes de pasarselas tendre que convertirlas de sll a int verdad?

boubou
26/08/2005, 09:43
Chui, donde tienes el tinyGL?

Tiene soporte para texturas?

---Ya lo he encontrado---

chui
26/08/2005, 15:46
uoo genial ha acelerado de 4 fps a 11 fps a 66Mhz :) ahora solo me queda solucionar el porque no aparece los graficos en pantalla jajaj


una pregunta... no puedo poner como argumentos un sll no? por ejemplo la rutina que tengo para dibujar lineas me pide las coordenadas tipo int antes de pasarselas tendre que convertirlas de sll a int verdad?

si, tendras que hacer algo como:

pinta_yo_que_se( sll2int(x), sll2int(y) );





Chui, donde tienes el tinyGL?

Tiene soporte para texturas?

AQUI (http://sdl-tinygl.sourceforge.net/). Si tiene, pero si las uso con fixed point peta.

A.r.R.c.H.E.r
26/08/2005, 22:34
Lo normal es añadir al Makefile esa opcion de compilacion, osea que tiene que compilar como:
arm-elf-gcc -DUSE_FIXED_POINT patatin pataton patatero


Tambien puedes forzarlo poniendo al principio de 'math-sll.h':
#define USE_FIXED_POINT

Como mas te guste.


Buenas chui, ya e conseguido implementar el fixed point en el engine y funciona correctamente... lo malo es que no ha acelerado nada... sigue a la misma velocidad... por que puede ser? mi correo es ArcherEmisarioGorgonita@hotmail.com si quieres agregame y lo comentamos... muchas gracias ;) a ver si hay suerte jejeje

otto_xd
26/08/2005, 23:54
Una pregunta, esas librerias solo aceleran en caso de tener que usar operaciones que requieren coma flotante, no?
Es decir, senos, cosenos, divisiones con reales...
Saludos.

Damizean
27/08/2005, 03:10
En realidad esto es para "reemplazar" a las variables reales. Como la GP32 (ni la GPX2) no tienen un hardware especializado en operaciones de punto flotante, son mas lentos que el fari comiendo limones, así que se tienen que usar metodos "mas guarros" para conseguir los mismos resultados y rapido.

otto_xd
27/08/2005, 14:12
yap, pero si se usa en un programa solo enteros, no tiene porque haber mejora de rendimiento, no?
Gracias

Petiso
24/11/2005, 23:14
:arriba:

Tras unos dias peleandome con los pu*tos floats, y pensado que ya no sabia programar ... me he pasado a la "libreria" de punto fijo de Chui, y despues de convertir el programa, este hacia lo que tenia que hacer, y he vuelto a confiar en mi programacion :-p

Así que:
- No useis floats si podeis (sobretodo con sin i cos ...).

Por cierto, el la libreria de chui, han un pequeño error, que me impedia compilar:

Linea 438: for (u = v; u; ((ull)u) >>= 1)
(me da error de compilacion ...)

Y ha de ser:

for (u = v; u; u = (ull) u >> 1)

Bye and thanks chui !

NoobLuck
25/11/2005, 21:55
Yo uso estas... 64bit y en assembler de ARM, acelera un co-jon.

No veo código ensamblador, veo muchas macros...

Petiso
25/11/2005, 22:04
Las macros son solo para cuando usas los "double" de la maquina.

Si vas mas abajo, están todas las funciones en ensamblador.

Bye !

Damizean
26/11/2005, 01:29
La parte de ensamblador es para hacer las multiplicaciones directamente con variables de 64 bits. La verdad es que ya no uso la SLL, ahora utilizo variables long (16:16), y una tabla que contiene los inversos de los numeros (65536 vectores que son interpolados, lo siento una-i por copiarte el metodo xD) para hacer divisiones. Total, va a ser mas o menos lo mismo, y funcionará más rapido a la larga :D