• No se han encontrado resultados

INSTITUTO DE ASTROFISICA DE CANARIAS ESPACIO ACÚSTICO VIRTUAL

N/A
N/A
Protected

Academic year: 2022

Share "INSTITUTO DE ASTROFISICA DE CANARIAS ESPACIO ACÚSTICO VIRTUAL"

Copied!
86
0
0

Texto completo

(1)

ESPACIO ACÚSTICO VIRTUAL

DESARROLLO DE UN ALGORITMO EFICIENTE PARA LA IDENTIFICACIÓN DE SISTEMAS EMPLEANDO SECUENCIAS

DE PRUEBA DE LONGITUD MÁXIMA

INSTITUTO DE ASTROFISICA DE CANARIAS

38200 La Laguna (Tenerife) - ESPAÑA - Teléfono (922)605200 - Fax (922)605210

(2)

CUADRO DE AUTORES

Nombre Función

Marcos Suárez Valles Becario de Verano del Área de Instrumentación

CUADRO DE CONTROL

Control Nombre Función

Revisado por: Haresh M. Chulani Ingeniero Electrónico

Aprobado por: Luis Fernando Rodriguez Jefe Departamento Electrónica Autorizado por: Luis Fernando Rodriguez Jefe Departamento Electrónica

HISTORIA DEL DOCUMENTO

Versión Fecha Resumen modificación 1 27/09/1999 Todos los apartados

(3)

RESUMEN

El presente informe recoge una implementación eficiente del cálculo de la respuesta impulsional de un sistema empleando patrones de ruido pseudoaleatorio en forma de Secuencias de Longitud Máxima (MLS) como señales de prueba. Esto se consigue mediante un conjunto de dos rutinas que hacen uso de la Transformada Rápida de Hadamard (FHT). Dichas rutinas han sido diseñadas para sustituir ventajosamente al software utilizado hasta el momento en el proyecto Espacio Acústico Virtual (EAV). Una de ellas ha sido escrita en MATLAB, mientras que la otra, cuya eficiencia es crítica, se ha codificado en ANSI C y ha sido compilada como fichero ejecutable de MATLAB (MEX). Se proporcionan dos variantes de las rutinas desarrolladas, compatibles con las versiones 4.2 y 5.3 del intérprete MATLAB.

(4)

TABLA DE CONTENIDO

CUADRO DE AUTORES...2

CUADRO DE CONTROL...2

HISTORIA DEL DOCUMENTO...2

RESUMEN...3

TABLA DE CONTENIDO...4

LISTA DE ABREVIATURAS...6

1. INTRODUCCIÓN Y OBJETIVOS...7

2. DESCRIPCIÓN DEL ALGORITMO UTILIZADO...9

2.1 EXPRESIÓN MATRICIALDEL PIR PARA SEÑALESDE PRUEBADE TIPO MLS...9

2.2 ALGORITMODE CÁLCULODELOS VECTORESDE PERMUTACIÓN...11

2.3 ALGORITMODE CÁLCULODEL PIR DEL SISTEMA...15

3. IMPLEMENTACIÓN...18

3.1 RUTINADE CÁLCULODELOS VECTORESDE PERMUTACIÓN: PERMUT.M...19

3.1.1 Prototipo de la Función y Descripción del Código Fuente...19

3.1.2 Compilación de la Rutina permut.m para MATLAB 5.3...24

3.2 RUTINADE CÁLCULODEL PIR: CCIRCFHT.C...25

3.2.1 Prototipo de la Función y Descripción del Código Fuente...25

3.2.2 Compilación de ccircfht.c para MATLAB en sus Versiones 4.2 y 5.3...35

3.3 UBICACIÓN Y UTILIZACIÓN DE LAS RUTINAS PERMUT.M/PERMUT.DLL Y CCIRCFHT.MEX/CCIRCFHT.DLL...38

4. RESULTADOS...40

5. POSIBLES MEJORAS...46

ANEXOS...47

A. LISTA DE DOCUMENTOS DE REFERENCIA...47

B. FUNDAMENTO MATEMÁTICO DEL CÁLCULO EFICIENTE DEL PIR PARA SEÑALES DE PRUEBA DE TIPO MLS...48

B.1. INTRODUCCIÓNTEÓRICAALA FHT...48

B.1.1. Matrices de Hadamard y Transformada de Hadamard...48

B.1.2. Descripción del Algoritmo FHT...49

B.2. CÁLCULO DE LA CORRELACIÓN CIRCULAR MEDIANTE LA FHT PARA SECUENCIAS DE ENTRADADE TIPO MLS...51

B.2.1. Características de una MLS...51

B.2.2. Justificación Matemática del Método de Cálculo de la Correlación Circular mediante la FHT...52

(5)

B.2.3. Descripción del Algoritmo de Cálculo de la Correlación Circular mediante la FHT....59 C. RESULTADOS PARCIALES DEL DESARROLLO DE LA RUTINA DE CÁLCULO

DE LOS VECTORES DE PERMUTACIÓN...67 D. RESULTADOS PARCIALES DEL DESARROLLO DE LA RUTINA DE CÁLCULO

DEL PIR...69 D.1. RESULTADOS DEL INTENTO DESARROLLO DE UNA RUTINA DE CÁLCULO DEL PIR EN

CÓDIGO MATLAB...69 D.2. RESULTADOS PARCIALESDEL DESARROLLODE RUTINADE CÁLCULODEL PIR EN CÓDIGO

C...74 E. POSIBILIDAD DE MEJORA DE LAS RUTINAS EXPUESTAS...79 F. CONTENIDO DEL DISQUETTE QUE ACOMPAÑA AL DOCUMENTO...89

(6)

LISTA DE ABREVIATURAS

D/A Digital/Analogue (Digital/Analógico) DC Direct Current (Corriente Continua)

DLL Dynamic Link Library (Librería de Enlace Dinámico) DSP Digital Signal Proccessing (Proceso Digital de la Señal) EAV Espacio Acústico Virtual

FFT Fast Fourier Transform (Transformada Rápida de Fourier) FHT Fast Hadamard Transform (Transformada Rápida de Hadamard)

HRTF Head Related Transfer Function (Función de Transferencia Relativa a la Cabeza) LSB Less Significant Bit (Bit Menos Significativo)

MEX MATLAB EXecutable (Fichero Ejecutable de MATLAB)

MLBS Maximum Length Sequence (Secuencia Binaria de Máxima Longitud) MLS Maximum Length Sequence (Secuencia de Máxima Longitud) MSB More Significant Bit (Bit de Mayor Peso)

PIR Periodic Impulse Response (Respuesta Impulsional Periódica) PN Pseudorandom Noise (Patrón de Números Pseudoaletorios) XOR eXclusive OR (“O” Exclusivo)

(7)

1. INTRODUCCIÓN Y OBJETIVOS

