double Matrix::distance(Matrix & B) {
    equal_size(B);
    double total_distance = 0;
    for (int i = 0; i < rows(); i++) {
        for (int j = 0; j < columns(); j++) {
            total_distance += abs(get(i, j) - B.get(i, j));
        }
    }
    return total_distance;
}
void exact_matching(unsigned char* imit_image, unsigned char* ref_image, int **imit_pixel_values, int **ref_pixel_values, unsigned ref_rows, unsigned ref_cols, unsigned imit_rows, unsigned imit_cols, unsigned *rows, unsigned *cols, int color){
    pixel_struct *imitpixel_struct_array, *refpixel_struct_array;
    int i;

    //make rows-columns equal
    *rows = equal_size(ref_rows, imit_rows);
    *cols = equal_size(ref_cols, imit_cols);

    pixel_values_2d_array(*rows, *cols, 4, ref_image, ref_pixel_values, color);
    pixel_values_2d_array(*rows, *cols, 4, imit_image, imit_pixel_values, color);

    //memory allocation
    refpixel_struct_array = (pixel_struct *)malloc((*rows) * (*cols) * sizeof(pixel_struct));
    imitpixel_struct_array = (pixel_struct *)malloc((*rows) * (*cols) * sizeof(pixel_struct));

    //fill array - unsorted
    make_pixel_struct_array(ref_pixel_values, refpixel_struct_array, *rows, *cols);
    make_pixel_struct_array(imit_pixel_values, imitpixel_struct_array, *rows, *cols);

    //sort pixel struct array
    qsort(refpixel_struct_array, ((*rows)*(*cols)), sizeof(pixel_struct), compfunc);
    qsort(imitpixel_struct_array, ((*rows)*(*cols)), sizeof(pixel_struct), compfunc);

    //check as usual
    /*for (i = 500; i < 800; i++){
        printf("%d %f %d\n", refpixel_struct_array[i].pxl_value, refpixel_struct_array[i].mo, refpixel_struct_array[i].row);
    }*/

    //equalize
    histogram_equalization(refpixel_struct_array, rows, cols);
    histogram_equalization(imitpixel_struct_array, rows, cols);

    //match
    histogram_matching(refpixel_struct_array, imitpixel_struct_array, rows, cols);

     //change 2d array --> na to kanw function
    for (i = 0; i < ((*rows)*(*cols)); i++){
        ref_pixel_values[refpixel_struct_array[i].row][refpixel_struct_array[i].col] = refpixel_struct_array[i].pxl_value;
        imit_pixel_values[imitpixel_struct_array[i].row][imitpixel_struct_array[i].col] = imitpixel_struct_array[i].pxl_value;
    }

}
int equal_matrice (Matrice m1, Matrice m2){
  if (!equal_size(m1, m2))
      return FALSE;
  int i, j;
  for(i = 0; i < m1->taille; i++){
    for(j = 0; j < m1->taille; j++){
      if (m1->tab[i][j] != m2->tab[i][j])
	return FALSE;
    }
  }
  return TRUE;
}
Matrix Matrix::multiply(Matrix & B) {
    equal_size(B);
    prod
    return prod(m, B);
    
//    Matrix result = Matrix(rows(), B.columns());
//    for (int i = 0; i < result.rows(); i++) {
//        for (int j = 0; j < result.columns(); j++) {
//            for (int k = 0; k < columns(); k++) {
//                double new_value = result.get(i, j) + get(i, k) * B.get(k, j);
//                result.set(i, j, new_value);
//            }
//        }
//    }
//    return result;
}
Matrix Matrix::elementwise_operation(Matrix & B, 
                                     Matrix::elementwise_operation_enum 
                                     operation_type) {
    equal_size(B);
    Matrix result = Matrix(rows(), columns());
    for (int i = 0; i < rows(); i++) {
        for (int j = 0; j < columns(); j++) {
            if (operation_type == E_HADAMARD) {
                result.set(i, j, get(i, j) * B.get(i, j));
            } else if (operation_type == E_DIVISION && B.get(i, j) != 0) {
                result.set(i, j, get(i, j) / B.get(i, j));
            } else if (operation_type == E_ADDITION) {
                result.set(i, j, get(i, j) + B.get(i, j));
            }
        }
    }
    return result;
}
Matrice multiplication_in_MnR(Matrice m1,Matrice m2){
  if(!equal_size(m1,m2)){
    printf("sont pas de meme taille");
    return NULL;
  }
  
  Matrice m3=creer_matrice(m1->taille);
  m3->mot = tree_concatenation(m1->mot,m2->mot);

  int i,j,k;
  for(i=0;i<m1->taille;i++)
    for(j=0;j<m1->taille;j++){
      m3->tab[i][j]=-1;
    }  
  for(i=0;i<m1->taille;i++)
    for(j=0;j<m1->taille;j++)   
      for(k=0;k<m1->taille;k++){
	if(m3->tab[i][j] == -1)
	  m3->tab[i][j]= max(m1->tab[i][k],m2->tab[k][j]);
	else
	  m3->tab[i][j]=min(max(m1->tab[i][k],m2->tab[k][j]), m3->tab[i][j]);
      }
  return m3;
}