\initializearticle
\title
AQUARIUS MATRIX LIBRARY\\
Libreria di Calcolo Matriciale e Funzioni Vettoriali per \amiga{}
\endtitle

\author  * Dott. Fausto Passariello *
\address * Centro Diagnostico AQUARIUS\\
           via Francesco Cilea, 280\\
           I-80127 Napoli NA\\
           Tel. 081-654110, 7144110*
\netaddress[\network{FidoNet}]   *2:335/229@fidonet.org *
\netaddress[\network{AmigaNet}]  *39:102/109@amiganet.ftn*
\netaddress[\network{InterNet}]  *aquarius@na.infn.it*
\netaddress[\network{CBMNet}]    *aquarius@lagrange.adsp.sub.org*


\article

Libreria di Calcolo Matriciale e Funzioni Vettoriali per \amiga{}

\head *Riassunto*

|Aquarius Matrix Library|, versione 1.0 \`e una libreria di  calcolo  matriciale
e funzioni vettoriali per \amiga{}. Le applicazioni del calcolo matriciale sono
di uso quotidiano nel campo scientifico e professionale. Vanno  dal calcolo
strutturale  alla grafica 2D e 3D, dalle elaborazioni statistiche al metodo
degli elementi finiti  o all'analisi  del
segnale  audio e video mediante trasformate e antitrasformate.

Il vantaggio del calcolo matriciale \`e evidente: poter trattare intere
tabelle di dati (matrici o vettori) come un singolo  scalare permette una
formulazione pi\`u sintetica e ordinata del procedimento di  calcolo e una
sua  maggiore comprensione.

Aquarius  Matrix Library fornisce, belle e pronte, le funzioni pi\`u classiche
del calcolo matriciale (copia, stampa,  addizione, moltiplicazione, inversa
e determinante di una matrice quadrata, calcolo di autovalori e autovettori).
Vi sono per\`o anche altre funzioni pi\`u sofisticate e di uso pi\`u
specialistico quali l'immissione dei dati da file e la loro  contemporanea
conversione logaritmica, oppure la standardizzazione delle colonne di dati
con calcolo della variabilit\`a intorno alla  media.
Insolite, poi sono le funzioni vettoriali o meglio matriciali.
Con esse si costituiscono  matrici, i cui elementi  non sono
dati  numerici ma  funzioni, tutte  dipendenti da uno stesso
parametro.La chiamata di funzione  si risolve quindi nella  esecuzione
di una griglia $m \times n$ di funzioni dello stesso parametro.
Questa operazione permette la gestione ad esempio di tabelle
di dati variabili nel tempo.

La libreria \`e scritta in linguaggio C e compilata con SAS/C
6.3.
\`E  prevista una sua versione futura  in C++, mentre a tutt'oggi il
codice pu\`o  essere compilato  senza variazioni  su
piattaforme MS/DOS.

|AMTieee.lib| e |amtieee.library| sono \copyright{} 1993 Fausto Passariello.
Esse possono essere distribuite liberamente, senza fini di lucro,
richiedendo al massimo il rimborso delle spese vive per la produzione
della copia. Nelle copie distribuite deve essere conservata intatta ogni informazione
relativa all'autore, e il codice non deve essere alterato in alcun modo.
\`E lecito distribuire una copia fedele di questo manuale, a patto che
queste note siano conservate integre in tutte le copie distribuite.

Pur essendo una libreria liberamente distribuibile, \`e vivamente suggerita la registrazione
dell'utente, per poter accedere via |E-mail| alle nuove versioni.
Inoltre, l'autore gradir\`a molto la segnalazione della produzione di
software adoperando le funzioni della libreria.
Nulla \`e dovuto per la produzione di software liberamente distribuibile.

Al contrario, la produzione di software commerciale, adoperando le
funzioni della libreria, sia essa {\it linkable} o {\it shared}, deve necessariamente
essere preceduta da un accordo con l'autore.
In sua mancanza, ogni commercializzazione di prodotti che includano o in
qualsiasi forma si servano delle funzioni della libreria {\it AMTieee},
potr\`a essere considerata una violazione delle vigenti norme di legge
italiane sul diritto di autore e potr\`a essere perseguita nei modi
previsti dalla legge.

Le condizioni suddette, necessariamente si adattano alla normativa vigente
in altri paesi.

La libreria |AMTieee| \`e fornita cos\`{\i} come \`e, senza nessuna garanzia che
serva a uno scopo prefissato.
L'autore declina ogni responsabilit\`a riguardo eventuali danni,
derivabili da un cattivo uso del software fornito.
In ogni caso, si consiglia una attenta lettura della guida ipertestuale
e del file di documentazione della libreria, prima di iniziare ad
adoperarla.

Per tutte le controversie sar\`a competente il Foro di Napoli, Italia.

\head *Introduzione*

Esiste uno spazio da riempire, lo spazio attualmente abbastanza vuoto
delle {\it applicazioni scientifiche} per il mondo \amiga{}.

Non esiste al momento una libreria di funzioni matriciali di pubblico
dominio per \amiga{}. Esistono invece, per vari calcolatori,
numerosissime librerie di pubblico dominio, che forniscono funzioni
ben pi\`u complicate e complete di quelle fornite dalla libreria di
cui parliamo.

Infatti, questa non si prefigge lo scopo di essere lo stato dell'arte per
la materia, ma il fine principale del lavoro \`e quello di mettere a
disposizione di una macchina, cronicamente sprovvista di questi strumenti,
una prima versione di libreria di calcolo matriciale che potr\`a essere
migliorata in seguito, per fornire ai programmatori un valido strumento di
sviluppo.

Le matrici costituiscono prevalentemente un argomento di matematica ma in
questa sede non diremo assolutamente nulla di talmente importante per la
{\it teoria delle matrici}.
L'argomento \`e la risoluzione pratica dei problemi del calcolo matriciale
e quindi eviteremo di cadere in particolari troppo tecnici dal punto di
vista matematico.

\head *Installazione*

La procedura \`e estremamente semplice:

\list
\item scegliere un percorso |<path>|
\item |MAKEDIR <path>AMT|
\item |COPY amtieee.lha <path>AMT/|
\item |cd <path>AMT|
\item |lha x amtieee|
\endlist

\noindent Bisogna in ultimo inserire nel file |s:user-startup| la linea
seguente:

||ASSIGN AMT: <percorso_scelto>||

La libreria \`e disponibile in due versioni, una {\it linkable} con nome
|amtieee.lib|, l'altra {\it shared}, con nome |amtieee.library|.
Se si installa la libreria {\it shared}, allora occorre copiarla nel
device |LIBS:|

||COPY amtieee.library LIBS:||

Per una efficace utilizzazione del codice della libreria, \`e opportuno che
nella directory di compilazione sia presente il file |mydebug.h|, che
non pu\`o essere fornito, in quanto \copyright Commodore. Se il programmatore non lo
ha a disposizione, basta un minimo di definizioni:

\verbatim
#define bug printf
#ifdef MYDEBUG
#define D(x) x
#else
#define D(x) ;
#endif
\endverbatim

\head *Applicazioni del Calcolo Matriciale*

\subhead *Grafica 2D e 3D*

L'utilit\`a del calcolo matriciale \`e evidente. L'esempio pi\`u classico,
pi\`u vicino alle applicazioni pratiche usate da tutti gli sviluppatori
software \`e la {\it GRAFICA 2D e 3D}.
Siamo soliti calcolare visualizzazioni particolari con algoritmi molte
volte artigianali. Ma se vogliamo essere rigorosi, ognuna di queste
operazioni di grafica {\it 2D} e {\it 3D} pu\`o essere ridotta a una
operazione matriciale.

Praticamente le operazioni che si fanno nel {\it rendering} in un programma
di grafica sono molte volte operazioni da eseguire in sequenza e in gran
numero per ogni visualizzazione e quindi con un dispendio di tempo macchina
notevole.

Il vantaggio dell'uso delle matrici \`e  rilevante perch\'e, conoscendo la
sequenza delle operazioni matriciali da applicare, possiamo moltiplicare in
una sola volta tutte le matrici che intervengono nel calcolo, coagulandole
in una sola operazione. Questo procedimento sintetico risulta efficace
(oltre che pi\`u chiaro) solo se il calcolo presenta caratteri ripetitivi.
Questo per\`o avviene spesso nei problemi di grafica.

\subhead *Calcolo Statistico*

Vi sono moltissimi altri campi in cui \`e possibile applicare il calcolo
matriciale per scopi pratici.

Uno di questi \`e il {\it CALCOLO STATISTICO}. Esso pu\`o essere eseguito in
modo elementare calcolando medie, deviazioni standard e cos\`i via. Oppure,
in modo molto pi\`u ordinato, su un insieme di dati caricati in matrice,
eseguendo le operazioni su tante variabili, ognuna delle quali sar\`a la
colonna di una matrice.
In tal modo possiamo ottenere che anche i risultati siano organizzati in
matrici e che quindi siano leggibili e ben ordinati.
Tra le applicazioni pi\`u pratiche abbiamo l'{\it analisi di regressione},
l'{\it analisi discriminante}, l'{\it analisi in componenti principali},
etc.
Esse sono le applicazioni tipiche dell'{\it analisi multivariata}, che
sono complicate a tal punto da essere affrontabili soltanto con il calcolo
matriciale.

\subhead *Metodo degli Elementi Finiti*

Un altro campo particolare \`e per esempio l'analisi delle strutture con il
{\it metodo degli elementi finiti}.
Quando si calcolano le tensioni interne e gli spostamenti di strutture
reticolari, si  \`e soliti porre tutte le variabili in tabelle, in modo da
trattare il problema con i metodi del calcolo matriciale.
Analogamente, per strutture dinamiche si pu\`o giungere alla definizione
di una matrice di dati e di una colonna di variabili incognite.

Non \`e qui il caso di accennare neanche alla complessit\`a del problema.

\subhead *Analisi del Segnale*

Altra applicazione importante \`e quella dell'{\it analisi del segnale} audio
o video mediante {\it trasformate}.
Se queste trasformate sono eseguite in modo artigianale, hanno una certa
complessit\`a di elaborazione. Se invece le concepiamo come trasformazioni
matriciali, assumono una versione molto semplificata. Chiaramente la
velocizzazione della trasformata ci pu\`o imporre di abbandonare lo
schematismo matriciale.


La {\it DFT}, ({\it Discrete Fourier Transform} o {\it Trasformata
Discreta di Fourier}) non \`e altro che una moltiplicazione matriciale di
una colonna di dati per una matrice di coefficienti.
Essa produce in uscita una colonna di coefficienti nel dominio delle
frequenze.

\subhead *Vantaggi del Calcolo Matriciale*

Il vantaggio evidente nell'uso delle matrici \`e che operazioni molto
complesse possono essere ridotte concettualmente a operazioni come
addizione, sottrazione e moltiplicazione. Nel senso che un'intera tabella
di dati, quindi una matrice organizzata per righe e per colonne pu\`o essere
considerata alla stregua di un solo numero o {\it scalare}.

Moltiplicare un vettore per una matrice e quindi in pratica due tabelle di
dati, ha la stessa importanza algoritmica nel nostro flusso di dati, di una
semplice moltiplicazione tra due numeri. In questo caso al posto di |+|
useremo |matplus()| o invece di |*| useremo |matper()|. Il concetto \`e
in fondo identico: poter trattare i dati come scalari e non come vettori o
matrici.

Un numero \`e uno {\it scalare}.
Un insieme di numeri organizzati in sequenza \`e un {\it vettore}.
Una tabella organizzata in righe e colonne \`e una {\it matrice}.
Molto pi\`u tecnicamente si pu\`o dire che:

\list
\item uno scalare \`e un {\it tensore} di ordine 0
\item un vettore \`e un tensore di ordine 1
\item una matrice \`e un tensore di ordine 2
\endlist

\noindent Esistono anche tensori di ordine 3,4,5,\dots

In ultimo, vorrei accennare solo al fatto che, in un'ottica senz'altro
pi\`u vasta, le matrici non sono altro che singoli elementi di uno spazio
vettoriale, cio\`e {\it vettori}, indipendentemente dalla loro dimensione.

\head *Aquarius Matrix Library*


\subhead *La Libreria*

Attualmente la libreria \`e disponibile in una versione da legare al codice
o linkable oppure in una versione shared.

Adoperando la versione residente, occorre aprire e in ultimo chiudere la
libreria, utilizzando le funzioni del sistema operativo di \amiga{}.
Se si adopera la versione da collegare al codice, allora l'apertura deve
essere effettuata mediante la funzione |InitKernel()|, mentre per
la chiusura si adopera l'analoga |CloseKernel()|.

Aquarius MaTrix library ({\it AMT}) \`e scritta in modo che possa essere
adoperata con un piccolo o con un enorme numero di dati.
Chiaramente {\it AMT} fallir\`a con dei messaggi d' errore, se non
riuscir\`a  a riservare la memoria richiesta dai dati.

{\it AMT} \`e scritta in C e non ancora in {\it C++} e compilata con
{\it SAS/C 6.3}
La naturale estensione al {\it C++} sar\`a il prossimo passo. Attualmente
la libreria \`e organizzata su numeri floating point , in {\it C++} sar\`a
automatica l'estensione ai numeri complessi e per alcuni tipi di
operazioni saranno utilizzabili anche gli interi, con notevole risparmio
di memoria.

Attualmente per \amiga{} non esiste una libreria di matrici, né per
numeri in virgola mobile, né per numeri complessi né per numeri interi.
Questo \`e solo un primo passo.

\subhead *La Definizione di Matrice*

Tutte le funzioni di libreria sono scritte in  modo che, volendo, si possa
accedere direttamente alla struttura della matrice cos\`{\i} come \`e definita,
ma sono fornite anche funzioni per estrarre gli elementi della matrice
senza dover accedere in modo {\it opaco} alla definizione.

Per estrarre dalla matrice l'array di dati posso usare la funzione
|getarray()|.
In alternativa si pu\`o entrare nella matrice e con una indirezione prelevare
il puntatore dell'array. Tra i due \`e preferibile il primo metodo, perch\'e
nelle future versioni si far\`a riferimento solo a questo procedimento.

Quindi il secondo approccio \`e non compatibile con le future versioni,
perch\'e, forse, cambier\`a la struttura della matrice. Analogamente, per
sapere quanto \`e grande una matrice si pu\`o adoperare la funzione
|getdim()| con il qualificatore {\it MATRAW} oppure {\it MATCOL}
(riga o colonna), con un metodo consistente con le future versioni di
{\it AMT}.

La matrice \`e definita come struttura e al suo interno vi \`e un puntatore di
puntatore a double:


\verbatim
struct matrix  {
	double  **mt;
	UWORD  rows, cols;
};
\endverbatim


{\it AMT} \`e costruita in modo che non debba essere definita in partenza
la dimensione delle matrici. Scrivere un calcolo matriciale in cui \`e gi\`a
deciso in partenza che le matrici sono 4 $\times$ 4. (es., in grafica 3D) \`e molto
pi\`u semplice.
Invece {\it AMT} pu\`o eseguire tutte le operazioni su matrici $m \times n$,
comunque definite.

Ci sono altri modi per definire un matrice, per esempio con un solo array
monodimesionale (un solo double |*|) e con un numero di righe e di colonne in
modo che una funzione calcoli poi dove si trova l'elemento di riga e di
colonna.
La soluzione adottata si preoccupa di conservare l'uso della matrice di
dati, che \`e interna alla struttura matrice, anche all'interno del proprio
programma.
Leggendo con |getarray()| il puntatore alla matrice, \`e possibile
utilizzare questo puntatore con i due indici matriciali e il compilatore
non d\`a messaggi di errore.

Il primo metodo invece dar\`a errore, perch\'e  la matrice \`e costruita con un
array monodimensionale.

\subhead *Configurazione*

L'apertura di {\it AMT} determina l'inizializzazione di un nucleo
interno di dati {\it Kernel}.
Le funzioni |setiterations()| e |getiterations()| permettono la
selezione del {\it numero massimo di iterazioni} (inizialmente 100), che i
procedimenti di approssimazione devono eseguire prima di restituire un
valore, sempre che la precisione desiderata non sia gi\`a stata raggiunta.
Le funzioni |setprecision()| e |getprecision()| permettono l'impostazione
e la lettura della precisione nel calcolo numerico
in virgola mobile, inizialmente impostata al valore 1.0E-8.
Ancora, le funzioni |getlastprecision()| e |getlastiteration()|
permettono la lettura dei corrispondenti valori raggiunti nei processi
iterativi. Tra questi, il calcolo degli autovettori e degli autovalori
di una matrice simmetrica.

Il termine precisione non ha nulla a che vedere con il formato dell'uscita dati,
che \`e selezionabile con la funzione |printusing()|
e leggibile con |getformat()|. Quest' ultima funzione ha per argomento il valore
logico {\it INTFMT} o {\it FLOATFMT}, definito nel file include della libreria.

Analogamente, \`e possibile leggere la {\it massima precisione} fornita
dalla macchina, tramite la funzione |getepsilon()|. Al momento, la
procedura legge solo il valore dichiarato della libreria matematica, mentre
in futuro restituir\`a il valore effettivo calcolato sulla singola macchina.

La rappresentazione tabellare dei dati di una matrice \`e senz'altro
influenzata dalla larghezza della linea del terminale e dal numero di
linee visibili. Questi dati sono configurabili mediante la funzione
|setterm()|, che calcola le colonne di dati visualizzabili in
contemporanea.

Il {\it seme} esterno della sequenza dei numeri pseudocasuali pu\`o
essere letto tramite la funzione |getseed()|. Il valore \`e privato
per ogni singolo utente della libreria.
L'utilit\`a \`e evidente. Il carattere pseudocasuale delle sequenza si
conserva solo se si riutilizza il seme gi\`a usato per altre operazioni
interne alla libreria, ad es. |matrandom()|. In effetti, il seme
non \`e fisso e cambia il suo valore man mano che si utilizzano i numeri
casuali, per cui il vero elemento fisso \`e il puntatore al seme.
Utilizzare un altro seme ha senso solo qualora la sequenza da generare
non debba pi\`u avere alcuna connessione con la sequenza precedente.
Come in ogni altra operazione matematica, la scelta \`e ragionata e spetta
al solo programmatore confrontarsi con la correttezza di un metodo o di un
altro.

Le funzioni |setmatperid()| e |getmatperid()| permettono di
configurare il tipo di moltiplicazione matriciale. Le opzioni previste
sono:

\list
\item PER moltiplicazione righe per colonne
\item PERCOL moltiplicazione colonne per colonne
\item COLROW moltiplicazione colonne per righe
\item ROWROW moltiplicazione righe per righe
\endlist

\noindent In pratica, all'apertura la libreria \`e configurata per la
moltiplicazione righe per colonne, che \`e la forma pi\`u adoperata.
L'operazione si ottiene con la chiamata alla funzione |matper()|,
che \`e una forma generalizzata di moltiplicazione matriciale. In questa
prima versione della libreria, questa forma coesiste con le funzioni
semplici |matrowcol()| e |matpercol()|. L'uso delle altre
forme di moltiplicazione \`e pi\`u raro, ma teoricamente possibile. Il loro
uso \`e legato necessariamente alla impostazione del tipo di operazione
della funzione |matper()|.

In altra parte di questa guida sono trattate altre funzioni di
configurazione.

\subhead *Procedure di Debug*

Su \amiga{} il {\it Debug} pu\`o essere facilitato inserendo messaggi di commento
tra le righe di codice. La procedura pu\`o essere controllata definendo il
simbolo di preprocessore |MYDEBUG|. In mancanza della definizione, tutti i
commenti non sono compilati e non appesantiscono il codice oggetto.
Al contrario, quando |MYDEBUG| \`e definito, i messaggi vanno a video o
sulla seriale o sulla porta parallela, in dipendenza di alcune
definizioni nel file |MyDebug.h|.
Questa procedura \`e stata estesa anche alla chiamata delle funzioni della
libreria {\it AMT}.

Vi sono generalmente due nomi per la stessa funzione. Il nome con lettere
minuscole corrisponde alla semplice chiamata di funzione, mentre adoperando
il nome con alcune lettere maiuscole si accede alla stessa funzione
controllata da una procedura di {\it Debug}.
Ad esempio, per |matplus()| la funzione analoga con supporto
{\it Debug} si chiama |MatPlus()|.
Questa ovviamente rallenta di molto l'esecuzione del programma, per via
della mole cospicua di informazioni emesse.
Nondimeno, le due chiamate di funzione sono equivalenti, qualora non sia
definito il simbolo |MYDEBUG|, nel senso che il codice oggetto \`e identico.
Per questo motivo si raccomanda vivamente l'uso delle funzioni con nome
capitalizzato, perch\'e queste facilmente si trasformano nelle loro
equivalenti, spegnendo l'interruttore |MYDEBUG|.

Il tipo di informazione che fuoriesce dal {\it Debug} riguarda prevalentemente
la {\it consistenza} delle dimensioni delle matrici fornite come argomento a
ogni funzione.
In particolare, sono segnalate condizioni di errore nelle funzioni che
richiedono l'uso di matrici quadrate e in quelle che comportano una
{\it contrazione} delle dimensioni.
Limitatamente a questa versione della libreria, per alcune funzioni che
restituiscono un valore non \`e possibile adoperare in contemporanea le
macro per il supporto Debug. Questi casi sono segnalati negli AutoDocs.

\head *Funzioni di Occupazione di Memoria*

\`E possibile definire una matrice chiamando
\discretionary{|alloc-|}{|matmem()|}{|allocmatmem()|}, fornendo
due {\it dimensioni} $m$ e $n$. \`e restituito un puntatore a matrice.
In alternativa, \`e possibile definire un' {\it istanza} di struttura
matriciale, inserire all'interno le dimensioni e poi chiamare
|allocmat()|.

Questa ultima routine \`e di basso livello nel senso che bisogna entrare
nella struttura della matrice mentre la prima fornisce la matrice senza che
l'utente sia costretto  ad avere alcuna cognizione di come sia fatta.
I due livelli sono forniti per un solo motivo perch\'e |allocmatmem()|
al suo interno chiama |allocmat()|. Nella prossima versione,
presumibilmente la funzione |allocmat()| sar\`a totalmente rivista
senza alcun riguardo per la compatibilit\`a con la vecchia versione.
Se ne sconsiglia quindi l'uso.

Analogamente, esistono le funzioni di basso e di alto livello per la
liberazione della memoria, |freemat()| e |freematmem()|.

Molto interessante \`e |allocmatcopy()|, che data una matrice gi\`a
esistente $m \times n$, ne crea un' altra con le stesse dimensioni.
Chiamiamo semplicemente |allocmatcopy()|, dando per argomento il
puntatore alla matrice gi\`a esistente e in uscita ci sar\`a fornita una
matrice identica all'originale con tutti elementi nulli.

\head *Input e Output*

\subhead *|matprint()| e |matdbg()|*

La funzione principale dell'output \`e |matprint()|, che pu\`o stampare
 anche una stringa di commento. Un' altra funzione di output quasi identica
si chiama |matdbg()|. Pu\`o essere inserita ovunque nei programmi e,
una volta definito il simbolo di preprocessore |MYDEBUG|, si comporta
come |matprint()|, altrimenti non \`e compilata.
|matprint()| mostra sullo schermo la matrice ordinata per righe e
per colonne, nei limiti della finestra di visualizzazione. Per cui le
righe e le colonne non visualizzabili sono mostrate in una schermata
successiva. Questo lavoro di ordinamento del formato comporta un maggior
tempo di elaborazione, poco importante visto che la maggiore limitazione
proviene dalla velocit\`a della periferica (scroll del video, in questo
caso).
Volendo fare a meno di questa funzione di ordinamento, \`e possibile
chiamare la funzione |matrawprint()|, che mostra la matrice senza
tenere in alcun conto i limiti di visualizzazione. In quest' ultimo caso
sta al programmatore verificare la correttezza dell'operazione.

\subhead *|printusing()|*

Il formato dell'output, dato da |matprint()| o da |matdbg()|, \`e
definito dalla funzione |printusing()|, che pu\`o definire il numero
delle cifre intere prima e dopo la virgola nel formato floating point o
solamente della parte intera per la stampa dei numeri interi\note{Quest' ultima opzione pu\`o sembrare un p\`o ridondante, vista la
limitazione della libreria ai soli numeri in virgola mobile, ma \`e stata
inserita, perch\'e alcune funzioni interne di libreria adoperano il formato
intero. Inoltre, \`e una opzione che trover\`a piena applicazione con l'
estensione di alcune funzioni anche alle matrici di numeri interi.}.
La funzione |printusing()|, mutuata interamente dal {\it BASIC}, pu\`o
essere chiamata anche una sola volta e dal quel momento in poi essa
influenza tutte le funzioni di uscita dei dati della libreria. Pu\`o essere
richiamata quante volte si vuole, sempre per ridefinire l'output.

\subhead *Input da file*

Vi sono alcune funzioni per l'introduzione dati direttamente da file, tra
queste |openmatfile()|, che apre il file dove sono conservati i dati
da inserire in matrice e carica in memoria il nome delle colonne di dati.
Nella {\it struttura del file}, descritta chiaramente negli {\it autodocs},
\`e specificato un nome per ogni variabile, quindi per ogni colonna di dati.
In tal modo l'apertura del file comporta il caricamento in memoria di
questi nomi e la definizione di puntatori alla struttura del file.
Un' altra funzione |matinp()| si preoccupa di caricare  in matrice i
dati prelevati dal file.

Tra |openmatfile()| e |matinp()| pu\`o essere inserita la
funzione |choosematvar()|, che permette la scelta delle variabili da
introdurre. In alternativa, il flag  |ALLVAR| permette di comunicare
alla funzione |matinp()| che si desiderano tutte le colonne di dati.

Praticamente un file dati pu\`o contenere anche un gran numero di colonne
per\`o noi possiamo scegliere di caricare solo la colonna 3 e la colonna 15,
e in tal modo ottenere una matrice di solo due colonne per N dati. I nomi
sono forniti solamente per facilitare l'operazione di scelta. Ad es., nel
file sono inserite le variabili x1, x2, ..., xn, ma volendo posso caricare
nella matrice solo x1 e x15.

La funzione |choosematvar()| pu\`o essere chiamata anche pi\`u volte
sullo stesso file. Ad es., per effettuare l'analisi statistica delle
colonne y1 e y2 contro le colonne x1, x2 e x4, essendo tutti questi dati
contenuti nello stesso file. In tal modo \`e possibile caricare dallo
stesso file di dati anche pi\`u matrici con composizione diversa.
All'inverso, non \`e ancora possibile caricare in una sola matrice dati
provenienti da pi\`u file\note{Purtroppo, per motivi di
compatibilit\`a con altri sistemi operativi, non \`e disponibile al momento
una interfaccia iconica che guidi la scelta delle variabili. Aggiungerla
sarebbe facile. Aggiungerla in modo da garantire il funzionamento in altri
ambienti \`e estremamente difficile.}.

La funzione |file2matrix()| si preoccupa di gestire la chiamata a
|openmatfile()| e |matinp()| in modo automatico compresa
|choosematvar()|.
In tal modo |file2matrix("filename",flag)| restituisce direttamente la
matrice dei dati richiesti. Il flag pu\`o essere ALLVAR o CHOOSE, per
indicare rispettivamente la scelta automatica di tutte le variabili del
file oppure la loro scelta.

\subhead *Formato del file*

I dati possono essere inseriti nel file adoperando un semplice editor
{\it ASCII}, rispettando il formato previsto e descritto negli autodocs.

Questo formato proprietario consiste in un primo file |.def|, che
definisce quante righe e quante colonne e poi un altro rigo in cui sono
inseriti i nomi delle variabili. Il secondo file non \`e altro che la matrice
vera e propria, organizzata per righe e colonne e il suo nome deve avere
un' estensione {\it .exp}. Il tipo dei dati \`e sempre la stringa ASCII,
convertita poi in floating point direttamente da |matinp()|.

\subhead *|mattransform()|*


La routine |mattransform()| \`e in grado di effettuare alcune variazioni dei dati
in entrata cio\`e pu\`o fare automaticamente la {\it conversione in logaritmo}
oppure caricare il dato cos\`{\i} come appare. Si pu\`o specificare anche che una
delle colonne della matrice non deve essere influenzata dai dati in entrata ma
deve essere posta a una {\it costante}. Questo \`e utile ad es.
nell'analisi di {\it regressione statistica } in cui la prima colonna
deve essere sempre posta a 1.

La scelta della funzione logartimica per la trasformazione dei dati \`e
evidente, perch\'e la maggior parte delle operazioni statistiche (ad esempio la
{\it regressione)} possono prevedere vari tipi di modelli in cui i dati in
ingresso devono essere trasformati per ottenere un determinato risultato.
La {\it trasformazione logaritmica} \`e finalizzata al trattamento di certi
problemi tipici dell'analisi statistica.

Con la funzione |settranform()| \`e possibile configurare
|mattransform()|, in modo che trasformi i dati del file servendosi
di una funzione diversa, anche definita dall'utente, purch\'e sia una
funzione di un solo parametro double e tale da restituire un risultato
double. L'unico problema (ma sussiste anche per il logaritmo) \`e che
non esiste alcun controllo sulla possibilit\`a di effettuare l'operazione
sui dati. Qualora quindi il file contenga un numero negativo e se ne
calcoli il logaritmo (operazione impossibile, per i numeri reali), si
cade ovviamente in errore.

In breve , {\it AMT} non \`e in grado di controllare che i dati del file siano
elaborabili correttamente mediante un' operazione definita dall'utente.

In ultima analisi il problema della {\it consistenza} tra dati e funzione
definita dall'utente attiene al solo programmatore.

Infine, la funzione |matrandom()| riempie una matrice $m \times n$  di numeri
casuali.

\head *Alcune Funzioni di Libreria*

La descrizione dettagliata di tutte le funzioni della libreria pu\`o essere
senz'altro omessa, in quanto completamente disponibile negli AutoDocs.

\`E pi\`u utile invece spendere qualche parola sull'uso di una funzione
fondamentale quale la moltiplicazione matriciale. Come per l'analoga
operazione numerica, partendo da due matrici, si moltiplica e si ha un
risultato. Sembra ovvio, ma la sua applicazione prevede una certa consistenza
tra le matrici in entrata e quella in uscita, pi\`u precisamente per quanto
attiene le righe e le colonne. Una matrice $m \times n$, moltiplicata per una
$n \times r$, fornisce una $m \times r$ in uscita.

Le dimensioni che stanno al centro devono essere identiche e l'uscita \`e
costituita dalle due dimensioni esterne. Questo concetto \`e molto semplice
e pu\`o dare idea degli errori che si possono commettere nell'uso delle
matrici. Se le matrici non sono consistenti, la libreria fallir\`a nel fare
la moltiplicazione ed \`e previsto che dia un messaggio di errore se \`e
definito il simbolo |MYDEBUG|.
La {\it gestione dell'errore} in questo caso non \`e ottimizzata, per\`o
senz'altro \`e gi\`a abbastanza efficiente.
Alla prima condizione di errore, la libreria fallisce nell'operazione
richiesta. Molte funzioni hanno una specifica di tipo {\it BOOL}, sono
cio\`e {\it variabili logiche}, per cui forniscono un valore vero o falso
in uscita.
La condizione di errore \`e presentata allora come "buon fine" o "cattivo
esito" di una particolare operazione.

\`E possibile quindi avere gi\`a in fase di programmazione un' uscita logica
che ci fa conoscere se la routine abbia avuto successo o meno.
Gli {\it errori di consistenza} possono essere cos\`{\i} identificati.
Anche nel caso della moltiplicazione matriciale, la funzione \`e una
variabile logica, perch\'e la matrice risultato \`e data come terzo argomento
della funzione.
Dalla definizione del simbolo |MYDEBUG| si possono ottenere ulteriori
informazioni.
Per la funzione |matper()| la macro associata con il supporto Debug
\`e |MatPer()|. In generale, fuoriesce il messaggio
{\it Check Matrix Dimensions}, quando vi sono errori di consistenza\note{Occorre notare che per questa funzione non \`e possibile per\`o
adoperare contemporaneamente la macro per il supporto Debug e la
restituzione del valore logico dell'operazione. Per maggiori ragguagli
su ogni funzione, fare riferimento agli AutoDocs.}.

Le {\it dimensioni interne} devono essere uguali e le {\it dimensioni
esterne} definiscono le dimensioni della matrice risultato.
Questa schematizzazione della moltiplicazione matriciale pu\`o essere vista
come una {\it contrazione}\note{Il concetto di contrazione \`e mutuato
dalla teoria dei tensori.}, cio\`e sono fornite due matrici con quattro
dimensioni e le due dimensioni centrali sono uguali. La ripetizione di una
dimensione provoca la sua contrazione, cio\`e le dimensioni centrali
spariscono e restano solo le due dimensioni esterne.
Il caso descritto \`e quello molto particolare della moltiplicazione
{\it righe per colonne}, che pu\`o essere ottenuta anche mediante la
funzione |matrowcol()|.

Ma \`e possibile definire moltiplicazioni {\it colonne per colonne},
{\it righe per righe} e {\it colonne per righe}.
Una moltiplicazione colonne per colonne equivale a moltiplicare la trasposta
della prima per la seconda.
Il vantaggio di una moltiplicazione per colonne \`e quello di poter gestire
facilmente l'elevazione al {\it quadrato di una matrice}.
La funzione |matpower()| fornisce gi\`a il risultato richiesto,
direttamente, senza richiedere una copia trasposta. Essa \`e utile quando
si calcola la deviazione standard per colonne di dati, cio\`e una colonna
corrisponde a una variabile.
Una moltiplicazione colonne per righe equivale a moltiplicare la trasposta
della prima per la trasposta della seconda, ovvero a moltiplicare la
seconda per la prima e a fare poi la trasposta della matrice risultato.
Una moltiplicazione righe per righe  equivale a moltiplicare la prima per
la trasposta della seconda.

Tutte queste funzioni possono essere ottenute utilizzando la procedura di
configurazione della funzione |matper()|.

La funzione |matpercol()| effettua direttamente la moltiplicazione
colonne per colonne.

Un' altra funzione di uso prevalentemente statistico \`e |matstandard()|,
che calcola la media e la deviazione standard colonna per colonna e
sostituisce ogni dato con il valore della {\it variabile standardizzata z}\note{La variabile standardizzata \`e definita cos\`{\i}:
z = [(variabile - media)/deviazione standard]}.
Questa funzione \`e importante, perch\'e molti calcoli statistici devono
essere eseguiti su variabili standardizzate e non sulle variabili
originarie.

Cito la disponibilit\`a della funzione |matinv()|, che fornisce la
{\it matrice inversa} di una matrice quadrata assegnata e ne calcola anche il
{\it determinante}, mentre |matavl()| fornisce invece la matrice
degli {\it autovalori} e degli {\it autovettori} di una matrice simetrica.

\head *Funzioni Vettoriali*

Una {\it matrice di funzioni}, invece di essere costituita da singoli
dati numerici, ha come singolo elemento una funzione che restituisce un
dato numerico.

La {\it struttura matfunc} \`e definita in modo un po' pi\`u complicato,
come un puntatore di puntatore di puntatore a funzione che restituisce un
{\it double}.


\verbatim
struct matfunc  {
	double  (***mt)();
	UWORD  rows, cols;
};
\endverbatim


Le funzioni possono coincidere con {\it funzioni matematiche del sistema}
(logaritmo seno, coseno, etc.) oppure possono essere {\it definite
dall'utente}, come elaborazioni anche molto complicate dei dati in entrata.

La funzione |loadmatfunc()| permette di caricare dinamicamente le
funzioni nelle matrici funzionali.

Tutte le funzioni presenti in una matrice funzionale sono dipendenti da
un solo {\it parametro} $t$. La funzione |matfunccopy()| calcola i
valori di tutte le {\it funzioni elemento}, in dipendenza del valore del
parametro $t$ fornito, e li scarica in una matrice che \`e la {\it  copia
numerica} relativa al valore del parametro $t$.
Ad esempio, se $t$ \`e il tempo, \`e possibile controllare, istante per istante i
punti in movimento di un {\it modello filamentare} o {\it wireframe},
 una volta definite le funzioni che governano il movimento di questi punti
nello spazio.
Il punto si muove vincolato a una {\it traiettoria} descritta da una certa
equazione. Questa dipende in generale solo da $t$ e, nelle {\it curve cosidette
regolari}, le coordinate x,y,z possono essere espresse in funzione del solo
parametro $t$. (al massimo due)

Anche per le matrici di funzioni sono definite l'{\it occupazione} e la
{\it liberazione di memoria}. Queste operazioni devono corrispondere a una idea
completamente diversa, in quanto si deve riservare spazio in memoria per
puntatori a funzione non per dei semplici dati numerici.
In parallelo alla esistenza per le matrici di dati di funzioni quali
|mateq()| (pone tutta la matrice al valore della costante K),
|matzer()| (pone ogni elemento a zero) o |matidn()| (pone tutta
la diagonale principale a uno), esistono le loro {\it estensioni} nel
{\it campo funzionale}, quali |matfunceq()|, |matfunczer()| e
|matfuncidn()|.
Quindi |matfunczer()| \`e una funzione che introduce in tutta
la matrice puntatori a funzioni che restituiscono zero.
Analogamente le altre.
Anche qui abbiamo |allocfuncmatcopy()|, che riserva la memoria per
una matrice di funzioni che abbia la stessa dimensione di una matrice gi\`a
esistente.

L'uso delle matrici funzionali \`e demandato solo alla {\it fantasia} del
programmatore, dal momento che le possibili applicazioni sono pressocch\'e
infinite.

\head *Elenco delle Funzioni di Libreria*



INPUT

\list
\item matinp
\item choosematvar
\item openmatfile
\item file2matrix
\item matrandom
\endlist

OUTPUT

\list
\item matdbg
\item matprint
\item matrawprint
\endlist

MEMORIA

\list
\item allocmat
\item allocmatmem
\item allocmatcopy
\item freemat
\item freematmem
\endlist

TRATTAMENTO MATRICI

\list
\item getarray
\item getdim
\endlist

CONFIGURAZIONE

\list
\item InitKernel
\item CloseKernel
\item printusing
\item settransform
\item setprecision
\item setiterations
\item setterm
\item getprecision
\item getiterations
\item getseed
\item getepsilon
\item getformat
\item getlastprecision
\item getlastiteration
\endlist

CALCOLO MATRICIALE

\list
\item mateq
\item matzer
\item matidn
\item matcopy
\item mattrs
\item mattrsrd
\item matplus
\item matper
\item matrowcol
\item matpercol
\item matscal
\item matpower
\item matsymm
\item mattrace
\item matcopyrd
\item matstandard
\item matinv
\item matavl
\item matorder
\item matnorm
\endlist

MEMORIA FUNZIONI VETTORIALI

\list
\item allocfuncmat
\item allocfuncmatmem
\item allocfuncmatcopy
\item freefuncmat
\item freefuncmatmem
\endlist

FUNZIONI VETTORIALI

\list
\item matfuncnull
\item matfuncidn
\item matfunccopy
\item matfunceq
\endlist

TRATTAMENTO FUNZIONI VETTORIALI

\list
\item getfuncarray
\item getfuncdim
\item loadmatfunc
\endlist

\head *Ringraziamenti*

Gran parte della documentazione sarebbe stata incompleta e senz'altro
non ben leggibile senza l'aiuto di |makeguide| di Sebastiano Vigna e
Reinhard Spisser. Sempre riguardo la documentazione, gli AutoDocs
allegati sono stati scritti adoperando AutoDoc e AD2AG \copyright{} Commodore.

Molte idee sono state prese a prestito e ampliate, a partire da libri
di vari Autori

Altri spunti mi sono stati offerti dalla lettura di aree specializzate
su INTERNET, specie quelle che trattano di BioMeccanica e delle varie
applicazioni degli Elementi Finiti, dove il calcolo matriciale \`e davvero
una premessa irrinunciabile.

Ringrazio inoltre Raffaele Carbone, per avermi seguito e stimolato
durante la stesura del codice e Amelia Morra per aver pazientemente
digitato da capo una prima versione del sorgente, dopo un irreparabile
guasto della memoria di massa su \amiga{}.

{\signaturewidth=16pc
\makesignature}

\head  *Bibliografia*        % Togliere il simbolo di commento se e' presente la Bibliografia.
\nocite{*}                   % Togliere il simbolo di commento se e' presente la Bibliografia.

\bibliographystyle{itaplain} % Togliere il simbolo di commento se e' presente la Bibliografia.
\bibliography{amt}      % Togliere il simbolo di commento se e' presente la Bibliografia.

\endarticle