El software de procesado de datos para el prototipo inicial del proyecto EAV [1] lleva a cabo el cálculo de las funciones de transferencia de los sistemas altavoz-micrófono y auricular-micrófono para cada canal auditivo del voluntario. Ambos resultados son dependientes del equipo físico empleado en la generación/grabación de los sonidos de prueba (altavoces, auriculares, amplificadores y conversores). La función de transferencia altavoz-micrófono recoge, además, información acerca del entorno en que se realiza la medida, así como de la Función de Transferencia Relativa a la Cabeza (HRTF) del sujeto. Estos factores, sin embargo, no aparecen incluidos en la función de transferencia auricular-micrófono. Ambas funciones se combinan para obtener una pareja de filtros espacializadores (uno por canal auditivo) que permiten convertir la señal de prueba generada por el prototipo en un estímulo auditivo que es percibido por el voluntario como localizable en el espacio.

Resulta necesario generar tantas parejas de filtros espacializadores como posiciones espaciales (estereopíxels) se deseen distinguir. Es posible abarcar un amplio rango de posiciones, ya que el equipamiento de la sala del proyecto EAV permite variar la posición relativa del voluntario respecto a la matriz de altavoces presente. Esto, unido al hecho de que la generación de cada pareja de filtros espacializadores requiere el cálculo de cuatro funciones de transferencia, da lugar a que dicho proceso sea muy costoso en tiempo de cálculo.

La determinación de cada una de las cuatro funciones de transferencia anteriores requiere el cálculo de la respuesta impulsional de los sistemas altavoz-micrófono y auricular-micrófono. Esto se realiza generando señales de prueba en forma de ruido pseudoaleatorio, que es la versión analógica (obtenida mediante bloqueadores de orden cero) de una señal digital conocida como Patrón de Números Pseudoaleatorios (PN) o Secuencia de Máxima Longitud (MLS). Las MLS son emitidas a través de los altavoces y los auriculares y el estímulo finalmente percibido por el voluntario se registra mediante unos micrófonos situados a la entrada de sus canales auditivos. Este registro constituye la respuesta del sistema altavoz-micrófono o auricular-micrófono, según el caso, siendo la MLS la excitación del sistema.

Dado que la correlación circular renormalizada de una MLS simétrica de amplitud unidad y de la respuesta de un sistema a dicha MLS es una versión acoplada en alterna de la Respuesta Impulsional Periódica del Sistema (PIR) [2, apartado 1.2], el cálculo de la respuesta impulsional de los sistemas altavoz-micrófono y auricular-micrófono se reduce a la computación de una correlación circular por sistema y canal auditivo para cada estereopíxel. El software actualmente disponible en el proyecto EAV realiza esta tarea mediante la función corrcirc.m [3, apartado 4.5], escrita en MATLAB, que computa la correlación cruzada mediante un paso intermedio al dominio de la frecuencia:

   

 

Re ( ) Re ( *)

Re ) ,

( MLS y FFT

1

FFT MLS FFT y

corrcirc

(1)

Donde las secuencias MLS e y, de longitud de muestral L, son la excitación de prueba y la señal registrada por el micrófono respectivamente, mientras que la secuencia y* se construye de acuerdo con:

 

 

1 ...

1 ),1 (

0 ),0

