Pasar una matriz de floats a una función (Solucionado)

Hola!

Para construir unos filtros de kalman estoy programando unas funciones para trabajar con las matrices. Y no tengo mucha experiencia con Arduino / C++

Como en ocasiones el filtro trabajará con matrices de 2x2 o de 3x3 me gustaría que el tamaño de los arrays no estuviese hardcoded en la definición de la función, por lo que he intentado esto:

float m1[2][2]= {
      {2.0, 1.0},
      {5.0, 3.0}
     };
float m2[2][2]={
      {1.0, 0.0},
      {0.0, 1.0}
     };
     

float a[2][2]={0};


void setup() {

  Serial.begin(9600);

}

void loop() {

 // multiplico
  matmult(m1, m2, a, 2);

}

void matmult(const float** matrix1, const float** matrix2, float** matres, const int n){
  

  int i,j,k;

  for (i = 0; i<n; ++i){
    for(j = 0; j<n; ++j){
      matres[i][j]=0;
      for(k = 0; k<n; ++k){
        matres[i][j]+= matrix1[i][k]*matrix2[k][j];        
      }
    }
  } 

}

y obtengo el siguiente error

sketch_matmult:25: error: cannot convert 'float (*)[2]' to 'const float**' for argument '1' to 'void matmult(const float**, const float**, float**, int)'

No tengo muy claro como solucionarlo. La verdad es que lo he visto hacer así y la opción que se me ocurre es que quizá el problema esté en la definición de la matriz como un array "rígido".

Obviamente, si declaro la función así:

void matmult(const float matrix1[2][2], const float matrix2[2][2], float matres[2][2], const int n){

No tengo el problema, pero me gustaría que la función fuese más flexible.

Muchas gracias.


Solucionado por surbyte:

Era necesario declarar las variables como:

float **m1;
float **m2;
float **a;
byte nrows = 2;
byte ncolumns = 2;

Y alocatarlas en el setup así:

 m1 = (float **) malloc(nrows * sizeof(float));
  for(int i=0; i<ncolumns; i++) {
       m1[i] = (float *) malloc(ncolumns * sizeof(float));
  }

y si pones

void matmult(const float matrix1[][], const float matrix2[][], float matres[][], const int n){

Gracias por el apunte!

Me dice que todas las dimensiones salvo la primera tienen que estar definidas:

sketch_matmult:6: error: declaration of 'matrix1' as multidimensional array must have bounds for all dimensions except the first
sketch_matmult:6: error: expected ')' before ',' token
sketch_matmult:6: error: expected unqualified-id before 'const'
sketch_matmult:40: error: declaration of 'matrix1' as multidimensional array must have bounds for all dimensions except the first
sketch_matmult:40: error: expected ')' before ',' token
sketch_matmult:40: error: expected unqualified-id before 'const'
declaration of 'matrix1' as multidimensional array must have bounds for all dimensions except the first

vamos, que estamos en las mismas, porque si la cuestion es que puedo pasarle matrices como matrix[][2] es igual de rígido para el código :frowning:

La verdad es que me extraña, porque esa solución que comentas la he visto en alguna página en mi peregrinación para sacar la solución

He encontrado un tema parecido en inglés:

http://forum.arduino.cc/index.php?topic=77312.0

Y entiendo yo que lo que está haciendo es el equivalente en mi código a esto:

float m1[2][2]= {
      {2.0, 1.0},
      {5.0, 3.0}
     };
float m2[2][2]={
      {1.0, 0.0},
      {0.0, 1.0}
     };
     

float a[2][2]={0};

float *pm1=&m1;
float *pm2=&m2;
float *pa=&a;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  

}

void loop() {
  // put your main code here, to run repeatedly:
  matmult(pm1, pm2, pa,2);
  Serial.print(a[0][0]);
  Serial.print(" ");
  Serial.print(a[0][1]);
  Serial.print("\n");
  Serial.print(a[1][0]);
  Serial.print(" ");
  Serial.print(a[1][1]);
  Serial.print("\n");
  Serial.print("----");
  
  delay(1000);

}

[b]void matmult(const float* matrix1, const float* matrix2, float* matres, const int n){
  [/b]

  int i,j,k;
  
  for (i = 0; i<n; ++i){
    for(j = 0; j<n; ++j){
      matres[i][j]=0;
      for(k = 0; k<n; ++k){
        matres[i][j]+= matrix1[i][k]*matrix2[k][j];        
      }
    }
  } 
}

Sin embargo a mi me da este error al compilar:

sketch_matmult:15: error:[b] cannot convert 'float (*)[2][2]' to 'float*' in initialization[/b]
sketch_matmult:16: error: cannot convert 'float (*)[2][2]' to 'float*' in initialization
sketch_matmult:17: error: cannot convert 'float (*)[2][2]' to 'float*' in initialization
sketch_matmult.ino: In function 'void matmult(const float*, const float*, float*, int)':
sketch_matmult:53: error: invalid types 'float[int]' for array subscript
sketch_matmult:55: error: invalid types 'float[int]' for array subscript
sketch_matmult:55: error: invalid types 'const float[int]' for array subscript
sketch_matmult:55: error: invalid types 'const float[int]' for array subscript
cannot convert 'float (*)[2][2]' to 'float*' in initialization

Realmente en ese código me extraña la definición de los punteros, pues entiendo que tiene que ser "**", es decir, un puntero de punteros por tener dos dimensiones, pero termino hacerlo funcionar.

Uy, que me pierdo en el código, resumo los cambios:

He creado estos punteros:

float *pm1=&m1;
float *pm2=&m2;
float *pa=&a;

Defino la función así:

void matmult(const float* matrix1, const float* matrix2, float* matres, const int n){

Y la llamo así:

  matmult(pm1, pm2, pa,2);

Bueno aunque no definí los elementos de las matrices (te lo dejo a ti) resolví tu problema
Espero te guste la solución.
Es completamente dinámica.
Si la matriz es cuadrada puedes simplificar nrows y ncolumns

float **m1;
float **m2;
float **a;
byte nrows = 2; 
byte ncolumns = 2;

void setup() {

  Serial.begin(9600);
  m1 = (float **) malloc(nrows * sizeof(float));
  for(int i=0; i<ncolumns; i++) {
 m1[i] = (float *) malloc(ncolumns * sizeof(float));
  }

}

void loop() {

 // multiplico
  matmult(m1, m2, a, 2);

}

void matmult(float **matrix1, float **matrix2, float **matres, int n){
  

  int i,j,k;

  for (i = 0; i<n; ++i){
    for(j = 0; j<n; ++j){
      matres[i][j]=0;
      for(k = 0; k<n; ++k){
        matres[i][j]+= matrix1[i][k]*matrix2[k][j];        
      }
    }
  } 

}

Pongo un enfoque distinto que tal vez te pueda ayudar. No lo he probado, pero creo que es bastante entendible. El quid de la cuestión es que pasamos una matriz de una sola dimensión:

void setup()
{
  float m1[4] = {
    2.0, 1.0,
    5.0, 3.0
  };
  float m2[9] = {
    1.0, 0.0, 0.0,
    1.0, 0.0, 0.0,
    0.0, 1.0, 1.0
  };
  matmult(m1, 2);
  matmult(m2, 3);
}
void loop()
{

}
void matmult(float matriz[], int elementos) {
  for (int i = 0; i < elementos; i++) {
    for (int j = 0; j < elementos; j++) {
      Serial.print(matriz[i*elementos+j]);
      Serial.print(",");
    }
    Serial.println();
  }
}

Muchas gracias Surbyte, funciona perfectamente!!

Noter: también era una opción muy interesante, gracias!