AQUARIUS MATRIX LIBRARY
***********************

Aquarius Matrix Library, version 1.02, 3 Novembre 1993

Copyright © 1993 Fausto Passariello

Libreria di Calcolo Matriciale e Funzioni Vettoriali per Amiga

Riassunto
*********

Aquarius Matrix Library, version 1.02

Libreria  di  calcolo  matriciale  e funzioni vettoriali per Amiga

Le applicazioni del calcolo matriciale sono di uso quotidia- no nel campo  scientificoe professionale. Vanno  dal calcolo strutturale  alla grafica 2D e 3D, dalle elaborazioni stati- stiche al metodo  degli elementi finiti  o all' analisi  del segnale  audio e video mediante trasformate e antitrasforma- te.

Su Amiga non  esiste a tutt'  oggi una libreria  di funzioni matriciali di pubblico dominio.

Il vantaggio del calcolo matriciale e' evidente: poter trat- tare intere tabelle di dati (matrici o vettori) come un sin- golo  scalare permette una formulazione piu' sintetica e or- dinata del procedimento di  calcolo e una sua  maggiore com- prensione.

Aquarius  Matrix Library fornisce belle e pronte le funzioni piu' classiche del calcolo matriciale (copia, stampa,  addi- zione, moltiplicazione, inversa e determinante di una matri- ce quadrata, calcolo di autovalori e autovettori).

Vi sono pero' anche altre funzioni piu' sofisticate e di uso piu' specialistico quali l' immissione dei dati da file e la loro  contemporanea conversione logaritmica, oppure la stan- dardizzazione delle colonne di dati con calcolo della varia- bilita' intorno alla  media.

Insolite, poi sono le funzioni vettoriali o meglio matricia- li.

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 x 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.2. E'  prevista una sua versione futura  in C++, mentre a tutt' oggi il  codice puo'  essere compilato  senza variazioni  su piattaforme MS/DOS.

CopyRight
*********

Aquarius Matrix Library, version 1.02

Copyright © 1993 Fausto Passariello

AMTieee.lib e AMTieee.library sono librerie di Pubblico Dominio (PD).

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 PD, e' vivamente suggerita la registrazione dell' utente, per poter accedere via Email alle nuove versioni.

Inoltre, l' Autore gradira' molto la segnalazione della produzione di software adoperando le funzioni della libreria.

Nulla e' dovuto per la produzione di software PD.

Al contrario, la produzione di software commerciale, adoperando le funzioni della libreria, sia essa LINKABLE o 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 AMTieee, potra' essere considerata una violazione delle vigenti norme di legge italiane sul diritto di autore e potra' essere perseguita nei modi previsti dalla legge.

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

La libreria AMTieee e' fornita cosi' come e', senza nessuna garanzia che serva a uno scopo prefissato.

L' Autore declina ogni responsabilita' 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 sara' competente il Foro di Napoli, Italia.

Storia
******

La storia di AMTieee.library inizia molto tempo addietro:

1983

Primo nucleo di routines, scritte in BASIC per il computer VIC20. Queste sono adoperate per la scrittura di programmi di analisi statistica multivariata.

1988

Traduzione del programma originario nel Basic © MicroSoft di Amiga 1000, con il nome di MULTIPLE.BAS, programma di ANALISI STATISTICA MULTIVARIATA. Esso comprende la REGRESSIONE MULTIPLA, L' ANALISI IN COMPONENTI PRINCIPALI E LA CORRELAZIONE CANONICA.

1993

Traduzione in C del nucleo matriciale dei programmi precedenti. L' operazione e' necessaria, per l' assenza di un BASIC di sistema su AMIGA, da A3000 in poi, anche se validamente sostituito da ARexx.

Con la corrente stesura della libreria, i programmi suddetti si sono notevolemente ridotti di dimensioni, guadagnando notevolemente in velocita' e chiarezza.

VERSIONI DISTRIBUITE:

1.00    18 ottobre 1993

AMTieee.lib, linkable library.

1.02    3 Novembre 1993

Corretta la funzione checkdim(), nel controllo della operazione matinv().

Corretta la funzione matinv() per un bug evidente per valori negativi del pivot.

Introdotto un demo semplificato per il calcolo delle soluzioni di piu' sistemi di equazioni, tutti dipendenti dalla stessa matrice di coefficienti.

