/* matrix2.c -- Speicherung einer Matrix mit Indexberechnung, Struktur */

#include <stdio.h>		/* printf */
#include <stdlib.h>		/* malloc, abort */
#include <assert.h>

/* Strukturdefinition */

struct matrix {
  int num_rows;
  int num_columns;
  double *elements;
};

/* Konstruktor */

struct matrix *alloc_matrix(int num_rows, int num_columns)
{
  struct matrix *m = malloc(sizeof(struct matrix));
  if (m == NULL) {
    fprintf(stderr, "Allocation of memory failed\n");
    abort();
  }
  (*m).num_rows = num_rows;
  (*m).num_columns = num_columns;
  (*m).elements = malloc(sizeof(double) * num_rows * num_columns);
  if ((*m).elements == NULL) {
    fprintf(stderr, "Allocation of memory failed\n");
    abort();
  }
  return m;
}

/* Zugriffsfunktionen (Accessors) */

double matrix_element(struct matrix *matrix, int row, int column)
{
  return *((*matrix).elements + row * (*matrix).num_columns + column);
}

void set_matrix_element(struct matrix *matrix, int row, int column,
			double element)
{
  *((*matrix).elements + row * (*matrix).num_columns + column) = element;
}

/* Destruktor */

void free_matrix(struct matrix *matrix)
{
  free((*matrix).elements);
  free(matrix);
}

struct matrix *read_matrix()
{
  int num_rows;
  int num_columns;
  struct matrix *matrix;
  
  printf("Anzahl Zeilen:  ");
  scanf("%d", &num_rows);
  printf("Anzahl Spalten: ");
  scanf("%d", &num_columns);

  matrix = alloc_matrix(num_rows, num_columns);
  {
    int i, j;
    for (i = 0; i<num_rows; i++) {
      printf("Zeile %d: ", i);
      for (j = 0; j<num_columns; j++) {
	double element;
	scanf("%lf", &element);
	set_matrix_element(matrix, i, j, element);
      }
    }
  }
  return matrix;
}

void print_matrix(struct matrix *matrix)
{
  int i, j;
  for (i = 0; i<(*matrix).num_rows; i++) {
    for (j = 0; j<(*matrix).num_columns; j++)
      printf("%g ", matrix_element(matrix, i, j));
    printf("\n");
  }
}

struct matrix *matrix_sum(struct matrix *A,
			  struct matrix *B)
{
  struct matrix *S;
  int num_rows;
  int num_columns;
  
  /* Dimensionen ueberpruefen */
  assert((*A).num_rows == (*B).num_rows && (*A).num_columns == (*B).num_columns);
  num_rows = (*A).num_rows;
  num_columns = (*A).num_columns;
  /* Speicher bereitstellen */
  S = alloc_matrix(num_rows, num_columns);
  /* Summe berechnen */
  {
    int i, j;
    for (i = 0; i<num_rows; i++)
      for (j = 0; j<num_columns; j++)
	set_matrix_element(S, i, j,
			   matrix_element(A, i, j)
			   + matrix_element(B, i, j));
  }
  /* Wert zurueckgeben */
  return S;
}

int main()
{
  struct matrix *A;
  struct matrix *B;
  struct matrix *S;

  printf("Matrix A:\n");
  A = read_matrix();
  printf("Matrix B:\n");
  B = read_matrix();

  S = matrix_sum(A, B);
  printf("Matrix A + B:\n");
  print_matrix(S);

  free_matrix(A);
  free_matrix(B);
  free_matrix(S);
  
  return 0;
}
