2.3.5 Matriz de Hilbert

void asm_hilbert(int ordem, float matriz[ordem][ordem])

Wolfram Mathematica Matriz Hilbert
Wolfram Mathematica Matriz Hilbert

Função para atribuir valores a uma matriz de Hilbert

/**
 * @file    asm_hilbert.s
 * @author  Reficio
 * @version 1.0
 * 
 * @section DESCRIPTION
 *
 * Função para atribuir valores a uma matriz de Hilbert.
 *
 * Em álgebra linear, uma matriz de Hilbert, introduzida por
 * Hilbert (1894), é uma matriz quadrada com os elementos sendo
 * as frações unitárias:
 *
 * Hij = 1 / (i + j - 1)
 *
 * onde i e j variam de 1 até a ordem da matriz.
 *
 * @param  1 ordem da matriz quadrada
 * @param  2 endereço da matriz
 *
 * @see Hilbert matrix https://en.wikipedia.org/wiki/Hilbert_matrix
 */

// Nova sintaxe unificada

.syntax unified

// Dados 

.data

.align
um:     .float  1.0             // Dividendo

// Código

.text
.global asm_hilbert
.type asm_hilbert, %function

asm_hilbert:

        PUSH    {R4-R11, LR}    // Salvar R4 a R11 e LR (Link Register) na pilha.

        MOV     R8, 0           // R8 = Número da Linha = i
        MOV     R9, 0           // R9 = Número da Coluna = j
        MOV     R10, R1         // R10 = Endereço da matriz
        MOV     R11, R0         // R11 = Ordem da matriz quadrada
        LDR     R7, =um         // R7 -> um
        FLDS    S14, [R7]       // S14 = 1.0 = Dividendo
giro:                           // Loop nos elementos da matriz
        MOV     R5, R11         // R5 = número de colunas
        MLA     R6, R8, R5, R9  // R6 = Posição na matriz = j + (i x COLUNAS)
        MOV     R6, R6, LSL 2   // R6 = R6 x 4 = Deslocamento na matriz em bytes
        MOV     R0, R10         // R0 -> Início da matriz
        ADD     R0, R0, R6      // R0 -> Posição do elemento na matriz
        ADD     R1, R8, R9      // R1 = i + j
        ADD     R1, 1           // R1 = i + j + 1 (i e j começam em zero, não em 1)
        FMSR    S15, R1         // S15 = R1 (sem conversão)
        FSITOS  S15, S15        // Converter de inteiro para ponto flutuante
        FDIVS   S15, S14, S15   // S15 = Hij = 1 / (i + j + 1)
        FSTS    S15, [R0]       // Armazenar o quociente na matriz
        ADD     R9, 1           // Próxima coluna
        CMP     R9, R11         // Comparar o nº da coluna com o nº de colunas
        BLT     giro            // Se for menor processar a próxima coluna
        MOV     R9, 0           // R9 = Número da coluna = Primeira coluna
        ADD     R8, 1           // R8 = Próxima linha
        CMP     R8, R11         // Comparar o nº da linha com o nº de linhas
        BLT     giro            // Se for menor processar a próxima linha

end:

        POP     {R4-R11, PC}    // Trazer R4 a R11 e PC (Program Counter) da pilha.

Programa em C para testar a função:

/**
 * @file    hilbert.c
 * @author  Reficio
 * @version 1.0
 * 
 * @section DESCRIPTION
 * 
 * Este programa tem por finalidade chamar a função "asm_hilbert",
 * que atribui valores a uma matriz de Hilbert, para fins de teste
 * da função.
 * 
 */

#include <stdio.h>

extern void asm_hilbert(int ordem, float matriz[ordem][ordem]);

void print(int ordem, float matriz[ordem][ordem]) {
        
        int linha, coluna;

        for (linha = 0; linha < ordem; linha++) {
                for (coluna = 0; coluna < ordem; coluna++) {
                        printf("%8.4f", matriz[linha][coluna]);
                }
                printf("\n");
        }

        return;
}

void main () {
        int ordem = 10;
        float hilbert [10][10];
        // Inicializar a matriz
        asm_hilbert(ordem, hilbert);
        // Mostrar a matriz inicializada
        print(ordem, hilbert);
}

Makefile:

hilbert: hilbert.c asm_hilbert.s
	gcc -o hilbert hilbert.c asm_hilbert.s
clean:
	rm hilbert

Construção e execução:

pi@raspberrypi:~/assembly/hilbert $ make clean
rm hilbert

pi@raspberrypi:~/assembly/hilbert $ make
gcc -o hilbert hilbert.c asm_hilbert.s

pi@raspberrypi:~/assembly/hilbert $ ./hilbert 
  1.0000  0.5000  0.3333  0.2500  0.2000  0.1667  0.1429  0.1250  0.1111  0.1000
  0.5000  0.3333  0.2500  0.2000  0.1667  0.1429  0.1250  0.1111  0.1000  0.0909
  0.3333  0.2500  0.2000  0.1667  0.1429  0.1250  0.1111  0.1000  0.0909  0.0833
  0.2500  0.2000  0.1667  0.1429  0.1250  0.1111  0.1000  0.0909  0.0833  0.0769
  0.2000  0.1667  0.1429  0.1250  0.1111  0.1000  0.0909  0.0833  0.0769  0.0714
  0.1667  0.1429  0.1250  0.1111  0.1000  0.0909  0.0833  0.0769  0.0714  0.0667
  0.1429  0.1250  0.1111  0.1000  0.0909  0.0833  0.0769  0.0714  0.0667  0.0625
  0.1250  0.1111  0.1000  0.0909  0.0833  0.0769  0.0714  0.0667  0.0625  0.0588
  0.1111  0.1000  0.0909  0.0833  0.0769  0.0714  0.0667  0.0625  0.0588  0.0556
  0.1000  0.0909  0.0833  0.0769  0.0714  0.0667  0.0625  0.0588  0.0556  0.0526