00001 /**********************************************************/ 00002 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00003 /* 00004 Copyright: 1994 - Grupo de Voz (DAET) ETSII/IT-Bilbao 00005 00006 Nombre fuente................ SPL1.C 00007 Nombre paquete............... SPL 00008 Lenguaje fuente.............. C (Borland C/C++ 3.1) 00009 Estado....................... Completado 00010 Dependencia Hard/OS.......... - 00011 Codigo condicional........... NDEBUG 00012 00013 Codificacion................. Borja Etxebarria 00014 00015 Version dd/mm/aa Autor Proposito de la edicion 00016 ------- -------- -------- ----------------------- 00017 1.1.2 15/05/96 Borja bugs en documentacion 00018 1.1.1 30/07/95 Borja scope funciones explicito 00019 1.1.0 08/12/94 Borja revision general (tipos,idx,nel,tnel...) 00020 1.0.0 06/07/93 Borja Codificacion inicial. 00021 00022 ======================== Contenido ======================== 00023 <DOC> 00024 Manejo de matrices especiales, resolucion de sistemas 00025 de ecuaciones, calculo de autovalores.... 00026 00027 Definir NDEBUG para desconectar la validacion de parametros 00028 con assert(). No definir este simbolo mientras se depuren 00029 aplicaciones, ya que aunque las funciones son algo mas lentas, 00030 el chequeo de validacion de parametros resuelve muchos problemas. 00031 00032 00033 Matrices y sistemas de ecuaciones basados en matrices. 00034 Los elementos de las matrices se referencian por (i,j) siendo 00035 i la fila y j la columna. i=1...n, j=1...n. 00036 00037 Matrices simetricas: matrices matrix_sim 00038 y matrices triangulares matrix_tri 00039 ---------------------------------------- 00040 00041 La estructura que se almacena en estas matrices es la siguiente: 00042 00043 . a(1,1) 00044 . a(2,1) a(2,2) 00045 . .... 00046 . a(n,1) ............a(n,n) 00047 00048 la primera fila tiene un elemento, la segunda 2... hasta n lineas para 00049 una matriz cuadrada de orden n. La mitad superior de la matriz es la 00050 simetrica de la inferior en las matrices simetricas, o nula en las 00051 matrices triangulares. 00052 00053 Se almacena todo por lineas de izq. a derecha y de arriba a abajo: 00054 . a(1,1) a(2,1) a(2,2) a(3,1) ... a(n,n) 00055 00056 La funcion idx_matrix_sim(i,j) {devuelve} el indice dentro del array 00057 lineal y empezando en cero, para el elemento (i,j) de la matriz. 00058 Por ejemplo, idx_matrix_sim(3,1) {devuelve} 3 (cuarto elemento del array). 00059 Similar para las triangulares con idx_matrix_tri(i,j). 00060 En las funciones nel_matrix_tri(n) y nel_matrix_sim(n) se {devuelve} el 00061 numero de elementos que se deben almacenarse para representar una 00062 matriz triangular o simetrica. 00063 00064 00065 Matrices diagonales: matrices matrix_dgn 00066 ---------------------------------------- 00067 00068 La estructura que se almacena en estas matrices es la siguiente: 00069 00070 . a(1,1) 00071 . a(2,2) 00072 . ... 00073 . a(n,n) 00074 00075 Cada fila tiene solo un elemento, es resto de elementos hasta formar 00076 la matriz cuadrada de orden n son nulos. 00077 00078 Se almacenan solo los elementos no nulos, en un vector lineal: 00079 . a(1,1) a(2,2) a(3,3) ... a(n,n) 00080 00081 La funcion idx_matrix_dgn(i) {devuelve} el indice dentro del array lineal 00082 y empezando en cero, para el elemento (i,i) de la matriz. Por ejemplo, 00083 idx_matrix_dgn(3,3) {devuelve} 2 (tercer elemento del array). 00084 La funcion nel_matrix_dgn(n) {devuelve} el numero de elementos 00085 que deben almacenarse para representar una matriz diagonal. 00086 00087 Ref: 00088 . Digital Processing of Speech Signals 00089 . L.R. Rabiner / R.W Schafer 00090 . Prentice Hall 00091 00092 Ref Autovalores y autovectores: 00093 . Numerica Recipes 00094 . W.H. Press, B.PUBLIC.Flannery,... 00095 . Cambridge University Press 00096 </DOC> 00097 =========================================================== 00098 */ 00099 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00100 /**********************************************************/ 00101 00102 #include "spli.h" 00103 00104 /*<DOC>*/ 00105 /**********************************************************/ 00106 /* {devuelve} el indice dentro de un array para el elemento 00107 ({i},{j}) de una matriz simetrica de cualquier orden. 00108 {i} son filas, {j} columnas. 00109 Aunque el elemento ({i},{j}) es igual que el ({j},{i}), 00110 enviar _siempre_ {j}<={i}. 00111 {i}>=1, {j}>=1. 00112 00113 La estructura que se almacena en esta matriz es la siguiente: 00114 00115 . a(1,1) 00116 . a(2,1) a(2,2) 00117 . .... 00118 . a(n,1) ............a(n,n) 00119 00120 la primera fila tiene un elemento, la segunda 2... hasta n lineas para 00121 una matriz cuadrada de orden n. La mitad superior de la matriz es la 00122 simetrica de la inferior. 00123 00124 Se almacena todo por lineas de izq. a derecha y de arriba a abajo: 00125 . a(1,1) a(2,1) a(2,2) a(3,1) ... a(n,n) */ 00126 00127 PUBLIC SPL_INT XAPI idx_matrix_sim( SPL_INT i, SPL_INT j ) 00128 /*</DOC>*/ 00129 { 00130 assert(i>0); 00131 assert(j>0); 00132 assert(j<=i); 00133 00134 return __idx_matrix_sim(i,j); 00135 } 00136 00137 /*<DOC>*/ 00138 /**********************************************************/ 00139 /* {devuelve} el numero de elementos que se deben almacenar en una 00140 matriz simetrica de orden {n}. {n}>=0 */ 00141 00142 PUBLIC SPL_INT XAPI nel_matrix_sim( SPL_INT n ) 00143 /*</DOC>*/ 00144 { 00145 assert(n>=0); 00146 00147 return __idx_matrix_sim(n+1,1); 00148 } 00149 00150 /*<DOC>*/ 00151 /**********************************************************/ 00152 /* {devuelve} el indice dentro de un array para el elemento ({i},{j}) 00153 de una matriz triangular de cualquier orden. 00154 {i} son filas, {j} columnas. 00155 Aunque el elemento ({i},{j}) es igual que el ({j},{i}), 00156 enviar _siempre_ {j}<={i}. 00157 {i}>=1, {j}>=1. 00158 00159 La estructura que se almacena en esta matriz es la siguiente: 00160 00161 . a(1,1) 00162 . a(2,1) a(2,2) 00163 . .... 00164 . a(n,1) ............ a(n,n) 00165 00166 la primera fila tiene un elemento, la segunda 2... hasta n lineas para 00167 una matriz cuadrada de orden n. La mitad superior de la matriz es nula. 00168 00169 Se almacena todo por lineas de izq. a derecha y de arriba a abajo: 00170 . a(1,1) a(2,1) a(2,2) a(3,1) ... a(n,n) */ 00171 00172 /* Estas macros se encuentran en SPL.H 00173 #define __idx_matrix_tri(i,j) __idx_matrix_sim(i,j) 00174 #define idx_matrix_tri(i,j) idx_matrix_sim(i,j) 00175 */ 00176 /*</DOC>*/ 00177 00178 /*<DOC>*/ 00179 /**********************************************************/ 00180 /* {devuelve} el numero de elementos que se deben almacenar en una 00181 matriz triangular de orden {n}. {n}>=0 */ 00182 00183 /* Esta macro esta en SPL.H 00184 #define nel_matrix_tri(n) nel_matrix_sim(n) 00185 */ 00186 /*</DOC>*/ 00187 00188 /*<DOC>*/ 00189 /**********************************************************/ 00190 /* {devuelve} el indice dentro de un array para el elemento 00191 ({i},{j}) de una matriz diagonal de cualquier orden. 00192 {i} son filas, {j} columnas. 00193 {i}>=1, {j}>=1. 00194 00195 La estructura que se almacena en esta matriz es la siguiente: 00196 00197 . a(1,1) 00198 . a(2,2) 00199 . ... 00200 . a(n,n) 00201 00202 la primera fila tiene un elemento, la segunda otro... hasta n lineas para 00203 una matriz cuadrada de orden n. La parte inferior y la superior a la 00204 diagonal es nula. 00205 00206 Se almacena todo por lineas de izq. a derecha y de arriba a abajo: 00207 . a(1,1) a(2,2) a(3,3) ... a(n,n) */ 00208 00209 PUBLIC SPL_INT XAPI idx_matrix_dgn( SPL_INT i ) 00210 /*</DOC>*/ 00211 { 00212 assert(i>0); 00213 00214 return __idx_matrix_dgn(i); 00215 } 00216 00217 /*<DOC>*/ 00218 /**********************************************************/ 00219 /* {devuelve} el numero de elementos que se deben almacenar en una 00220 matriz diagonal de orden {n}. {n}>=0 */ 00221 00222 PUBLIC SPL_INT XAPI nel_matrix_dgn( SPL_INT n ) 00223 /*</DOC>*/ 00224 { 00225 assert(n>=0); 00226 00227 return n; 00228 } 00229 00230 /*<DOC>*/ 00231 /**********************************************************/ 00232 /* Triangulacion de matriz simetrica definida positiva. 00233 Dada una matriz simetrica {msi} de orden {n}>=0, calcula una 00234 matriz triangular {mtr} del mismo orden, tal que {mtr} multiplicada 00235 por {mtr} transpuesta es igual a {msi}. 00236 Solo para matrices simetricas definidas positivas. 00237 {msi} y {mtr} _no_ pueden ser punteros a la misma matriz en memoria. 00238 El formato de {msi} y {mtr} es el explicado para matrices simetricas. 00239 Ambas matrices deben ser de nel_matrix_sim(n) elementos. 00240 {n}>=0, {msi}!={mtr} */ 00241 00242 PUBLIC SPL_VOID XAPI matrix_sim2tri( SPL_pFLOAT msi, SPL_pFLOAT mtr, 00243 SPL_INT n ) 00244 /*</DOC>*/ 00245 { 00246 SPL_INT i,j,k, i1, i1o, i2; 00247 SPL_FLOAT sum; 00248 assert(n>=0); 00249 assert(msi!=mtr); 00250 00251 i1=0; 00252 for (i=0; i<n; i++) { 00253 i1o=i1; 00254 i2=0; 00255 for (j=0; j<i; ) { 00256 __xsub(k,0,j,mtr[i1o+k]*mtr[i2+k],sum,msi[i1]); 00257 mtr[i1++]=sum/mtr[i2+j]; 00258 j++; 00259 i2+=j; 00260 } 00261 __xsub(k,0,i,mtr[i1o+k]*mtr[i1o+k],sum,msi[i1]); 00262 mtr[i1++]= sqrt(sum); 00263 } 00264 } 00265 00266 /*<DOC>*/ 00267 /**********************************************************/ 00268 /* Triangulacion de matriz simetrica definida positiva por Cholesky. 00269 Dada una matriz simetrica {msi} de orden {n}>=0, calcula una 00270 matriz triangular {mtr} del mismo orden, y una matriz diagonal {mdi} 00271 tambien del mismo orden, tal que {mtr} multiplicada por {mdi} y por 00272 {mtr} transpuesta es igual a {msi}. 00273 La matriz triangular tiene todos los elementos de la diagonal principal 00274 iguales a 1. Por tanto, esta matriz se puede almacenar como una matriz 00275 triangular de orden {n}-1. 00276 Solo para matrices simetricas definidas positivas. 00277 {msi}, {mdi} y {mtr} _no_ pueden ser la misma matriz en memoria. 00278 El formato de {msi} y {mtr} es el explicado para matrices simetricas. 00279 La matriz {msi} es de nel_matrix_sim(n) elementos, mientras que la matriz 00280 triangular {mtr} sera de nel_matrix_tri(n-1) elementos. 00281 El formato de {mdi} es el explicado para matrices diagonales, y 00282 debe tener nel_matrix_dgn(n) elementos */ 00283 00284 PUBLIC SPL_VOID XAPI matrix_sim2tri_dgn( SPL_pFLOAT msi, SPL_pFLOAT mtr, 00285 SPL_pFLOAT mdi, SPL_INT n ) 00286 /*</DOC>*/ 00287 { 00288 SPL_INT i,j,k; 00289 SPL_INT bi,bj,ai; 00290 SPL_FLOAT sum; 00291 assert(n>=0); 00292 assert(msi!=mtr); 00293 assert(msi!=mdi); 00294 00295 mdi[0] = msi[0]; 00296 bj=0; 00297 for (j=0; j<n-1; ) { 00298 ai=bj+j+1; 00299 bi=bj; 00300 for (i=j+2; i<=n; i++) { 00301 __xsub(k,0,j,mtr[bi+k]*mtr[bj+k-j]*mdi[k],sum,msi[ai+j]) 00302 mtr[bi+j] = sum/mdi[j]; 00303 bi+=(i-1); 00304 ai+=i; 00305 } 00306 j++; 00307 __xsub(k,0,j,mtr[bj+k]*mtr[bj+k]*mdi[k],sum,msi[bj+j+j]); 00308 mdi[j] = sum; 00309 bj+=j; 00310 } 00311 } 00312 00313 /*<DOC>*/ 00314 /**********************************************************/ 00315 /* resolucion de ecuaciones con matriz triangular. 00316 Dado un sistema de ecuaciones lineales, matricialmente: 00317 00318 . A*x=c 00319 00320 donde 00321 . A=matriz cuadrada triangular de dimension n 00322 . x=vector incognita de dimension n 00323 . c=vector de terminos independientes de dimension n 00324 00325 Conocidos A y c, esta funcion resuelve el sistema (calcula el 00326 vector x). 00327 Parametros: 00328 - SPL_pFLOAT {mA} : Matriz triangular A de dimension {n}. 00329 . de nel_matrix_tri(n) elementos. 00330 - SPL_pFLOAT {vc} : Vector de terminos independientes c. 00331 . de {n} elementos. 00332 - SPL_INT {n} : Orden o dimension del sistema. 00333 - SPL_pFLOAT {vx} : Vector de resultado, de {n} elementos. */ 00334 00335 PUBLIC SPL_VOID XAPI ecsys_tri( SPL_pFLOAT mA, SPL_pFLOAT vc, SPL_INT n, 00336 SPL_pFLOAT vx ) 00337 /*</DOC>*/ 00338 { 00339 SPL_INT i,k, bi; 00340 SPL_FLOAT sum; 00341 assert(n>=0); 00342 00343 bi=0; 00344 for (i=0; i<n; i++) { 00345 bi+=i; 00346 __xsub(k,0,i,mA[bi+k]*vx[k],sum,vc[i]); 00347 vx[i]=sum/mA[bi+i]; 00348 } 00349 } 00350 00351 /*<DOC>*/ 00352 /**********************************************************/ 00353 /* resolucion de ecuaciones con matriz simetrica triangulada. 00354 Dado un sistema de ecuaciones lineales, matricialmente: 00355 00356 . A*x=c 00357 00358 donde 00359 . A=matriz cuadrada de dimension n 00360 . x=vector incognita de dimension n 00361 . c=vector de terminos independientes de dimension n 00362 00363 Si A es simetrica definida positiva, se puede expresar como 00364 00365 . A=B*B' 00366 00367 Donde B es una matriz triangular, y B' es su transpuesta. 00368 Conocidos B y c, esta funcion resuelve el sistema (calcula el 00369 vector x). B se puede obtener a partir de A mediante la funcion 00370 matrix_sim2tri(). 00371 Parametros: 00372 - SPL_pFLOAT {mB} : Matriz triangular B de dimension {n}. 00373 . de nel_matrix_tri(n) elementos. 00374 - SPL_pFLOAT {vc} : Vector de terminos independientes c, de {n} elementos. 00375 - SPL_INT {n} : Orden o dimension del sistema 00376 - SPL_pFLOAT {vx} : Vector de resultado, de {n} elementos. */ 00377 00378 PUBLIC SPL_VOID XAPI ecsys_simtri( SPL_pFLOAT mB, SPL_pFLOAT vc, SPL_INT n, 00379 SPL_pFLOAT vx ) 00380 /*</DOC>*/ 00381 { 00382 SPL_INT i,k, bi, bk; 00383 SPL_FLOAT sum; 00384 assert(n>=0); 00385 00386 bi=0; 00387 for (i=0; i<n; i++) { 00388 bi+=i; 00389 __xsub(k,0,i,mB[bi+k]*vx[k],sum,vc[i]); 00390 vx[i]=sum/mB[bi+i]; 00391 } 00392 00393 for (i=n-1; i>=0; i--) { 00394 bk=bi; 00395 __xsub(k,i+1,n,mB[(bk+=k)+i]*vx[k],sum,vx[i]); 00396 vx[i]=sum/mB[bi+i]; 00397 bi-=i; 00398 } 00399 } 00400 00401 /*<DOC>*/ 00402 /**********************************************************/ 00403 /* resolucion de ecuaciones por Cholesky. Es mucho mas seguro 00404 que el metodo de la matriz triangulada. 00405 Dado un sistema de ecuaciones lineales, matricialmente: 00406 00407 . A*x=c 00408 00409 donde 00410 . A=matriz cuadrada de dimension n 00411 . x=vector incognita de dimension n 00412 . c=vector de terminos independientes de dimension n 00413 00414 Si A es simetrica definida positiva, se puede expresar como 00415 00416 . A=B*d*B' 00417 00418 Donde B es una matriz triangular inferior (diagonal principal=1), 00419 B' es su transpuesta, y d es una matriz diagonal. 00420 Al ser B triangular inferior, se puede guardar como matriz triangular 00421 de dimension n-1. 00422 Conocidos B, d y c, esta funcion resuelve el sistema (calcula el 00423 vector x). B y d se pueden obtener a partir de A mediante la funcion 00424 matrix_sim2tri_dgn(). 00425 Parametros: 00426 - SPL_pFLOAT {mB} : Matriz triangular inferior B de dimension {n}-1. 00427 . de nel_matrix_tri(n-1) elementos. 00428 - SPL_pFLOAT {md} : Matriz diagonal d de dimension {n}. 00429 . de nel_matriz_dgn(n) elementos. 00430 - SPL_pFLOAT {vc} : Vector de terminos independientes c. 00431 . de {n} elementos. 00432 - SPL_INT {n} : Orden o dimension del sistema 00433 - SPL_pFLOAT {vx} : Vector de resultado. 00434 . de {n} elementos. 00435 */ 00436 00437 PUBLIC SPL_VOID XAPI ecsys_tri_dgn( SPL_pFLOAT mB, SPL_pFLOAT md, 00438 SPL_pFLOAT vc, SPL_INT n, SPL_pFLOAT vx ) 00439 /*</DOC>*/ 00440 { 00441 SPL_INT i,k, bi, bk; 00442 SPL_FLOAT sum; 00443 assert(n>=0); 00444 00445 bi=0; 00446 for (i=0; i<n; i++) { 00447 __xsub(k,0,i,mB[bi+k]*vx[k],sum,vc[i]); 00448 vx[i]=sum; 00449 bi+=i; 00450 } 00451 00452 bi-=i-1; 00453 for (i=n-1; i>=0; ) { 00454 bk=bi; 00455 __xsub(k,i+1,n,mB[(bk+=k-1)+i]*vx[k],sum,vx[i]/md[i]); 00456 vx[i]=sum; 00457 i--; 00458 bi-=i; 00459 } 00460 } 00461 00462 /*<DOC>*/ 00463 /**********************************************************/ 00464 /* Calculo de autovalores y autovectores normalizados de una 00465 matriz tridiagonal simetrica, por metodo QL con desplazamientos 00466 implicitos (Ref: Numerical Recipes, rutina tqli() ). 00467 El orden de la matriz se envia en {n}, y solo es necesario enviar 00468 la diagonal principal ({n} elementos) en {vd}, y la subdiagonal 00469 inferior (o la superior, pues es la misma) en {ve}. La subdiagonal 00470 solo tiene {n}-1 elementos, pero el vector {ve} que se envie, debe 00471 tener espacio para un elemento mas al final, por lo que en total 00472 tambien sera de {n} elementos. El valor de este ultimo elemento 00473 dentro del vector {ve} es irrelevante. 00474 La funcion calcula los autovalores y los devuelve en el propio 00475 vector {vd}. Ademas {ve} queda con valores indefinidos. 00476 El calculo de los autovectores es opcional, pues requiere muchas 00477 operaciones. Si se envia NULL en {mz}, los autovectores no se calculan. 00478 Para calcular los autovectores, enviar en {mz} un puntero a un array de 00479 {n}*{n} elementos (NOTA IMPORTANTE ABAJO), en el que se almacenara en 00480 cada fila el autovector correspondiente a cada autovalor almacenado 00481 en {d}. El autovector correspondiente al autovalor d[0] se almacena 00482 en z[0]-->z[n-1] (es un vector de {n} componentes). Despues, el 00483 correspondiente a d[1], se almacena en z[n]-->z[2*n-1]; asi hasta 00484 los {n} autovectores. En general, el autovector de d[x] esta 00485 en z[n*x]-->z[n*x+n-1]. 00486 NOTA IMPORTANTE: Si se va a calcular los autovectores, la matriz de 00487 autovectores {mz} debe enviarse inicializada como una matriz unidad!!! 00488 es decir, todo a ceros (z[i*n+j]=0 para i,j=0,1...n-1, i!=j) y la 00489 diagonal principal a unos (z[n*i+i]=1 para i=0,1...n-1). Esto es asi 00490 porque esta funcion tiene otros usos (Numerical Recipes).... 00491 00492 La funcion {devuelve} un valor booleano, que sera FALSE (0) en caso de 00493 que todo funcione correctamente. Pero si en algun momento se supera 00494 el numero maximo de iteraciones permitidas (EIGEN_MAXITER, definido 00495 en SPL.H) entonces {devuelve} TRUE, y los resultados quedan indefinidos */ 00496 00497 PUBLIC SPL_BOOL XAPI eigen_tdg( SPL_pFLOAT vd, SPL_pFLOAT ve, SPL_INT n, 00498 SPL_pFLOAT mz ) 00499 /*</DOC>*/ 00500 { 00501 #define __EIGEN_SIGN(a,b) ((b)<0 ? -fabs(a) : fabs(a)) 00502 SPL_INT m,l,iter,i,j,k; 00503 SPL_FLOAT s,r,p,g,f,dd,c,b; 00504 00505 ve[n-1]=0.0; 00506 for (l=0;l<n;l++) { 00507 iter=0; 00508 do { 00509 for (m=l;m<n-1;m++) { 00510 dd=fabs(vd[m])+fabs(vd[m+1]); 00511 if ((fabs(ve[m])+dd) == dd) 00512 break; 00513 } 00514 if (m != l) { 00515 if ((iter++)==EIGEN_MAXITER) /* demasiadas iteraciones */ 00516 return SPL_TRUE; 00517 g=(vd[l+1]-vd[l])/(2.0*ve[l]); 00518 r=sqrt((g*g)+1.0); 00519 g=vd[m]-vd[l]+ve[l]/(g+__EIGEN_SIGN(r,g)); 00520 s=c=1.0; 00521 p=0.0; 00522 for (i=m-1;i>=l;i--) { 00523 f=s*ve[i]; 00524 b=c*ve[i]; 00525 if (fabs(f) >= fabs(g)) { 00526 c=g/f; 00527 r=sqrt((c*c)+1.0); 00528 ve[i+1]=f*r; 00529 c *= (s=1.0/r); 00530 } 00531 else { 00532 s=f/g; 00533 r=sqrt((s*s)+1.0); 00534 ve[i+1]=g*r; 00535 s *= (c=1.0/r); 00536 } 00537 g=vd[i+1]-p; 00538 r=(vd[i]-g)*s+2.0*c*b; 00539 p=s*r; 00540 vd[i+1]=g+p; 00541 g=c*r-b; 00542 if (mz!=NULL) { /* autovectores, si mz no es nul */ 00543 j=i*n; 00544 for (k=0;k<n;k++) { 00545 f=mz[j+n+k]; 00546 mz[j+n+k]=s*mz[j+k]+c*f; 00547 mz[j+k]=c*mz[j+k]-s*f; 00548 } 00549 } 00550 } 00551 vd[l]=vd[l]-p; 00552 ve[l]=g; 00553 ve[m]=0.0; 00554 } 00555 } while (m != l); 00556 } 00557 return SPL_FALSE; 00558 #undef __EIGEN_SIGN 00559 } 00560 00561 /**********************************************************/ 00562