Introduzione
************

Esiste uno spazio da riempire, lo spazio attualmente abbastanza vuoto delle 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 piu' 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 potra' 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 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.

Installazione
*************

La procedura e' estremamente semplice:

  * scegliere un percorso <path>

  * MAKEDIR <path>AMT

  * COPY amtieee.lha <path>AMT/

  * cd <path>AMT

  * lha x amtieee

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

ASSIGN AMT: <percorso_scelto>

La libreria e' disponibile in due versioni, una LINKABKE con nome amtieee.lib, l' altra SHARED, con nome amtieee.library.

Se si installa la libreria SHARED, allora occorre copiarla nel device LIBS:

COPY amtieee.library LIBS:

La libreria SHARED non e' al momento distribuita, perche' ancora in fase di rifinitura.

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

#define bug printf

#ifdef MYDEBUG

#define D(x) x

#else

#define D(x) ;

#endif

Applicazioni del Calcolo Matriciale
***********************************

Grafica 2D e 3D
===============

L' utilita' del calcolo matriciale e' evidente. L' esempio piu' classico, piu' vicino alle applicazioni pratiche usate da tutti gli sviluppatori software e' la 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 2D e 3D puo' essere ridotta a una operazione matriciale.

Praticamente le operazioni che si fanno nel 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 perche', 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 piu' chiaro) solo se il calcolo presenta caratteri ripetitivi. Questo pero' avviene spesso nei problemi di grafica.

Calcolo Statistico
==================

Vi sono moltissimi altri campi in cui e' possibile applicare il calcolo matriciale per scopi pratici. Uno di questi e' il CALCOLO STATISTICO. Esso puo' essere eseguito in modo elementare calcolando medie, deviazioni standard e cosi via. Oppure, in modo molto piu' ordinato, su un insieme di dati caricati in matrice, eseguendo le operazioni su tante variabili, ognuna delle quali sara' 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 piu' pratiche abbiamo l' analisi di regressione, l' analisi discriminante, l' analisi in componenti principali, etc.

Esse sono le applicazioni tipiche dell' analisi multivariata, che sono complicate a tal punto da essere affrontabili soltanto con il calcolo matriciale.

Metodo degli Elementi Finiti
============================

Un altro campo particolare e' per esempio l' analisi delle strutture con il 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 puo' giungere alla definizione di una matrice di dati e di una colonna di variabili incognite.

Non e' qui il caso di accennare neanche alla complessita' del problema.

Analisi del Segnale
===================

Altra applicazione importante e' quella dell' ANALISI DEL SEGNALE audio o video mediante TRASFORMATE. Se queste trasformate sono eseguite in modo artigianale, hanno una certa complessita' di elaborazione. Se invece le concepiamo come trasformazioni matriciali, assumono una versione molto semplificata. Chiaramente la velocizzazione della trasformata ci puo' imporre di abbandonare lo schematismo matriciale.