* (

L k k L y

k

y y

(2)

(8)

Las siglas FFT denotan la Transformada Rápida de Fourier; Re es la función parte real y indica el producto de secuencias muestra a muestra.

Así pues, el cálculo de una correlación circular con el software actualmente disponible en el proyecto EAV requiere el cómputo de dos algoritmos FFT, de eficiencia nlog2n, y de una FFT inversa. Sin embargo, debido a las propiedades particulares de las MLS, resulta posible simplificar el proceso anterior reduciéndolo al cálculo de dos permutaciones y una única Transformada Rápida de Hadamard (FHT), también de eficiencia nlog2n. Según se describe en [4], para el caso de señales de excitación tipo MLS cabe expresar la correlación circular como un conjunto de sumas y diferencias que, convenientemente reordenado, permite su computación mediante el algoritmo FHT (un caso particular de la transformada Wavelet [9,10]) con un incremento notable de la eficiencia global.

Así pues, el presente documento recoge una implementación del método descrito en [4], adaptada a las necesidades del proyecto EAV. Se pretende mejorar en al menos un orden de magnitud el tiempo de proceso invertido en el cálculo de las respuestas impulsionales, con objeto de agilizar la generación de los filtros espacializadores. Para ello, se ha optado por sustituir la función corrcirc.m existente por un conjunto de dos rutinas (una de ellas codificada en MATLAB y la otra en ANSI C para mejorar su eficiencia).

El prototipo inicial del proyecto EAV emplea un computador industrial, Nécora, que se encarga de realizar el interfaz con los procesadores DSP del sistema de medida Hurón. Un segundo computador, conocido como Rascasio, ejecuta las aplicaciones del sistema de medida. Nécora emplea Windows 3.1, sistema operativo para el que se ha desarrollado el software Hurón. Rascasio, por el contrario, utiliza como sistema operativo Windows 95, bajo el que ejecuta MATLAB 4.2. Para esta última plataforma es para la que han de desarrollarse las rutinas que sustituirán a la función corrcirc.m. Sin embargo, en previsión de una futura actualización del equipamiento con el que cuenta el proyecto EAV, se han desarrollado paralelamente dos versiones de estas rutinas, capaces de funcionar bajo MATLAB 4.2 (versión actualmente instalada en el prototipo del proyecto EAV) y MATLAB 5.3 (de próxima instalación en el prototipo definitivo), habiéndose apreciado ventajas significativas en el rendimiento estas últimas.

(9)

2. DESCRIPCIÓN DEL ALGORITMO UTILIZADO

2.1 Expresión Matricial del PIR para Señales de Prueba de Tipo MLS

La función corrcirc.m utilizada por el software actual del proyecto EAV calcula la respuesta impulsional periódica (PIR)de los sistemas altavoz-micrófono y auricular-micrófono de acuerdo con la expresión que se indica [3, apartado 4.5]:

        

( )mod

, 0... 1

0 1

1 1

0

2    

 

L i

L j

i y j x x

i L

PIR L

j (3)

Donde x es la MLS simétrica de prueba, y es la secuencia de respuesta del sistema registrada por el micrófono y L es la longitud muestral de las secuencias.

Tal y como se describe en el anexo B.2.3, la expresión (3) es una renormalización de la correlación circular de las secuencias x e y que obedece, por un lado, a motivos de conveniencia matemática y, por otro, a la necesidad de corrección de las medidas obtenidas, ya que las MLS de prueba utilizadas en el proyecto EAV no tienen amplitud unidad (ver anexo B.2.1).

Con objeto de aplicar el algoritmo eficiente descrito en [4] al cálculo del PIR, es necesario reformular (3) introduciendo uno de los dos factores

 

0

1

x bajo el signo sumatorio, lo cual da lugar a:

     

'

  

( )mod

, 0... 1

0 1

1 1

0

 

L i

L j

i y j x x

i L PIR

L j

(4)

Donde x’ es la secuencia x normalizada, es decir, una MLS de amplitud unidad. Puesto que el número de entradas positivas de una MLS excede en uno al de entradas negativas (ver anexo B.2.1, cada término del sumatorio se expresa como la suma de

2

1

L muestras de y menos la suma de las

2

1

L muestras restantes. Las entradas concretas afectadas por un sigo u otro dependen del índice i.

En total, el número de adiciones/sustracciones a realizar para el cálculo del PIR resulta ser

L

2.

De acuerdo con [4], al ser x’ una MLS de amplitud unidad, el PIR puede expresarse como un producto matricial. Considerando la secuencia y como un vector columna y asociando adecuadamente los factores, se obtiene:

   

P S

H

S

Py

  

x

PIR L 2 2 L 1 1 1 0

1 1

(5)

La estructura de las matrices P1, P2 , S1 y S2, así como el método a seguir para su obtención, se describen en detalle en el anexo B.2.2. Del mismo modo, la morfología y propiedades de la matriz

1

HL , se hayan recogidas en el anexo B.1.1. No obstante, tanto para la aplicación práctica del

(10)

algoritmo como para la comprensión de las rutinas desarrolladas, reviste mayor importancia el estudio de la transformación que cada matriz representa:

- HL1 es la matriz de Hadamard de orden

L  1

en su forma normalizada. Aplicada a un vector de dimensión

L  1

, produce su Transformada Natural de Hadamard (ver anexo B.1.1), que es otro vector de la misma longitud. Precisamente, la ventaja fundamental de (5) radica en la posibilidad de computar la Transformada de Hadamard dada por el producto

H

L1

S

1

  P

1

y

mediante un algoritmo FHT [9], de elevada eficiencia. Con ello, el PIR del sistema pasa a calcularse definitivamente como:

   

P S

FHT

S

Py

 

x

PIR L 2 2 1 1

0 1 1

  (6)

Que es la expresión matricial en la que se basarán las rutinas desarrolladas en este documento.

- P1 y P2 son matrices de permutación, de orden

LL

. Aplicadas a un vector dado de dimensión L, producen otro vector de la misma dimensión pero cuyas componentes se encuentran en distinto orden.

Cada una de las muestras de la Transforma Natural de Hadamard de una secuencia, a excepción de la primera, es igual a la suma de

2

1

L muestras de dicha secuencia menos la suma de las

2

1

L muestras restantes, propiedad que comparte con los términos del sumatorio de la expresión (4). Gracias a ello, es posible obtener la correlación (4) como una reordenación, mediante la matriz de permutación P2 , de las componentes de la Transformada Natural de Hadamard de la secuencia y, previamente reordenada por P1.

- S1y S2 son matrices de adaptación de dimensiones, de orden

L 1

L y L L

1

respectivamente. El producto de S1 por un vector de dimensión L produce un nuevo vector, de dimensión

L  1

, cuya primera componente es nula. El resto de componentes son las del vector original, en el mismo orden. De forma similar, el producto de S2 por un vector de dimensión

 1

L

, origina un nuevo vector, de dimensión L, igual al vector original del que se ha suprimido la primera componente.

El algoritmo FHT sólo es aplicable a secuencias cuya longitud muestral L sea una potencia de 2 (ver descripción detallada de la FHT en el anexo B.1.2). Debido a que el proyecto EAV emplea señales de prueba de tipo MLS, la longitud de la secuencia y es necesariamente de la forma

1 2 

n

L

. Por este motivo, se añade una muestra adicional nula al principio del vector

P

1

y

, de dimensión L, mediante la matriz de adaptación de dimensiones S1. El vector resultante ya puede ser procesado mediante una FHT. A continuación se elimina del resultado la primera muestra, mediante S2, y se obtiene una secuencia de la longitud adecuada, L.

Recapitulando, el resultado (6) permite computar el PIR de un sistema (que, formulado según (4), requeriría

L

2 operaciones) calculando en su lugar la Transformada de Hadamard de un vector (lo cual requiere sólo Llog2L operaciones), dos permutaciones de L elementos, una operación de ampliación y otra de truncado de vectores.

(11)

Obviamente, las operaciones de permutación, ampliación y truncado no deben realizarse por medio de productos matriciales, en contra de lo que se indica en (6). En el proyecto EAV, se emplea una longitud muestral L de valor 16.383, lo cual hace prohibitivo el cómputo de estos productos, dado el tamaño de las matrices. Aunque esto no fuera así, el mero hecho de tener que realizar un alto número de multiplicaciones conduciría a una eficiencia muy inferior a la proporcionada por el algoritmo disponible actualmente. Por este motivo, todas las operaciones matriciales presentes en (6) han de llevarse a cabo de una forma computacionalmente más eficiente:

- Las permutaciones dadas por P1 y P2 se realizan mediante la permutación de los índices del vector sobre el que actúan. Para ello, la información de estas matrices se almacena de forma comprimida en los vectores de permutación P y 1* P respectivamente (ver anexo B.2.3).2* - Las transformaciones S1 y S2 se llevan a cabo directamente, ampliando o truncando el vector

afectado por ellas.

La mejora de la eficiencia obtenida al emplear la expresión (6) dependerá de la relación entre el tiempo de cálculo correspondiente a las operaciones dadas por P1, P2 , S1 y S2 frente al tiempo de cálculo total, así como de la eficiencia con que éstas hayan sido programadas.

Debe hacerse notar que las matrices P1 y P2 (y, por tanto, los vectores de permutación P y1*

*

P ) dependen exclusivamente de la MLS de prueba, mientras que 2 S1 y S2 son función tan sólo de la longitud de dicha MLS (ver anexo B.2.2). Puesto que el prototipo inicial del EAV emplea siempre la misma MLS para todas las medidas, sólo es necesario calcular la información de las permutaciones una vez en cada sesión. Así pues, resulta más eficiente separar el cálculo de los vectores de permutación del cálculo del PIR propiamente dicho. Esto origina dos algoritmos diferenciados.

Para una información más completa acerca de la expresión matricial del PIR de un sistema, consúltese el anexo B.2.2.

2.2 Algoritmo de Cálculo de los Vectores de Permutación

Los vectores de permutación P y 1* P contienen la información de las matrices 2* P1 y P2 de forma más eficiente en cuanto al uso de la memoria. Se trata de vectores dimensión L (frente al orden

L

L

de las matrices originales) cuya componente i-ésima indica el número de orden de la componente del vector original que pasará a ocupar la posición i-ésima en el vector permutado.

El algoritmo a seguir para la generación de los vectores de permutación se describe en detalle en el anexo B.2.3. Como punto de partida, es necesario disponer de la MLS de entrada x en su forma asimétrica, la cual denotaremos por MLBS. Para ello basta sustituir los términos negativos de la MLS de entrada por elementos 1 y los positivos por entradas 0:

  i ixsi ixsi i L

MLBS , ...1

0 0

0

1 

 

 

(7)

(12)

A modo de ejemplo, se indica este paso para una MLS de orden 3 y longitud 7 (se recuerda que la relación entre la longitud L y el orden n viene dada por

L  2

n

 1

):

MLS = -1 -1 -1 1 -1 1 1  MLBS = 1 1 1 0 1 0 0 (8) El vector de permutación P se obtiene recorriendo circularmente la MLBS hacia la derecha, a partir1* de la posición L n2, tomando grupos de n bits, donde n es el orden de la MLS. Si se denota por

Ei el valor decimal de estas etiquetas de n bits, las L componentes de P vienen dadas por:1*

 

i i L

P1* Ei  , 1.. (9)

El proceso descrito se concreta en el algoritmo de la figura 1.

DATOS DE ENTRADA:

- MLBS ASOCIADA A LA SECUENCIA DE PRUEBA x: MLBS

ALGORITMO:

 

 

Fin i i

j P

i i i MLBS

L j

Para n L i

j j

1 E

2 1 E

...

1 2

* 1

(Todos los incrementos circulares.)

DATOS DE SALIDA:

VECTOR DE PERMUTACIÓN 1: P1*

Figura 1: Algoritmo para la obtención del vector de permutación P .1*

Para mejor comprensión del algoritmo anterior, la figura 2 ejemplifica este proceso para la MLS de orden 3 dada en (8).

i MLBS Etiqueta 3 2 1 Valor decimal Componente

(13)

- --- --- --- --- 1 1 1 1 0 1 0 0 0 0 1  E1 1  P1*

 

1 1 2 1 1 1 0 1 0 0 0 1 1  E2 3 

 

3 2

*

1

P

3 1 1 1 0 1 0 0 1 1 1  E3 7 

 

7 3

*

1

P

4 1 1 1 0 1 0 0 1 1 0  E4 6  P1*

 

6 4 5 1 1 1 0 1 0 0 1 0 1  E5 5 

 

5 5

*

1

P

6 1 1 1 0 1 0 0 0 1 0  E6 2  P1*

 

2 6 7 1 1 1 0 1 0 0 1 0 0  E7 4  P1*

 

4 7

1 6 2 7 5 4 3

* 1P

Figura 2: Ejemplo del cálculo de P para la MLS de orden 3 dada en (8) por aplicación del1* algoritmo de la figura 1.

Una vez conocido P , el vector de permutación 1* P se construye tomando un subconjunto de n2* componentes de P , concretamente, las que ocupan las posiciones 1* p

1 2 4 ... 2n1

del

vector. Con ello se obtiene un conjunto de n posiciones

       

1* 1

* 1

* 1

*

1

1 2 4 ... 2

'  P P P P

n

p

que se va rotando circularmente hacia la izquierda sobre la MLBS para obtener sucesivos grupos de n bits. Denotando por Eiel valor decimal de las sucesivas etiquetas obtenidas, las componentes de P vienen dadas por:2*

 

i E i L

P2*i , 1.. (10)

El proceso descrito se concreta en el algoritmo de la figura 3.

DATOS DE ENTRADA:

(14)

- MLBS ASOCIADA A LA SECUENCIA DE PRUEBA x: MLBS

- VECTOR DE PERMUTACIÓN 1: P1*

ALGORITMO:

       

 

     

 

     

   

   

Fin

n p n p

p p

p p

E i P

n p p

p MLBS E

L i

Para

P P

P P

p

i i

n

1 ' '

...

1 2 ' 2 '

1 1

´ 1 '

' ...

2 ' 1 ' ...

1

2 ...

4 2

1 '

* 2

* 1 1

* 1

* 1

* 1

(Todos los incrementos circulares.)

DATOS DE SALIDA:

VECTOR DE PERMUTACIÓN 2: P2*

Figura 3: Algoritmo para la obtención del vector de permutación P .2*

Para mejor comprensión del algoritmo anterior, la figura 4 ejemplifica este proceso aplicado a la MLS de orden 3 dada en (8).

1 1

p

p

'1

 P

1*

  1  1

2 2

p

p

'2

 P

1*

  2  6

3 4

p

p

'3

 P

1*

  4  7

1 2 4 1 6 7 - - - - - - 1 1 1 0 1 0 0  1 1 1 0 1 0 0

i MLBS Etiqueta 3 2 1 Valor decimal Componente - --- --- ---

1 1 1 1 0 1 0 0 0 0 1 E1 1  P2*

 

1 1 2 1 1 1 0 1 0 0 0 1 0  E2 2  P2*

 

2 2

(15)

3 1 1 1 0 1 0 0 1 0 0  E3 4  P2*

 

3  4 4 1 1 1 0 1 0 0 0 1 1  E4 3 

 

4 3 P2*

5 1 1 1 0 1 0 0 1 1 0  E5 6 

 

5 6 P2*

6 1 1 1 0 1 0 0 1 1 1  E6 7  P2*

 

6 7 7 1 1 1 0 1 0 0 1 0 1  E7 5 

 

7 5 P2*

1 2 4 3 6 7 5

P2*

Figura 4: Ejemplo del cálculo de P para la MLS de orden 3 dada en (8) por aplicación del2* algoritmo de la figura 3.

Una explicación más detallada de los algoritmos descritos, se recoge en el anexo B.2.3.

2.3 Algoritmo de Cálculo del PIR del Sistema

Conocidos los vectores de permutación, el cálculo de la respuesta impulsional periódica se lleva a cabo traduciendo la expresión matricial (6) en un conjunto de pasos computacionalmente eficientes:

- En primer lugar, se reordenan las muestras de la secuencia de respuesta del sistema y de manera que cada componente de y pasa a ocupar la posición indicada por la componente de P que2* tiene el mismo número de orden. De este modo se obtiene una nueva secuencia y’. Esta reordenación equivale a la transformación matricial P1 de (6).

- Se incrementa la dimensión de y’ añadiendo una muestra inicial nula, lo cual equivale a aplicar la transformación matricial S1indicada en (6). Esto origina la secuencia y’’.

- Se calcula la FHT de y’’, obteniéndose una nueva secuencia y’’’. El cálculo de la FHT se lleva a cabo según el método descrito en el anexo B.1.2.

- Se elimina la primera muestra de y’’’, dando lugar a y(iv, con un resultado equivalente a aplicar la transformación matricial S2 de (6).

- Reordenando y(ivde acuerdo con el vector de permutación P de forma análoga a como se2* hizo con P , se obtiene una secuencia proporcional al PIR del sistema, 1* y(v. Este proceso es equivalente a aplicar la transformación P2 indicada en (6).

- Finalmente, se divide y(v por la amplitud de la MLS de entrada x y por la longitud muestral más una unidad, para obtener el PIR.

La expresión algorítmica del procedimiento descrito se recoge en la figura 5.

DATOS DE ENTRADA:

(16)

- SECUENCIA DE PRUEBA: x

- RESPUESTA DEL SISTEMA: y

- MATRICES DE PERMUTACIÓN: P1, P2

ALGORITMO:

1. y'

 

iy

P1*

 

i

, i1... L 2. y''

0 y'

3. y' ''FHT(y '')

4. y(iv

 

iy'''

i1

,i 1...L 5.

y

vxy

  i y

iv

  P

2*

  i , i 1 ... L

(

(

 

6. PIR L x

 

y(v

0 ) 1 (

1

 

DATOS DE SALIDA:

- PIR DEL SISTEMA:

PIR

Figura 5: Algoritmo de cálculo del PIR del sistema.

A modo de ejemplo, el algoritmo anterior se ilustra para la MLS de orden 3 dada en (8). Los vectores de permutación correspondientes ya han sido calculados en el apartado 2.2 y se asume, como respuesta del sistema, el vector:

1 2 1 1 2 1 0

y (11)

Los resultados obtenido se recogen en la figura 6:

 

 

:

1 1 2 0 2 1 1 0 '' :

1 1 2 0 2 1 1 ' :

1

* 1

FHT la de Cálculo

y S

Ampliación

y P

n Permutació

(17)

' '

y y''1 y''2 y ''3y' ''

0 1 =0+1 2=1+1 0=2-2

1 1=-1+2 -2=-2+0 -4=-4+0 -1 -2=0-2 -4=--1-3 -2=0-2

2 0=-1+1 0=-2-2 6=2+4

0 -1=0-1 0=1-1 4=2-(-2) -2 -3=-1-2 -2=-2-0 -4=-4-0 -1 2=0-(-2) 2=--1-(-3) 2=0-(-2) 1 -2=-1-1 4=2-(-2) -2=2-4

 

 

0,5 0,25 0,5 0,75 0,25 0,25 0,5

1 ) 1 7 ( : 1

4 2 2 6 4 2 4 :

2 2 4 4 6 2 4 :

(

* ( 2

( 2

 

 

v v

iv

y PIR

ión Normalizac

y P

n Permutació

y S

Truncado

Figura 6: Ejemplo de cálculo del PIR para la MLS dada en (8) y la respuesta del sistema (11).

Para una explicación más detallada del algoritmo de cálculo del PIR, véase el anexo B.2.3.

(18)

3. IMPLEMENTACIÓN

Una vez descritos los algoritmos necesarios, su implementación en cualquier lenguaje de programación es inmediata. En el caso concreto del proyecto EAV, se han desarrollado dos grupos de rutinas:

1. Rutina de cálculo de los vectores de permutación:

Su tiempo de ejecución no es crítico, dado que la MLS de prueba empleada en el proyecto EAV es siempre la misma, con lo que sólo es necesario calcular una vez los vectores P y 1* P y 2* almacenarlos en disco. Por ello, la versión definitiva de este algoritmo se ha escrito en MATLAB.

Se proporcionan dos versiones distintas de este conjunto de rutinas:

- Versión para MATLAB 4.2: comprende la función permut.m, escrita en código MATLAB.

Dado que la versión de MATLAB 4.2 empleada en el proyecto EAV carece de compilador integrado, no ha podido compilarse esta función en forma de DLL.

- Versión para MATLAB 5.3: se ha empleado el compilador mcc (versión 2.0) para generar una DLL de 32 bits a partir de la función permut.m. Esta DLL sustituye a la función MATLAB anterior y lleva por nombre permut.dll. Con este procedimiento, se ha conseguido una mejora significativa de la eficiencia.

2. Rutina de cálculo de la correlación circular:

El tiempo de computación del algoritmo de cálculo del PIR es un parámetro a minimizar. Por este motivo se ha pasado de una primera versión en MATLAB a una rutina optimizada escrita en C. Se realizó un intento inicial de compilar la rutina original en MATLAB, tal y como se hizo con permut.dll, pero los resultados no fueron satisfactorios.

De nuevo, se proporcionan dos versiones de la rutina en cuestión:

- Versión para MATLAB 4.2: MATLAB 4.2 no permite especificar el tipo de datos las matrices.

En consecuencia, los elementos de los vectores P y 1* P han de tratarse obligadamente2* como reales de doble precisión. Esto incide directamente sobre el rendimiento de la rutina en C que calcula la correlación circular, ccircfht.c, a que accede a los datos contenidos en P1* y P . Dichos accesos serían más eficientes (y se haría un mejor uso de la memoria) si los2* elementos de P y 1* P , que, de hecho, son enteros, pudiesen almacenarse como tales. La2* imposibilidad de hacer esto en MATLAB 4.2 reduce la eficiencia del algoritmo.

Con objeto de mejorar la velocidad y de evitar ciertos problemas de gestión de memoria bajo WINDOWS 3.1 (ver apartado 1.2), se ha compilado la rutina ccircfht.c, no como una DLL de 16 bits, sino como un programa reubicable en formato REX que se ejecuta en modo de 32 bit:

ccircfht.mex. El compilador empleado a tal efecto ha sido el WATCOM C/C++ versión 10.

- Versión para MATLAB 5.3: Esta versión del intérprete matemático ya permite el paso de los datos contenidos en los vectores P y 1* P a la función ccircfht.c en forma de elementos2* de tipo entero, con la consecuente mejora del rendimiento. En este caso, se ha empleado el compilador mcc 2.0 para generar una DLL de 32 bits: ccircfht.dll.

La figura 7 muestra un esquema explicativo del software desarrollado:

(19)

 

 

 

 

dll ccircfht MATLAB

rex ccircfht MATLAB PIRdel Cálculo

dll permut MATLAB

m permut MATLAB PyP de Cálculo Software

. :3.5

. :2.4

. :3.5

.

* :2.4

2

* 1

Figura 7: Esquema de las rutinas desarrolladas para el cálculo eficiente de la correlación circular.

3.1 Rutina de Cálculo de los Vectores de Permutación: permut.m

3.1.1 Prototipo de la Función y Descripción del Código Fuente

La rutina MATLAB que proporciona los vectores de permutación P y 1* P , permut.m, opera de2* acuerdo con los algoritmos expuestos en las figuras 3 y 5. El prototipo de la función es el indicado:

function [P1,P2]=permut(MLS,n) Los argumentos de entrada de permut.m se describen a continuación:

- MLS es un vector (fila o columna, indistintamente), que representa la secuencia de prueba x, de longitud L.

- n es el orden de la MLS de entrada, verificándose que:

L  2

n

 1

.

La función proporciona como salida los vectores de permutación P y 1* P en forma de vectores2* columna P1 y P2 .

El código fuente de permut.m es el mismo para las versiones compatibles con MATLAB 4.2 y MATLAB 5.3 y puede observarse en el listado 1.

function [P1,P2]=permut(MLS,n)

% Comprobar orden no nulo if (n==0)

disp([ 'Error: el orden de la MLS ha de ser mayor que cero']);

return end

(20)

% Comprobar longitud correcta L=length(MLS);

if (L~=2^n-1)

disp([ 'Error: la longitud de la MLS es ' num2str(L) ...

' y ha de ser ' num2str(2^n-1)]);

return end

% Convertir a vector columna MLS=MLS(:);

% Asegurar que la MLS contiene más términos negativos que positivos,

% de forma que, al convertirla a su forma asimétrica, haya más unos

% que ceros y el método basado en FHT sea aplicable if(sum(MLS)>0) % Mayoría de términos positivos MLS=-MLS; % Cambiar el signo de la secuencia end

% Cálculo de la forma asimétrica de la MLS

% (MLBS asociada)

MLS=MLS/max(MLS); % normalización al rango 0-1

MLS=1-MLS; % conversión de 1 a 0 y de -1 a 1

MLS=MLS/2; % renormalización al rango 0-1

% Matriz de cambio de base

base=(2.^(n-1:-1:0))'; % Primeras n potencias de 2

% Cálculo de P1

P1=zeros(1,L); % Preasignar tag=zeros(n,1); % Preasignar

% Primeras n etiquetas for i=1:n-1

% Cálculo de la etiqueta de la columna i-ésima tag=[MLS(L-n+i+1:L) ; MLS(1:i)];

% Construcción del vector de permutación de columnas P1(sum(tag.*base))=i;

end

% L-n etiquetas restantes for i=n:L

tag=MLS(i-n+1:i);

P1(sum(tag.*base))=i;

end

% Cálculo de P2

P2=zeros(1,L); % Preasignar pos=zeros(n,1); % Preasignar

pos=P1(base(n:-1:1))-1; % Cambio de base y cálculo del

% vector de posiciones inicial for i=1:L

% Cálculo de la etiqueta de la fila i-ésima tag(n:-1:1)=MLS(pos+1);

(21)

% Construcción del vector de permutación de filas P2(i)=sum(tag.*base);

% Recalcular vector de posiciones % (rotar circularmente a la izquierda) pos=rem(pos+L-1,L);

end

% Conversión a vectores columna P1=P1(:);

P2=P2(:);

return

% end function [P1,P2]=permut(MLS,n)

Listado 1: Código fuente completo de la función permut.m.

El dato de entrada n, ha de verificar nlog2(L1) y es utilizado internamente por la función permut.m para comprobar posibles errores en la longitud de la MLS de entrada, tal y como se muestra en el listado 2:

% Comprobar orden no nulo if (n==0)

disp([ 'Error: el orden de la MLS ha de ser mayor que cero']);

return end

% Comprobar longitud correcta L=length(MLS);

if (L~=2^n-1)

disp([ 'Error: la longitud de la MLS es ' num2str(L) ...

' y ha de ser ' num2str(2^n-1)]);

return end

Listado 2: Fragmento de código de permut.m que implementa la comprobación de errores en los parámetros pasados a la función.

La función permut.m ha de calcular, a partir de la MLS de entrada, la MLBS asociada a ella. Esta última se emplea como patrón para generar los vectores P y 1* P por medio de los algoritmos2* recogidos en las figuras 3 y 5.

Ahora bien, la MLS utilizada en el proyecto EAV se obtiene mediante la función mlbs de la librería Signal Processing Toolbox. Dicha rutina no obedece el convenio habitualmente aceptado en la bibliografía de referencia, según el cual el número de términos negativos de la MLS ha de exceder en uno al de términos positivos (ver anexo B.2.1). En consecuencia, es necesario adaptar la MLS de entrada al formato visto en el anexo B.2.1 (multiplicarla por –1) para, a continuación, extraer la secuencia MLBS asimétrica asociada a ella (convertir los elementos –1 en entradas 1 y los elementos 1 en entradas 0).

Para el caso de la MLS de orden 3 recogido en la figura B.1 (ver anexo B.2.1) la función mlbs de MATLAB proporciona la siguiente secuencia como resultado.:

(22)

S : 1 1 1 -1 1 -1 -1

La cual, tratada según el proceso descrito, da lugar a la MLBS original, vista en el ejemplo (8):

(-1)·S : -1 -1 -1 1 -1 1 1  1 1 1 0 1 0 0 1  0

-1  1

Al hacer esto, se está calculando, realmente, la correlación circular cambiada de signo, puesto que una de las secuencias se multiplica por –1 y la correlación circular es una operación lineal. En consecuencia, es necesario cambiar el signo del resultado final para llegar así al valor correcto del PIR.

Con objeto de lograr la máxima generalidad y hacer las rutinas diseñadas independientes de la forma en que ha sido genera la MLS de entrada, la función permut.m tiene en cuenta estas cuestiones mediante el fragmento de código del listado 3:

% Asegurar que la MLS contiene más términos

% negativos que positivos, de forma que,

% al convertirla a su forma asimétrica, haya más unos

% que ceros y el método basado en FHT sea aplicable if(sum(MLS)>0) % Mayoría de términos positivos MLS=-MLS; % Cambiar el signo de la secuencia end

% Cálculo de la forma asimétrica de la MLS

% (MLBS asociada)

MLS=MLS/max(MLS); % normalización al rango 0-1

MLS=1-MLS; % conversión de 1 a 0 y de -1 a 1

MLS=MLS/2; % renormalización al rango 0-1

Listado 3: Fragmento de código de permut.m que lleva a cabo el cálculo de la MLBS asociada a la secuencia de entrada.

- En primer lugar, se suman todos los términos de la MLS de entrada. Un resultado positivo, indica que la secuencia tiene mayoría de términos positivos, con lo que no resulta necesario cambiar su signo. En caso contrario, la secuencia se multiplica por –1.

- A continuación, se lleva a cabo la sustitución eficiente de elementos –1 y 1 por entradas 1 y 0 respectivamente, mediante operaciones matemáticas.

A partir de la MLBS original calculada, que se almacena en la propia variable de entrada (MLS) para optimizar memoria, se aplican los algoritmos descritos en las figuras 3 y 5. La traducción a código MATLAB de los mismo se indica en el listado 4:

% Matriz de cambio de base

base=(2.^(n-1:-1:0))'; % Primeras n potencias de 2

% Cálculo de P1

P1=zeros(1,L); % Preasignar

tag=zeros(n,1); % Preasignar

% Primeras n etiquetas for i=1:n-1

% Cálculo de la etiqueta de la columna i-ésima tag=[MLS(L-n+i+1:L) ; MLS(1:i)];

% Construcción del vector de permutación de columnas P1(sum(tag.*base))=i;

(23)

end

% L-n etiquetas restantes for i=n:L

tag=MLS(i-n+1:i);

P1(sum(tag.*base))=i;

end

% Cálculo de P2

P2=zeros(1,L); % Preasignar

pos=zeros(n,1); % Preasignar

pos=P1(base(n:-1:1))-1; % Cambio de base y cálculo del

% vector de posiciones inicial for i=1:L

% Cálculo de la etiqueta de la fila i-ésima tag(n:-1:1)=MLS(pos+1);

% Construcción del vector de permutación de filas P2(i)=sum(tag.*base);

% Recalcular vector de posiciones % (rotar circularmente a la izquierda) pos=rem(pos+L-1,L);

end

Listado 4: Fragmento de código de permut.m que construye los vectores de permutación P y1*

*

P .2

La necesaria conversión entre los números binarios de las etiquetas de filas y columnas y su valor decimal se ha llevado a cabo prescindiendo de las funciones de MATLAB para tratamiento de cadenas y conversión de bases, por haber resultado ese procedimiento, en las pruebas, más lento. En el listado 4 se define un vector base formado por la n primeras potencias de 2, ordenadas de mayor a menor:

base=(2.^(n-1:-1:0))';

Así, para obtener el valor decimal de una etiqueta binaria dada, tag, basta multiplicar elemento a elemento ambos vectores y sumar el resultado de todos los productos parciales:

sum(tag.*base)

A la hora de analizar la parte del listado 4 que calcula el vector de permutación P , debe tenerse en2* cuenta que la primera posición de un vector, en MATLAB, es la número 1. Sin embargo, para que una tabla de índices, pos, pueda incrementarme de forma circular mediante operaciones basadas en el módulo de una división (sentencia rem) es necesario que la primera posición se denote por 0. En consecuencia, las posiciones indicadas por pos se convierten a índices de tipo MATLAB incrementándolas en una unidad.

Ha sido necesario establecer un formato de intercambio de datos entre las distintas rutinas diseñadas.

Se ha optado por el siguiente convenio:

- Cada rutina ha de ser capaz de recibir los datos de entrada tanto en formato de vector fila como de vector columna (internamente, la rutina los convierte y manipula en forma de columna).

- Las rutinas suministran los resultados de salida en forma de vector columna.

(24)

Este es el convenio más usual en aplicaciones para MATLAB. La conversión de entradas y salidas a vectores columna se ha implementado eficientemente en permut.m como se indica en el listado 5:

% Convertir a vector columna MLS=MLS(:);

...

% Conversión a vectores columna P1=P1(:);

P2=P2(:);

Listado 5: Fragmento de código de permut.m que implementa la conversión a vectores columna de la entrada y las salidas.

El rendimiento de la rutina permut.m se ha incrementado preasignando espacio para las matrices utilizadas [11, pág. 4-27]. Aunque MATLAB permite que las matrices definidas crezcan dinámicamente, esto requiere que, cada vez que tiene lugar una asignación del tipo A(i)=valor, donde el índice i excede las dimensiones actuales de la matriz A, sea necesario reasignar memoria para A y, en algunos casos, copiar A una nueva zona de la memoria. Para evitar estas operaciones, basta asignar a priori espacio para la matriz, si su tamaño final es conocido. Esto se lleva a cabo en la función permut.m inicializando las variables P1,P2,tag y pos con elementos nulos (ver listado 6):

P1=zeros(1,L); % Preasignar tag=zeros(n,1); % Preasignar

...

P2=zeros(1,L); % Preasignar pos=zeros(n,1); % Preasignar

Listado 6: Fragmento de código de permut.m que optimiza el rendimiento por preasignación de variables.

3.1.2 Compilación de la Rutina permut.m para MATLAB 5.3

La versión disponible de MATLAB 4.2 en el proyecto EAV no dispone de compilador, por lo que no ha sido posible convertir la función permut.m en una DLL de 16 bits ejecutable bajo MATLAB 4.2, lo cual habría mejorado parcialmente su rendimiento. Sin embargo, el paquete de software MATLAB 5.3, de reciente adquisición sí incluye un compilador: la utilidad mcc en sus versiones 2.0 y 1.2. Esta aplicación es capaz de traducir un fichero en código MATLAB a lenguaje C o C++ (a elección del usuario). El fuente en C/C++ generado es convertido automáticamente en un fichero ejecutable de MATLAB (fichero MEX), es decir, una DLL de 32 bits, mediante un compilador externo.

Las distintas alternativas y opciones de compilación disponibles se comparan en el anexo C en función de su rendimiento. De acuerdo con los resultados de esta discusión, la función permut.m se ha compilado finalmente mediante la utilidad mcc 1.2, generando código intermedio C y activando las opciones de optimización de código –i y –r. La primera evita que se compruebe en tiempo de ejecución si los índices de las matrices se encuentran dentro de rango. La segunda, evita que se compile código para el tratamiento de la parte imaginaria de los datos, que se asumen reales.

Para compilar la función permut.m, se ejecuta, desde la línea de comandos de MATLAB 5.3, la sentencia:

mcc –V1.2 –r –i permut

El proceso de compilación crea, en el directorio actual, la versión ejecutable de la función permut.dll.

El compilador externo utilizado ha sido el Microsoft Visual C/C++ 5.0.

(25)

3.2 Rutina de Cálculo del PIR: ccircfht.c

3.2.1 Prototipo de la Función y Descripción del Código Fuente

A la hora de desarrollar la rutina de cálculo del PIR se realizó un primer intento de escribir dicha función en código MATLAB. Esta línea de desarrollo dio lugar a una serie de funciones en MATLAB cuyo rendimiento no satisfizo las expectativas del proyecto (ver anexo D.1). La eficiencia de las rutinas desarrolladas resultó ser inferior al del algoritmo ya disponible en el proyecto EAV. Ello se debe a que el algoritmo preexistente se basa en la transformada FFT que, en las librerías de MATLAB, se encuentra compilada en forma de algoritmo propietario, escrito en C y ensamblador. El paso siguiente consistió en compilar las rutinas escritas para MATLAB 5.3, pero los resultados (ver anexo D.1) no evidenciaron una mejora significativa.

Finalmente, se decidió rescribir en C la rutina de cálculo del PIR y compilarla como fichero ejecutable de MATLAB (MEX). Diversos algoritmos y estructuras de datos fueron ensayados con objeto de obtener aquel cuya eficiencia fuera máxima (ver anexo D.2). Las rutinas definitivamente adoptadas, se describen en este apartado.

MATLAB proporciona un conjunto de ficheros de cabecera (mex.h y matrix.h) que suministran una serie de funciones para que una aplicación escrita en C pueda acceder a los métodos internos del intérprete con objeto de crear, manipular o destruir matrices, así como llamar a funciones internas de MATLAB. Un fichero fuente escrito en C que incluya los citados ficheros de cabecera, una vez compilado y enlazado con las librerías adecuadas, se convierte en un fichero MEX, que puede ser llamado directamente desde la línea de comandos. Esta es la forma en que se han compilado las rutinas descritas en este apartado.

Desgraciadamente, los ficheros de cabecera mex.h y matrix.h proporcionados por las versiones 4.2 y 5.3 de MATLAB son incompatibles entre sí, lo que obliga a escribir dos versiones distintas de la rutina C de cálculo del PIR: ccircfht.c. El código fuente de esta función para MATLAB 4.2 se indica en el listado 7.

#include <math.h>

#include "mex.h"

/* Argumentos de entrada */

#define INPUT_MLS prhs[0] /* Vector 'MLS' de la llamada a función desde MATLAB

*/

#define INPUT_y prhs[1] /* Vector 'y' de la llamada a función desde MATLAB */

#define INPUT_P1 prhs[2] /* Vector 'P1' de la llamada a función desde MATLAB*/

#define INPUT_P2 prhs[3] /* Vector 'n' de la llamada a función desde MATLAB */

#define INPUT_n prhs[4] /*Argumento 'n' de la llamada a función desde MATLAB*/

/* Argumentos de salida */

#define OUTPUT_PIR plhs[0] /* Vector 'PIR' de la llamada a función desde MATLAB

*/

/* Función computacional: FHT*/

(26)

static void FHT(double **hadamard, double **swap, int n, int half_length) {

double *org, *dest1, *dest2, *aux, x1, x2;

int i,j;

for(i=1; i<=n; i++) {

/* Intercambiar buffers 'hadamard' y 'swap' */

aux = *hadamard;

*hadamard = *swap; /* El buffer de destino, 'hadamard', apunta al espacio de intercambio, ocupado por el resultado de hace dos iteraciones */

*swap = aux; /* El buffer auxiliar apunta al resultado anterior, que será la entrada de la iteración actual */

/* Inicializar iteración FHT*/

org = *swap; /* org apunta al vector resultado de la iteración anterior */

dest1 = *hadamard; /* dest1 apunta a la primera mitad del buffer de destino */

dest2 = dest1 + half_length; /* dest2 apunta a la segunda mitad del buffer de destino */

/* Ejecutar iteración*/

for(j=1; j<=half_length; j++) {

x1 = *org++; /* Leer el primer y segundo elemento del par y */

x2 = *org++; /* avanzar al par siguiente */

*dest1++ = x1 + x2; /* Calcular la suma y diferencia del par de elementos */

*dest2++ = x1 - x2; /* leídos y almacenarlas en el buffer de destino */

} } return;

}

/* Función de interfaz con MATLAB */

void mexFunction(int nlhs, Matrix *plhs[], int nrhs, const Matrix *prhs[]) {

double *mls, *hadamard, *aux, *h, *y, *p, sum = 0.0, k;

int i, ext_size;

/* Chequeo de parámetros */

if (nrhs != 5)

mexErrMsgTxt("FHT requires five input arguments."); /* Cinco parámetros de entrada*/

else if (nlhs > 1)

mexErrMsgTxt("FHT requires one output argument."); /* Un parámetro de salida */

ext_size = mxGetM(INPUT_MLS) * mxGetN(INPUT_MLS) +1; /* ext_size = L + 1 */

y = mxGetPr(INPUT_y); /* Obtener puntero 'y' a la respuesta del sistema 'y' */

p = mxGetPr(INPUT_P1); /* Obtener puntero 'p' al vector de permutación 'P1' */

(27)

/* Incrementar dimensión y trasponer */

/* Reservar espacio en memoria para el buffer 'hadamard', de longitud L + 1 */

h = hadamard = (double *) mxCalloc(ext_size, sizeof(double));

/* Inicializar primer elemento (elemento extra) del buffer a 0.0 */

*h++ = 0.0;

/* Trasponer vector 'y' almacenando el resultado en el buffer 'hadamard' */

for(i = 1; i < ext_size; i++) *h++ = *(y + (int) *p++ -1);

/* Calcular FHT */

/* Reservar espacio en memoria para un buffer auxiliar 'aux' de longitud L + 1 */

aux = (double *) mxCalloc(ext_size, sizeof(double));

/* Calcular la FHT del vector almacenado en el buffer 'hadamard' empleando el buffer 'aux' como buffer de intercambio */

FHT(&hadamard, &aux, (int) *mxGetPr(INPUT_n), ext_size>>1);

/* Liberar buffer auxiliar */

mxFree(aux);

/* Calcular constante de renormalización para el PIR*/

/* Obtener puntero 'h' a la secuencia de entrada al sistema 'MLS' */

h = mls = mxGetPr(INPUT_MLS);

/* Calcular suma de los términos de la MLS */

for(i=1; i < ext_size; i++) sum += *h++;

/* Si la suma es mayor que 0, la MLS fue obtenida mediante la función mlbs de MATLAB y el signo de sus términos está invertido respecto al criteri standard. De ser así,

el PIR resultado tiene el signo cambiado, lo cual se tiene en cuenta cambiando el signo de la constante de renormalización */

k = (sum > 0.0) ? -fabs(*mls) * ext_size : fabs(*mls) * ext_size;

/* Trasponer, normalizar y Corregir el signo */

/* Reservar memoria para el vector PIR, en formato MATLAB, de longitud L */

OUTPUT_PIR = mxCreateFull(ext_size - 1, 1, REAL);

h = mxGetPr(OUTPUT_PIR); /* Obtener puntero h a la zona de datos del vector PIR */

p = mxGetPr(INPUT_P2); /* Obtener puntero p al vector de permutación P2 */

/* Copiar el vector almacenado en el buffer 'hadamard' transponiéndolo y renormalizándolo al mismo tiempo. Se omite copiar, en el proceso, la primera muestra (muestra adicional) */

for(i = 1; i < ext_size; i++)

*h++ = *(hadamard + (int) *p++)/k;

(28)

/* Liberar el buffer 'hadamard' */

mxFree(hadamard);

return;

}

Listado 7: Código fuente de la rutina ccircfht.c compatible con MATLAB 4.2

El código fuente de ccircfht.c correspondiente a MATLAB 5.3 se encuentra recogido en el listado 8.

#include <math.h>

#include "mex.h"

/* Argumentos de entrada */

#define INPUT_MLS prhs[0] /* Vector 'MLS' de la llamada a función desdeMATLAB*/

#define INPUT_y prhs[1] /* Vector 'y' de la llamada a función desde MATLAB */

#define INPUT_P1 prhs[2] /* Vector 'P1' de la llamada a función desde MATLAB */

#define INPUT_P2 prhs[3] /* Vector 'n' de la llamada a función desde MATLAB */

#define INPUT_n prhs[4] /* Argumento 'n' de la llamada a función desdeMATLAB*/

/* Argumentos de salida */

#define OUTPUT_PIR plhs[0] /* Vector 'PIR' de la llamada a función desde MATLAB */

/* Función computacional: FHT*/

static void FHT(double **hadamard, double **swap, int n, int half_length) {

double *org, *dest1, *dest2, *aux, x1, x2;

int i,j;

for(i=1; i<=n; i++) {

/* Intercambiar buffers 'hadamard' y 'swap' */

aux = *hadamard;

*hadamard = *swap; /* El buffer de destino, 'hadamard', apunta al espacio de

intercambio, ocupado por el resultado de hace dos iteraciones */

*swap = aux; /* El buffer auxiliar apunta al resultado anterior, que será la entrada de la iteración actual */

/* Inicializar iteración FHT */

*swap = aux;

org = *swap; /* org apunta al vector resultado de la iteración anterior */

dest1 = *hadamard; /* dest1 apunta a la primera mitad del buffer de destino */

dest2 = dest1 + half_length; /* dest2 apunta a la segunda mitad del buffer de destino */

/* Ejecutar iteración*/

for(j=1; j<=half_length; j++) {

x1 = *org++; /* Leer el primer y segundo elemento del par y */

(29)

x2 = *org++; /* avanzar al par siguiente */

*dest1++ = x1 + x2; /* Calcular la suma y diferencia del par de elementos */

*dest2++ = x1 - x2; /* leidos y almacenarlas en el buffer de destino */

} } return;

}

/* Función de interfaz con MATLAB */

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {

double *mls, *hadamard, *aux, *h, *y, sum = 0.0, k;

unsigned short int *p;

int i, ext_size;

/* Chequeo de parámetros */

if (nrhs != 5)

mexErrMsgTxt("FHT requires five input arguments."); /* Cinco parámetros de entrada*/

else if (nlhs > 1)

mexErrMsgTxt("FHT requires one output argument."); /* Un parámetro de salida */

ext_size = mxGetM(INPUT_MLS) * mxGetN(INPUT_MLS) +1; /* ext_size = L + 1 */

y = mxGetPr(INPUT_y);

p = (unsigned short int *) mxGetPr(INPUT_P1); /* Obtener puntero 'p' al vector de permutación 'P1' */

/* Incrementar dimensión y trasponer */

/* Reservar espacio en memoria para el buffer 'hadamard', de longitud L + 1 */

h = hadamard = (double *) mxCalloc(ext_size, sizeof(double));

/* Inicializar primer elemento (elemento extra) del buffer a 0.0 */

*h++ = 0.0;

/* Trasponer vector 'y' almacenando el resultado en el buffer 'hadamard' */

for(i = 1; i < ext_size; i++) *h++ = *(y + *p++ -1);

/* Calcular FHT */

/* Reservar espacio en memoria para un buffer auxiliar 'aux' de longitud L + 1 */

aux = (double *) mxCalloc(ext_size, sizeof(double));

/* Calcular la FHT del vector almacenado en el buffer 'hadamard' empleando el buffer 'aux' como buffer de intercambio */

FHT(&hadamard, &aux, (int) *mxGetPr(INPUT_n), ext_size>>1);

/* Liberar buffer auxiliar */

mxFree(aux);

Referencias

Outline

Documento similar