/* $Id: matrici.c,v 1.3 1997/05/01 17:34:49 sandro Exp $ */
/*
* Copyright (c) 1997
* Sandro Sigala, Brescia, Italy. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "matrici.h"
#include "umatrix.h"
int stile = STILE_CLASSICO;
double (valore)(Matrice m, int riga, int colonna)
{
return m->valori[(riga-1) * m->colonne + (colonna-1)];
}
Matrice matr_crea(char *nome, int righe, int colonne)
{
Matrice m;
assert(righe > 0 && colonne > 0);
m = (Matrice)malloc(sizeof *m);
m->righe = righe;
m->colonne = colonne;
m->nome = strdup(nome);
m->valori = (double *)calloc(righe * colonne, sizeof(double));
return m;
}
void matr_elimina(Matrice m)
{
assert(m != NULL);
free(m->nome);
free(m->valori);
free(m);
}
void matr_stampa(Matrice m)
{
int r, i, c, sp;
assert(m != NULL);
sp = strlen(m->nome) + 3;
for (r = 1; r <= m->righe; r++) {
if (sp) {
if (r-1 == m->righe / 2)
printf("%s = ", m->nome);
else
for (i = 0; i < sp; i++)
putchar(' ');
}
if (stile == STILE_ALTERNATIVO)
printf("|| ");
else {
if (m->righe > 1) {
if (r == 1) printf(" / ");
else if (r == m->righe) printf(" \\ ");
else printf("| ");
} else printf("| ");
}
for (c = 1; c <= m->colonne; c++)
printf("%3.0f ", valore(m, r, c));
if (stile == STILE_ALTERNATIVO)
printf("||\n");
else {
if (m->righe > 1) {
if (r == 1) printf(" \\\n");
else if (r == m->righe) printf(" /\n");
else printf(" |\n");
} else printf("|\n");
}
}
}
Matrice matr_somma(char *nome, Matrice m1, Matrice m2)
{
Matrice mr;
int r, c;
assert(m1 != NULL && m2 != NULL);
if (m1->righe != m2->righe || m1->colonne != m2->colonne) {
fprintf(stderr, getstr("Errore: somma di matrici di dimensioni differenti\n"));
return NULL;
}
mr = matr_crea(nome, m1->righe, m1->colonne);
for (r = 1; r <= m1->righe; r++)
for (c = 1; c <= m1->colonne; c++)
valore(mr, r, c) = valore(m1, r, c) + valore(m2, r, c);
return mr;
}
Matrice matr_prodotto_per_numero(char *nome, Matrice m, double n)
{
Matrice mr;
int r, c;
assert(m != NULL);
mr = matr_crea(nome, m->righe, m->colonne);
for (r = 1; r <= m->righe; r++)
for (c = 1; c <= m->colonne; c++)
valore(mr, r, c) = valore(m, r, c) * n;
return mr;
}
Matrice matr_prodotto(char *nome, Matrice m1, Matrice m2)
{
Matrice mr;
int r, c, i;
assert(m1 != NULL && m2 != NULL);
if (m1->colonne != m2->righe) {
fprintf(stderr, getstr("Errore: prodotto di matrici di dimensioni errate\n"));
return NULL;
}
mr = matr_crea(nome, m1->righe, m2->colonne);
for (r = 1; r <= m1->righe; r++)
for (c = 1; c <= m2->colonne; c++)
for (i = 1; i <= m1->colonne; i++)
valore(mr, r, c) += valore(m1, r, i) * valore(m2, i, c);
return mr;
}
Matrice matr_trasposta(char *nome, Matrice m)
{
Matrice mr;
int r, c;
assert(m != NULL);
mr = matr_crea(nome, m->colonne, m->righe);
for (r = 1; r <= m->righe; r++)
for (c = 1; c <= m->colonne; c++)
valore(mr, c, r) = valore(m, r, c);
return mr;
}
void matr_assegna_valori_casuali(Matrice m, int min, int max)
{
int r, c;
assert(m != NULL);
for (r = 1; r <= m->righe; r++)
for (c = 1; c <= m->colonne; c++)
valore(m, r, c) = rand() % (max + 1 - min) + min;
}
Matrice matr_crea_valori_casuali(char *nome, int righe, int colonne, int min, int max)
{
Matrice m;
m = matr_crea(nome, righe, colonne);
matr_assegna_valori_casuali(m, min, max);
return m;
}
Matrice matr_crea_matrice_unita(char *nome, int ordine)
{
Matrice m;
int i;
m = matr_crea(nome, ordine, ordine);
for (i = 1; i <= ordine; i++)
valore(m, i, i) = 1;
return m;
}
static double determinante(Matrice m)
{
double d;
int r, c, i, k;
Matrice mr;
/*
* Versioni inline non ricorsive del calcolo del determinante di
* matrice di ordine 1, 2 e 3.
*/
switch (m->righe) {
case 1:
return valore(m, 1, 1);
case 2:
return valore(m, 1, 1) * valore(m, 2, 2) -
valore(m, 1, 2) * valore(m, 2, 1);
case 3:
return valore(m, 1, 1) * valore(m, 2, 2) * valore(m, 3, 3) -
valore(m, 1, 1) * valore(m, 2, 3) * valore(m, 3, 2) -
valore(m, 1, 2) * valore(m, 2, 1) * valore(m, 3, 3) +
valore(m, 1, 3) * valore(m, 2, 1) * valore(m, 3, 2) +
valore(m, 1, 2) * valore(m, 2, 3) * valore(m, 3, 1) -
valore(m, 1, 3) * valore(m, 2, 2) * valore(m, 3, 1);
}
/* Matrice di ordine > 3. */
for (d = 0, k = 1; k <= m->righe; k++) {
if (valore(m, k, 1) == 0)
continue;
mr = matr_crea("", m->righe-1, m->righe-1);
for (r = i = 1; r <= m->righe; r++) {
if (r == k)
continue;
for (c = 1; c + 1 <= m->colonne; c++)
valore(mr, i, c) = valore(m, r, c+1);
i++;
}
d += determinante(mr) * valore(m, k, 1) * pow(-1, k + 1);
matr_elimina(mr);
}
return d;
}
/*
* matr_determinante(): funzione.
* La funzione restitusce il determinante della matrice.
*/
double matr_determinante(Matrice m)
{
if (m->righe != m->colonne) {
fprintf(stderr, getstr("Errore: calcolo determinante di matrice non quadrata\n"));
return 0;
}
return determinante(m);
}
/*
* Predicati.
*/
/*
* matr_quadrata_p(): predicato.
* La funzione e` vera se la matrice e` quadrata.
*/
int (matr_quadrata_p)(Matrice m)
{
assert(m != NULL);
return m->righe == m->colonne;
}
/*
* matr_rettangolare_p(): predicato.
* La funzione e` vera se la matrice e` rettangolare.
*/
int (matr_rettangolare_p)(Matrice m)
{
assert(m != NULL);
return m->righe != m->colonne;
}
/*
* matr_unita_p(): predicato.
* La funzione e` vera se la matrice e` una matrice unita`.
*
* Una matrice quadrata A di ordine n si dice matrice unita` se i suoi
* elementi della diagonale principale sono eguali a 1 e tutti gli altri
* elementi eguali a zero, cioe` se:
* per i,k=1..n --> a[i,k] = 0 con i != k e
* per i=1..n --> a[i,k] = 1
*/
int matr_unita_p(Matrice m)
{
int r, c;
assert(m != NULL);
if (!matr_quadrata_p(m))
return 0;
for (r = 1; r <= m->righe; r++)
for (c = 1; c <= m->colonne; c++)
if (r == c) {
/* Diagonale principale. */
if (valore(m, r, c) != 1)
return 0;
} else if (valore(m, r, c) != 0)
return 0;
return 1;
}
/*
* matr_simmetrica_p(): predicato.
* La funzione e` vera se la matrice e` simmetrica.
*
* Una matrice quadrata A di ordine n si dice simmetrica se sono eguali le
* coppie di elementi simmetrici rispetto alla diagonale principale, cioe` se:
* a[i,k] = a[k,i] con i,k=1..n e i != k
*
* In altre parole, una matrice e` simmetrica solo e solo se coincide con la
* sua trasposta.
*/
int matr_simmetrica_p(Matrice m)
{
int r, c;
assert(m != NULL);
if (!matr_quadrata_p(m))
return 0;
for (r = 1; r <= m->righe; r++)
for (c = 1; c <= m->colonne; c++)
if (valore(m, r, c) != valore(m, c, r))
return 0;
return 1;
}
/*
* matr_stesso_tipo_p(): predicato.
* La funzione e` vera se le due matrici sono dello stesso tipo, ovvero
* hanno la stessa dimensione.
*/
int (matr_stesso_tipo_p)(Matrice m1, Matrice m2)
{
assert(m1 != NULL && m2 != NULL);
return m1->righe == m2->righe && m1->colonne == m2->colonne;
}
/*
* matr_eguali_p(): predicato.
* La funzione e` vera se le due matrici sono eguali.
*/
int matr_eguali_p(Matrice m1, Matrice m2)
{
assert(m1 != NULL && m2 != NULL);
if (!matr_stesso_tipo_p(m1, m2))
return 0;
#if 1
/* Versione classica. */
{
int r, c;
for (r = 1; r <= m1->righe; r++)
for (c = 1; c <= m1->colonne; c++)
if (valore(m1, r, c) != valore(m2, r, c))
return 0;
return 1;
}
#else
/* Versione ottimizata. In alcuni casi non puo` funzionare. */
return memcmp(m1->valori, m2->valori,
m1->righe * m1->colonne * sizeof(double)) == 0;
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1