La DFT, (Discrete Fourier Transform o 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.

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 puo' essere considerata alla stregua di un solo numero o 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 scalare. Un insieme di numeri organizzati in sequenza e' un vettore. Una tabella organizzata in righe e colonne e' una matrice.

Molto piu' tecnicamente si puo' dire che:

  * uno scalare e' un tensore di ordine 0

  * un vettore e' un tensore di ordine 1

  * una matrice e' un tensore di ordine 2

Esistono anche tensori di ordine 3,4.5...

In ultimo, vorrei accennare solo al fatto che, in un' ottica senz' altro piu' vasta, le matrici non sono altro che singoli elementi di uno spazio vettoriale, cioe' vettori, indipendentemente dalla loro dimensione.

Aquarius Matrix Library
***********************

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 legare al codice, allora l' apertura deve essere effettuata mediante la funzione InitKernel(), mentre per la chiusura si adopera l' analoga CloseKernel().

Aquarius Matrix Library (AMT) e' scritta in modo che possa essere adoperata con un piccolo o con un enorme numero di dati. Chiaramente AMT fallira' con dei messaggi d' errore, se non riuscira'  a riservare la memoria richiesta dai dati.

AMT e' scritta in C e non ancora in C++ e compilata con SAS/C 6.3

La naturale estensione al C++ sara' il prossimo passo. Attualmente la libreria e' organizzata su numeri floating point , in C++ sara' 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, ne' per numeri in virgola mobile, ne' per numeri complessi ne' per numeri interi. Questo e' solo un primo passo.

La Definizione di Matrice
=========================

Tutte le funzioni di libreria sono scritte in  modo che, volendo, si possa accedere direttamente alla struttura della matrice cosi' come e' definita, ma sono fornite anche funzioni per estrarre gli elementi della matrice senza dover accedere in modo opaco alla definizione.

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

Quindi il secondo approccio e' non compatibile con le future versioni, perche'magari cambiera' la struttura della matrice. Analogamente, per sapere quanto e' grande una matrice si puo' adoperare la funzione getdim() con il qualificatore MATRAW oppure MATCOL (riga o colonna), con un metodo consistente con le future versioni di AMT.

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

struct matrix  {

double  **mt;

UWORD  rows, cols;

};

AMT e' costruita in modo che non debba essere definita in partenza la dimensione delle matrici. Scrivere un calcolo matriciale in cui e' gia' deciso in partenza che le matrici sono 4x4. (es., in grafica 3D) e' molto piu' semplice. Invece AMT puo' eseguire tutte le operazioni su matrici MxN, comunque definite.

Ci sono altri modi per definire un matrice, per esempio con un solo array mono-dimesionale (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 da' messaggi di errore.

Il primo metodo invece dara' errore, perche'  la matrice e' costruita con un array monodimensionale.

Configurazione
==============

L' apertura di AMT determina l' inizializzazione di un nucleo interno di dati Kernel.

Le funzioni setiterations() e getiterations() permettono la selezione del 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 gia' 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() see printusing(). e leggibile con getformat(). Quest' ultima funzione ha per argomento il valore logico INTFMT o FLOATFMT, definito nel file include della libreria.

Analogamente, e' possibile leggere la massima precisione fornita dalla macchina, tramite la funzione getepsilon(). Al momento, la procedura legge solo il valore dichiarato della libreria matematica, mentre in futuro restituira' 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 seme esterno della sequenza dei numeri pseudocasuali puo' essere letto tramite la funzione getseed(). Il valore e' privato per ogni singolo utente della libreria.

L' utilita' e' evidente. Il carattere pseudocasuale delle sequenza si conserva solo se si riutilizza il seme gia' 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 piu' 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:

  * PER moltiplicazione righe per colonne

  * PERCOL moltiplicazione colonne per colonne

  * COLROW moltiplicazione colonne per righe

  * ROWROW moltiplicazione righe per righe

In pratica, all' apertura la libreria e' configurata per la moltiplicazione righe per colonne, che e' la forma piu' adoperata. See Alcune Funzioni di Libreria.

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' piu' 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. See printusing(). See mattransform().

Procedure di Debug
==================

Su Amiga il Debug puo' essere facilitato inserendo messaggi di commento tra le righe di codice. La procedura puo' essere controllata definendo il simbolo di preprocessore MYDEBUG. In mancanza della definizione, tutti i commenti non sono compilati e non appesantiscono il codice oggetto. See Installazione.

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 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 Debug.

Ad es., per matplus() la funzione analoga con supporto 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, perche' queste facilmente si trasformano nelle loro equivalenti, spegnendo l' interruttore MYDEBUG.

Il tipo di informazione che fuoriesce dal Debug riguarda prevalentemente la 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 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. See Alcune Funzioni di Libreria. Questi casi sono segnalati negli AutoDocs.

Funzioni di Occupazione di Memoria
**********************************

E' possibile definire una matrice chiamando allocmatmem(), fornendo due dimensioni M e N. E' restituito un puntatore a matrice. In alternativa, e' possibile definire un' 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 perche' allocmatmem() al suo interno chiama allocmat(). Nella prossima versione, presumibilmente la funzione allocmat() sara' totalmente rivista senza alcun riguardo per la compatibilita' 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 gia' esistente MxN, ne crea un' altra con le stesse dimensioni.

Chiamiamo semplicemente allocmatcopy(), dando per argomento il puntatore alla matrice gia' esistente e in uscita ci sara' fornita una matrice identica all' originale con tutti elementi nulli.

Input e Output
**************

matprint() e matdbg()
=====================

La funzione principale dell' output e' matprint(), che puo' stampare anche una stringa di commento. Un' altra funzione di output quasi identica si chiama matdbg(). Puo' essere inserita ovunque nei programmi e, una volta definito il simbolo di preprocessore MYDEBUG, si comporta come matprint(), altrimenti non e' compilata. See Procedure di Debug.

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 velocita' 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.

printusing()
============

Il formato dell' output, dato da matprint() o da matdbg(), e' definito dalla funzione printusing(), che puo' 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.

 (Quest' ultima opzione puo' sembrare un po' ridondante, vista la limitazione della libreria ai soli numeri in virgola mobile, ma e' stata inserita, perche' alcune funzioni interne di libreria adoperano il formato intero. Inoltre, e' una opzione che trovera' piena applicazione con l' estensione di alcune funzioni anche alle matrici di numeri interi.)

La funzione printusing(), mutuata interamente dal BASIC, puo' essere chiamata anche una sola volta e dal quel momento in poi essa influenza tutte le funzioni di uscita dei dati della libreria. Puo' essere richiamata quante volte si vuole, sempre per ridefinire l' output.

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 struttura del file, see formato del file. descritta chiaramente negli 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(), puo' 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 puo' contenere anche un gran numero di colonne pero' 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() puo' essere chiamata anche piu' 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 piu' matrici con composizione diversa. All' inverso, non e' ancora possibile caricare in una sola matrice dati provenienti da piu' file.  (Purtroppo, per motivi di compatibilita' 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 puo' essere ALLVAR o CHOOSE, per indicare rispettivamente la scelta automatica di tutte le variabili del file oppure la loro scelta.

formato del file
================

I dati possono essere inseriti nel file adoperando un semplice editor 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 .exp. Il tipo dei dati e' sempre la stringa ASCII, convertita poi in floating point direttamente da matinp().

mattransform()
==============

La routine mattransform() e' in grado di effettuare alcune variazioni dei dati in entrata cioe' puo' fare automaticamente la conversione in logaritmo oppure caricare il dato cosi' com' e'. Si puo' specificare anche che una delle colonne della matrice non deve essere influenzata dai dati in entrata ma deve essere posta a una costante. Questo e' utile ad es. nell' analisi di 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, perche' la maggior parte delle operazioni statistiche (ad es. la regressione) possono prevedere vari tipi di modelli in cui i dati in ingresso devono essere trasformati per ottenere un determinato risultato. La 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, purche' 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 possibilita' 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.

Cioe', 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 consistenza tra dati e funzione definita dall' utente attiene al solo programmatore.

Infine, la funzione matrandom() riempie una matrice MxN  di numeri casuali. See Configurazione.

Alcune Funzioni di Libreria
***************************

La descrizione dettagliata di tutte le funzioni della libreria puo' essere senz' altro omessa, in quanto completamente disponibile negli autodocs.

E' piu' 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, piu' precisamente per quanto attiene le righe e le colonne. Una matrice MxN, moltiplicata per una NxR, fornisce una MxR 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 puo' dare idea degli errori che si possono commettere nell' uso delle matrici. Se le matrici non sono consistenti, la libreria fallira' nel fare la moltiplicazione ed e' previsto che dia un messaggio di errore se e' definito il simbolo MYDEBUG.

La gestione dell' errore in questo caso non e' ottimizzata, pero' senz' altro e' gia' abbastanza efficiente. See Procedure di Debug.

Alla prima condizione di errore, la libreria fallisce nell' operazione richiesta. Molte funzioni hanno una specifica di tipo BOOL, sono cioe' 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 gia' in fase di programmazione un' uscita logica che ci fa conoscere se la routine abbia avuto successo o meno. Gli errori di consistenza possono essere cosi' identificati. Anche nel caso della moltiplicazione matriciale, la funzione e' una variabile logica, perche' la matrice risultato e' data come terzo argomento della funzione.

Dalla definizione del simbolo MYDEBUG si possono ottenere ulteriori informazioni. See Procedure di Debug.

Per la funzione matper() la macro associata con il supporto Debug e' MatPer(). In generale, fuoriesce il messaggio Check Matrix Dimensions, quando vi sono errori di consistenza. (Occorre notare che per questa funzione non e' possibile pero' 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 dimensioni interne devono essere uguali e le dimensioni esterne definiscono le dimensioni della matrice risultato.

Questa schematizzazione della moltiplicazione matriciale puo' essere vista come una CONTRAZIONE  (Il concetto di CONTRAZIONE e' mutuato dalla teoria dei TENSORI.), cioe' sono fornite due matrici con quattro dimensioni e le due dimensioni centrali sono uguali. La ripetizione di una dimensione provoca la sua contrazione, cioe' le dimensioni centrali spariscono e restano solo le due dimensioni esterne.

Il caso descritto e' quello molto particolare della moltiplicazione righe per colonne, che puo' essere ottenuta anche mediante la funzione matrowcol.

Ma e' possibile definire moltiplicazioni colonne per colonne, righe per righe e 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 quadrato di una matrice. La funzione matpower() fornisce gia' il risultato richiesto, direttamente, senza richiedere una copia trasposta. Essa e' utile quando si calcola la deviazione standard per colonne di dati, cioe' 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(). See Configurazione.

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 variabile standardizzata z. (La variabile standardizzata e' definita cosi':

z = [(variabile - media)/deviazione standard])

Questa funzione e' importante, perche' molti calcoli statistici devono essere eseguiti su variabili standardizzate e non sulle variabili originarie.

Cito solo la disponibilita' della funzione matinv(), che fornisce la matrice inversa di una matrice quadrata assegnata e ne calcola anche il determinante, mentre matavl() fornisce invece la matrice degli autovalori e degli autovettori di una matrice simetrica.

Funzioni Vettoriali
*******************

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

La struttura matfunc e' definita in modo un po' piu' complicato, come un puntatore di puntatore di puntatore a funzione che restituisce un double.

struct matfunc  {

double  (***mt)();

UWORD  rows, cols;

};

Le funzioni possono coincidere con funzioni matematiche del sistema (logaritmo seno, coseno, etc.) oppure possono essere 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 parametro t. La funzione matfunccopy() calcola i valori di tutte le funzioni elemento, in dipendenza del valore del parametro t fornito, e li scarica in una matrice che e' la  copia numerica relativa al valore del parametro t.

Ad es., se t e' il tempo, e' possibile controllare, istante per istante i punti in movimento di un modello filamentare o wireframe, una volta definite le funzioni che governano il movimento di questi punti nello spazio.

Il punto si muove vincolato a una traiettoria descritta da una certa equazione. Questa dipende in generale solo da t e, nelle 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' occupazione e la 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 estensioni nel 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 gia' esistente.

L' uso delle matrici funzionali e' demandato solo alla fantasia del programmatore, dal momento che le possibili applicazioni sono pressocche' infinite.

Elenco delle Funzioni di Libreria
*********************************

INPUT

  * matinp

  * choosematvar

  * openmatfile

  * file2matrix

  * matrandom

OUTPUT

  * matdbg

  * matprint

  * matrawprint

MEMORIA

  * allocmat

  * allocmatmem

  * allocmatcopy

  * freemat

  * freematmem

TRATTAMENTO MATRICI

  * getarray

  * getdim

CONFIGURAZIONE

  * InitKernel

  * CloseKernel

  * printusing

  * settransform

  * setprecision

  * setiterations

  * setterm

  * getprecision

  * getiterations

  * getseed

  * getepsilon

  * getformat

  * getlastprecision

  * getlastiteration

CALCOLO MATRICIALE

  * mateq

  * matzer

  * matidn

  * matcopy

  * mattrs

  * mattrsrd

  * matplus

  * matper

  * matrowcol

  * matpercol

  * matscal

  * matpower

  * matsymm

  * mattrace

  * matcopyrd

  * matstandard

  * matinv

  * matavl

  * matorder

  * matnorm

MEMORIA FUNZIONI VETTORIALI

  * allocfuncmat

  * allocfuncmatmem

  * allocfuncmatcopy

  * freefuncmat

  * freefuncmatmem

FUNZIONI VETTORIALI

  * matfuncnull

  * matfuncidn

  * matfunccopy

  * matfunceq

TRATTAMENTO FUNZIONI VETTORIALI

  * getfuncarray

  * getfuncdim

  * loadmatfunc

Bibliografia
************

  * Plastok,R.A, Kalley,G.: Computer Grafica. Milano, Etas, Collana Schaum, 1987.

  * Haut,H.: Programmi di Matematica e Statistica in Basic. Milano, Gruppo Editoriale Jackson, 1982

  * Sadocchi, S.: Manuale di Analisi Statistica Multivariata. Milano, Franco Angeli, 1981.

  * Desmadril, M.: Analyse des Donnees en C. Paris, Eyrolles, 1989.

  * Bouroche, J.M., Saporta, G.: L' Analisi dei Dati. Napoli, CLU, 1983.

Ringraziamenti
**************

Gran parte della documentazione sarebbe stata incompleta e senz' altro non ben leggibile senza l' aiuto di MAKEGUIDE di Sebastiano Vigna e Rheinard Spissner. Sempre riguardo la documentazione, gli AutoDocs allegati sono stati scritti adoperando AutoDoc e AD2AG © Commodore.

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

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.

Autore
******

         Dott. Fausto Passariello
         Centro Diagnostico AQUARIUS
         via Francesco Cilea, 280 - Napoli
         80127 - tel. 081-654110, 7144110

         EMAIL:

         FIDONET:  2:335/229@fidonet.org
         AMIGANET: 39:102/109@amiganet.ftn
         INTERNET: aquarius@na.infn.it
         UUCP:     aquarius@lagrange.adsp.sub.org

Centro Diagnostico AQUARIUS
***************************

     --------------------------------------------------------------------------
                           A  Q  U  A  R  I  U  S    B  B  S
     --------------------------------------------------------------------------
      *cbmvax!cbmehq!cbmita!lagrange!aquarius     Dott.    Fausto   Passariello
      *  _    _         _   _  °        __        v. Francesco Cilea, 280 80127
      * / \  / \  |  | / \  /  |  |  | [_         Napoli Italia  0039-81-654110
      * \_ \ \_ | \_ \ \_ \ \_ \_ \_ \ __]        FIDONET             2:335/229
      *         |                                 AMIGANET           39:102/109
      *    \_   \_  \_  Centro Diagnostico        INTERNET  AQUARIUS@NA.INFN.IT
     --------------------------------------------------------------------------

AQUARIUS nasce in un piovoso febbraio 1984, con il none di Centro per la Diagnosi Strumentale Non invasiva delle Malattie Vascolari Periferiche.

L' associazione del nome con il Segno Astrologico, l' acqua e la circolazione del sangue sembra definitivamente ratificata dalle impietose condizioni atmosferiche.

AQUARIUS e' il simbolo che una tradizione astrologica millenaria assegna alle malattie vascolari periferiche, allo stesso modo che il segno del Leone e' legato storicamente al cuore e alle sue disfunzioni.

Nello Zodiaco segni opposti rivestono valenze opposte.

Cosi' il segno del Leone e' connesso all' azione del cuore, pompa di primaria importanza per l' organismo e fonte della circolazione sanguigna.

All' opposto AQUARIUS riceve l' energia del cuore e la trasmette all' estrema periferia.

La sua azione e' tanto piu'  valida quanto piu' veloce e' la distribuzione del sangue nei distretti lontani e quanto minore e' la degradazione energetica lungo il percorso.

AQUARIUS e' cosi' legato alla velocita', che e' la caratteristica del sangue misurata dallo strumento principale del Centro: il DOPPLER.

La velocita' e' inoltre indispensabile nella risposta diagnostica, che deve essere immediata e tale da permettere il trattamento contemporaneo di una mole cospicua di dati.

L' uso di apparecchiature elettroniche diventa cosi' indispensabile e la scelta va al trattamento dei dati in tempo reale per favorire la diagnosi.

AQUARIUS e' dominato da Urano ed e' tradizionalmente il segno della tecnica, cioe' nel nostro tempo, dell' elettronica e degli elaboratori.

AQUARIUS e' inoltre il segno della periferia, lontana dall' uniformita' e dal potere del centro, ed e' cosi' il segno della liberta' e della scelta di idee e direttive originali.

Il CENTRO DIAGNOSTICO AQUARIUS reinveste in ricerca scientifica e tecnologica la gran parte delle sue entrate economiche. Da un lato per garantire la qualita' delle prestazioni, dall' altro per portare avanti idee di rinnovamento nel campo specifico della diagnostica delle vasculopatie.