Gli ARRAY in FORTRAN 90



Похожие документы
Lezione 8. La macchina universale

Funzioni in C. Violetta Lonati

4. Operazioni elementari per righe e colonne

MATLAB. Caratteristiche. Dati. Esempio di programma MATLAB. a = [1 2 3; 4 5 6; 7 8 9]; b = [1 2 3] ; c = a*b; c

Appunti sulla Macchina di Turing. Macchina di Turing

Introduzione al MATLAB c Parte 2

Applicazioni lineari

Introduzione al linguaggio C Gli array

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Definizione di nuovi tipi in C

APPUNTI DI MATEMATICA ALGEBRA \ INSIEMISTICA \ TEORIA DEGLI INSIEMI (1)

Algebra Booleana ed Espressioni Booleane

Algoritmo. I dati su cui opera un'istruzione sono forniti all'algoritmo dall'esterno oppure sono il risultato di istruzioni eseguite precedentemente.

(anno accademico )

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }


3. La sintassi di Java

Esame di INFORMATICA

Variabili e tipi di dato

Corso di Fondamenti di Informatica

Corso di Informatica

Operazioni di input e output in Fortran 90

Anno 3. Funzioni: dominio, codominio e campo di esistenza

dall argomento argomento della malloc()

Metodologie di programmazione in Fortran 90

Dimensione di uno Spazio vettoriale

LE SUCCESSIONI 1. COS E UNA SUCCESSIONE

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

La selezione binaria

Elementi di Algebra Relazionale

Esercizi su. Funzioni

Sistemi Informativi Territoriali. Map Algebra

Rappresentazione grafica di entità e attributi

Matematica in laboratorio

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

4. Proiezioni del piano e dello spazio

Concetto di Funzione e Procedura METODI in Java

OTTAVA ESPERIENZA DI LABORATORIO. L elaborazione dei files in C

Energia potenziale elettrica e potenziale. In queste pagine R indicherà una regione in cui è presente un campo elettrostatico.

Rendering air show e verifica della sincronizzazione

Progettazione di Basi di Dati

Fortran per Ingegneri

Prova di Laboratorio di Programmazione

Vettori Algoritmi elementari di ordinamento

f(x) = 1 x. Il dominio di questa funzione è il sottoinsieme proprio di R dato da

LE FUNZIONI A DUE VARIABILI

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

5.3 TABELLE RECORD Inserire, eliminare record in una tabella Aggiungere record Eliminare record

Capitolo 2. Operazione di limite

Introduzione ai Metodi Formali

Cenni su algoritmi, diagrammi di flusso, strutture di controllo

LINGUAGGI DI PROGRAMMAZIONE

Esempi di algoritmi. Lezione III

Corso di Analisi Matematica Serie numeriche

Rette e curve, piani e superfici

CONCETTO DI LIMITE DI UNA FUNZIONE REALE

Ottimizazione vincolata

Protezione. Protezione. Protezione. Obiettivi della protezione

ESEMPIO 1: eseguire il complemento a 10 di 765

Corrispondenze e funzioni

Excel. A cura di Luigi Labonia. luigi.lab@libero.it

Organizzazione degli archivi

Progettaz. e sviluppo Data Base

I file di dati. Unità didattica D1 1

Matlab: Strutture di Controllo. Informatica B

Luigi Piroddi

Soluzione dell esercizio del 2 Febbraio 2004

Invio SMS. DM Board ICS Invio SMS

CONCETTO DI ANNIDAMENTO

Nozione di algoritmo. Gabriella Trucco

Funzioni. Il modello console. Interfaccia in modalità console

2. Spiegare brevemente qual è la funzione del compilatore e la sua importanza per il programmatore.

Studente: SANTORO MC. Matricola : 528

Descrizione di un algoritmo

Gestione della memoria centrale

IGiochidiArchimede-SoluzioniBiennio 22 novembre 2006

Capitolo Quarto...2 Le direttive di assemblaggio di ASM Premessa Program Location Counter e direttiva ORG

Come visto precedentemente l equazione integro differenziale rappresentativa dell equilibrio elettrico di un circuito RLC è la seguente: 1 = (1)

Capitolo 3. L applicazione Java Diagrammi ER. 3.1 La finestra iniziale, il menu e la barra pulsanti

DAL DIAGRAMMA AL CODICE

Algebra booleana. Si dice enunciato una proposizione che può essere soltanto vera o falsa.

Architettura (10/9/2003) Pag. 1/6. Cognome e Nome (in stampatello):

Cosa dobbiamo già conoscere?

I database relazionali sono il tipo di database attualmente piu diffuso. I motivi di questo successo sono fondamentalmente due:

Per studio di funzione intendiamo un insieme di procedure che hanno lo scopo di analizzare le proprietà di una funzione f ( x) R R

PROCEDURA INVENTARIO DI MAGAZZINO di FINE ESERCIZIO (dalla versione 3.2.0)

DAL PROBLEMA AL CODICE: ATTRAVERSO LO PSEUDOCODICE

RISOLUTORE AUTOMATICO PER SUDOKU

Macchine a stati finiti G. MARSELLA UNIVERSITÀ DEL SALENTO

Gestione della memoria. Paginazione Segmentazione Segmentazione con paginazione

Algebra Booleana 1 ALGEBRA BOOLEANA: VARIABILI E FUNZIONI LOGICHE

Un metodo per il rilevamento degli errori: la tecnica del Bit di Parità

Allocazione dinamica della memoria - riepilogo

MAPPE DI KARNAUGH. Nei capitoli precedenti si è visto che è possibile associare un circuito elettronico o elettrico ad una funzione logica.

Analisi dei Dati 12/13 Esercizi proposti 3 soluzioni

Esercizi Capitolo 6 - Alberi binari di ricerca

Metodi Stocastici per la Finanza

Una metodologia di progettazione di applicazioni web centrate sui dati

Транскрипт:

ELEMENTI DI PROGRAMMAZIONE Gli ARRAY in FORTRAN 90

Un ARRAY è un AGGREGATO di più DATI dello stesso TIPO (interi, reali, etc), ognuno univocamente individuato dal valore di uno oppure due.. e fino a sette indici. Il numero di indici definisce la DIMENSIONE dell array. Un array monodimensionale, che chiameremo VETTORE, è assimilabile concettualmente ad un elenco ordinato di valori di un certo tipo per esempio: (1, -5, 7, 0, 8) Come ogni altra variabile o costante con nome, un array può avere un NOME che lo individua globalmente come aggregato. Poi ci si potrà riferire ad un suo elemento utilizzando i succitati INDICI. Supponiamo, per esempio, di aver assegnato al vettore di cui sopra il nome Cinquina, allora Cinquina(2) sarà il suo secondo elemento cioè l intero -5. In realtà FORTRAN 90 consente un estrema flessibilità nell organizzazione del DOMINIO o RANGE di un indice. VETTORE: ( 1, -5, 7, 0, 8) RANGE: [-2, -1, 0, 1, 2] Definito così il RANGE, per riferirci all elemento -5 del vettore dovremo scrivere Cinquina(-1). Dall esempio è sufficientemente evidente che un RANGE è dato definendone gli estremi, nel nostro caso -2 e 2, così che l ESTENSIONE del vettore risulta come LIMSUP-LIMINF+1.

Gli array bidimensionali, che chiameremo MATRICI, sono concettualmente assimilabili a tabelle ordinate secondo indici di riga e colonna. Supponendo - ad esempio - data una matrice di nome Tabella, con elementi INTERI disposti su quattro righe e tre colonne, avremo lo schema concettuale che segue: L elemento Tabella(3, 2) individuerà quindi l intero 1024 posto all intersezione fra la terza riga e la seconda colonna.

In effetti, lo schema precedente illustra anche un ulteriore importante peculiarità degli Array multidimensionali così come implementati da FORTRAN 90: la cosiddetta organizzazione per colonne. Le frecce in figura evidenziano appunto un criterio di linearizzazione della struttura bidimensionale, un ordine interno, su cui al momento non ci soffermeremo ripromettendoci di riconsiderarlo al momento opportuno. Resta valido quanto detto sulla flessibilità del range per gli indici. Supponiamo di aver definito per l indice di riga: INIZIO=10, FINE=13 E per l indice di colonna: INIZIO=-1, FINE=1 Allora l elemento di matrice evidenziato in figura dovrebbe essere riferito come Tabella(12, 0).

La sintassi generale di una istruzione di dichiarazione Fortran 90 per un array è la seguente: tipo, DIMENSION(range1 [,range2 [..range7]] ) [, attributo,...] :: lista_di_array in cui tipo è il il tipo di appartenenza di tutti i componenti della lista_di_array, la parola chiave DIMENSION è un attributo che serve a specificare la dimensione dell array che si sta dichiarando, mentre range1,.. range7 forniscono i range in cui spaziano gli indici dell array in ogni dimensione. Esempi: INTEGER, DIMENSION(10) :: Numeri CHARACTER, DIMENSION(-2:5, 3) :: CharTab REAL, DIMENSION(-9:0, 2:5) :: RealTab! Numeri è un vettore di interi e dimensione 10! CharTab è una matrice di caratteri con 8 righe e 3 colonne! RealTab è una matrice di reali con 11 righe e 4 colonne

Un array deve essere, prima di ogni utilizzazione, esplicitamente inizializzato. L inizializzazione può essere effettuata a tempo di esecuzione, utilizzando una variabile indice, come negli esempi che seguono:! Esempio 1 INTEGER, DIMENSION(10) :: Numeri INTEGER i DO i=1,10 Numeri(i)=2**i END DO! Esempio 2 INTEGER, DIMENSION(-10:10:2) :: Numeri INTEGER i DO i=-10,10, 2 READ(*,*) Numeri(i) END DO

L inizializzazione può essere anche realizzata a tempo di compilazione, utilizzando i cosiddetti COSTRUTTORI:! Qui l array è inizializzato contestualmente alla sua! dichiarazione INTEGER, DIMENSION(5) :: Numeri=(/ 1, 5, -7, 3, 4 /) Comunque, il costruttore può essere utilizzato per inizializzare l array a tempo di esecuzione: INTEGER, DIMENSION(-2:2) :: Numeri Numeri =(/ 1, 5, -7, 3, 4 /)

INDICI Qualsiasi espressione che fornisce come risultato un intero è un indice valido per un array. Consideriamo, come esempio, il segmento di codice: REAL, DIMENSION(5) :: lista=(/ 3, 4, -5, 6, 3/) INTEGER :: i=1, j=5 WRITE(*,*) lista(i)!corretto, fornisce come output lista(1), quindi 3 WRITE(*,*) lista(i+j/2)!corretto, fornisce come output lista(3), quindi -5 WRITE(*,*) lista(i+0.5*j)!il compilatore denuncia un errore di tipo, infatti il valore dell espressione-indice è di!tipo reale WRITE(*,*) lista(i+j)!errore di out-range in compilazione

DO IMPLICITO Quando si lavora con gli array risulta particolarmente utile utilizzare un costrutto logico che consente di realizzare iterazioni per così dire implicite. Per esempio il segmente di codice che segue.. DO i=1,10 lista(i)=1000*i END DO potrebbe essere sostituito dalla singola linea di codice.. lista(i)=(/ (1000*i, i=1, 10) /) dove il costrutto (1000*i, i=1, 10) costituisce il cosiddetto DO IMPLICITO. In altre parole REAL, DIMENSION(5) :: lista=(/ 3, 4, -5, 6, 3/) INTEGER :: i=1, j=5 WRITE(*,*) lista(i)!corretto, fornisce come output lista(1), quindi 3 WRITE(*,*) lista(i+j/2)!corretto, fornisce come output lista(3), quindi -5 WRITE(*,*) lista(i+0.5*j)!il compilatore denuncia un errore di tipo, infatti il valore dell espressione-indice è di!tipo reale WRITE(*,*) lista(i+j)!errore di out-range in compilazione

Un array dinamico è dichiarato utilizzando l attributo ALLOCATABLE. Poichè le sue dimensioni non sono note all atto della dichiarazione, il limite di ciascuno dei suoi indici va sostituito con il simbolo dei due punti: tipo, ALLOCATABLE, DIMENSION(: [, :,...]) :: nome_array Esempi: integer, ALLOCATABLE, DIMENSION(:) :: elenco_interi character(10), ALLOCATABLE, DIMENSION(:,:) :: tabella_parole

Le estensioni di un array dichiarato ma non ancora allocato possono essere specificate utlizzando l istruzione ALLOCATE che ha appunto la funzione di riservare spazio in memoria per i suoi elementi. La sintassi della succitata istruzione è quella che segue: ALLOCATE(lista_di_array_dimensionati) Esempio: integer, ALLOCATABLE, DIMENSION(:) :: elenco_interi character(10), ALLOCATABLE, DIMENSION(:,:) :: tabella_parole ALLOCATE(elenco_interi(100), tabella_parole(0:9, 10))

L istruzione ALLOCATE rende disponibile al progettista un opzione per monitorare il successo dell operazione di allocazione. Il formato di questa versione estesa dell istruzione prevede l indicazione di una variabile intera che conterrà in esito all esecuzione dell operazione di allocazione un codice numerico di errore oppure il valore 0 se tutto è andato bene. ALLOCATE(lista_di_array_dimensionati, STAT=variabile_di_controllo) Esempio: INTEGER :: errore INTEGER, ALLOCATABLE, DIMENSION(:) :: elenco_interi ALLOCATE(elenco_interi(100), STAT=errore) IF (errore/=0) THEN PRINT*, "Allocazione dell array fallita, codice errore:, errore STOP END IF

Lo spazio di memoria occupato da un array correntemente allocato può essere liberato mediante l istruzione DEALLOCATE che ha la seguente sintassi: DEALLOCATE(lista_di_array [, STAT=variabile_di_controllo]) dove il significato e l uso della clausola STAT=variabile_di_stato sono identici a quelli visti per l istruzione di allocazione. E importante ricordare che una volta che un array sia stato deallocato i dati in esso immagazzinati sono definitivamente non più disponibili. L uso combinato delle istruzioni ALLOCATE e DEALLOCATE consente di lavorare con un array allocabile di dimensioni continuamente variabili. Attenzione: ALLOCATE(vettore(10)) ALLOCATE(vettore(20))!ERRORE Non è possibile riallocare lo stesso array prima di averlo deallocato!

program reverse_array_dinamico_errori implicit none integer, allocatable, dimension(:) :: elenco integer :: i, n, errore print*, "quanti elementi vuoi inserire?" read(*,*) n allocate(elenco(n), STAT=errore) IF (stato/=0) THEN PRINT*, "Allocazione degli array fallita, codice errore:, errore STOP END IF read(*,*) elenco elenco((/(i, i=n,1,-1)/))=elenco write(*,*) elenco deallocate(elenco) end program

TYPE :: coord3 REAL :: x REAL :: y REAL :: z END TYPE coord3 TYPE(coord3), ALLOCATABLE, DIMENSION(:) :: elenco_punti INTEGER :: n WRITE(*,*) Numero di punti da leggere: READ(*,*) n ALLOCATE(elenco_punti(n))

TYPE :: coord3 REAL :: x REAL :: y REAL :: z END TYPE coord3 TYPE :: spezzata TYPE(coord3) :: inizio TYPE(coord3), ALLOCATABLE, DIMENSION(:) :: elenco_punti_intermedi TYPE(coord3) :: fine END TYPE spezzata INTEGER :: n WRITE(*,*) Numero di punti da leggere: READ(*,*) n ALLOCATE(elenco_punti(n))

PROGRAM confronta IMPLICIT NONE INTEGER, PARAMETER :: n=10 INTEGER, DIMENSION(n) :: a, b INTEGER :: i WRITE(*,*) Immetti il primo elenco di, n, interi: READ(*,*) (a(i), i=1, n) WRITE(*,*) Immetti il secondo elenco di, n, interi: READ(*,*) (b(i), i=1, n) IF (a==b) THEN WRITE(*,*) i due elenchi sono uguali! ELSE WRITE(*,*) i due elenchi non sono uguali! END IF END PROGRAM confronta

Modifichiamo il programma come segue: PROGRAM confronta INTEGER, PARAMETER :: n=10 INTEGER, DIMENSION(n) :: a, b INTEGER :: i WRITE(*,*) Immetti il primo elenco di, n, interi: READ(*,*) (a(i), i=1, n) WRITE(*,*) Immetti il secondo elenco di, n, interi: READ(*,*) (b(i), i=1, n) WRITE(*,*) Esito del confronto: WRITE(*,*) (a==b) END PROGRAM confronta La compilazione non darà errori ed in esecuzione potremmo avere il seguente risultato: Immetti il primo elenco di 10 interi:" 1 3 5 6 7 2 3 4 5 8 Immetti il secondo elenco di 10 interi: 2 3 5 6 3 4 4 3 5 8 Esito del confronto: F T T T F F F F T T

a 1 3 5 6 7 2 3 4 5 8 b 2 3 5 6 3 4 4 3 5 8 == == == == == == == == == == a==b F T T T F F F F T T Il confronto fra due array (conformi!) è quindi possibile e genera un array logico avente per contenuti i risultati del confronto, elemento per elemento!

IF (a==b) THEN IF (ALL(a==b)) THEN ALL è una cosiddetta funzione intrinseca di array, appartiene cioè ad una classe di funzioni specificamente pensate per evere come argomento/i degli array. In particolare ALL restituirà lo scalare logico.true. se il suo argomento (un array logico) contiene come elementi tutti.true., lo scalare.false. altrimenti.

a 1 3 5 6 7 2 3 4 5 8 b 1 3 5 6 3 4 4 3 5 8 ALL((a==b))! Restituisce.FALSE. ALL((a(1:4)==b(1:4)))! Restituisce.TRUE. ANY((a==b))! Restituisce.TRUE. ANY((a(5:8)==b(5:8)))! Restituisce.FALSE. Riuscite ad individuare cosa fa la funzione ANY?

Le funzioni intrinseche di array sono usualmente ricondotte, a seconda dell uso e degli scopi, a 7 categorie: 1. Funzioni di riduzione 2. Funzioni di interrogazione 3. Funzioni di costruzione 4. Funzioni di trasformazione 5. Funzioni topologiche 6. Funzioni di manipolazione 7. Funzioni algebriche

Funzioni di interrogazione (esempi) ALLOCATED (ARRAY) Indica se l ARRAY è o non è allocato. Il risultato è.true. se ARRAY è correntemente allocato,.false. altrimenti. Esempio: REAL, ALLOCATABLE, DIMENSION (:,:,:) :: myarr... PRINT*, ALLOCATED(myarr)! stampa il valore.false. ALLOCATE(myarr(10,0:9)) PRINT*, ALLOCATED(myarr)! stampa il valore.true.

Funzioni di costruzione (esempi) MERGE(TSOURCE,FSOURCE,MASK) Seleziona tra due valori, o tra gli elementi corrispondenti di due array, in accordo con la condizione specificata da una maschera. TSOURCE può essere uno scalare o un array di tipo qualsiasi. FSOURCE è uno scalare o un array avente stesso tipo di TSOURCE. MASK è un array logico. Il risultato (che ha lo stesso tipo di TSOURCE) viene determinato prendendo, elemento elemento, il valore corrispondente di TSOURCE (se MASK è.true.) o di FSOURCE (se MASK è.false.). Ad esempio, se la variabile intera r ha valore -3, allora il risultato di MERGE(1.0,0.0,r<0) ha valore 1.0, mentre per r pari a 7 ha the valore 0.0.

Funzioni di costruzione (esempi) Un esempio appena più complesso è il seguente. Se TSOURCE è l array: 1 3 5 2 4 6 FSOURCE è l array: 8 9 0 1 2 3 e MASK è l array:.false..true..true..true..true..false. allora l istruzione: MERGE(TSOURCE,FSOURCE,MASK) produce il risultato: 8 3 5 2 4 3

Funzioni di trasformazione (esempi) RESHAPE(SOURCE,SHAPE[,PAD]) Costruisce un array di forma differente a partire da un array di input. L argomento SOURCE è un array di tipo qualsiasi. Esso fornisce gli elementi per l array risultante. La sua ampiezza deve essere maggiore o uguale a PRODUCT(SHAPE) se PAD è omesso oppure se ha ampiezza nulla. L argomento SHAPE è un array di sette elementi al massimo, rango unitario e dimensione costante. Esso definisce la forma dell array risultante. Non può avere ampiezza nulla ed i suoi elementi non possono avere valori negativi. L argomento opzionale PAD è un array avente stesso tipo di SOURCE. Il suo compito è quello di fornire valori di riserva nel caso in cui l array risultante avesse ampiezza maggiore di SOURCE.

Funzioni di trasformazione (esempi) Un semplice esempio di utilizzo della funzione RESHAPE è fornito dalla seguente istruzione: RESHAPE((/3,4,5,6,7,8/),(/2,3/)) la quale fornisce come risultato la matrice: 3 5 7 4 6 8 mentre l istruzione: RESHAPE((/3,4,5,6,7,8/),(/2,4/),(/1,1/)) fornisce il seguente risultato: 3 5 7 1 4 6 8 1

Funzioni topologiche (esempi) MAXLOC(ARRAY [,MASK]) MINLOC (ARRAY [,MASK]) Restituiscono la posizione dell elemento di valore massimo/minimo di un array, di una sezione di array o lungo una specificata dimensione dell array.

Funzioni topologiche (esempi) L argomento ARRAY è un array di tipo intero o reale. L argomento opzionale MASK è un array logico compatibile con ARRAY. Il risultato è un array di tipo intero. Valgono le seguenti regole: a.l array risultante ha rango unitario e ampiezza pari al rango di ARRAY. b.se MASK è assente, gli elementi dell array risultante rappresentano gli indici della locazione dell elemento di ARRAY avente valore massimo/ minimo. Se MASK è presente, gli elementi dell array risultante rappresentano gli indici della locazione dell elemento di ARRAY avente valore massimo/ minimo fra quelli compatibili con la condizione specificata da MASK.

Funzioni topologiche (esempi) Esempi: Il valore di MAXLOC((/3,7,4,7/)) è 2, essendo questo l indice della posizione della prima occorrenza del valore massimo (7) nell array monodimensionale specificato come argomento. Sia mat l array: 4 0-3 2 3 1-2 6-1 -4 5-5 MAXLOC(mat,MASK=mat<5) fornisce il valore (/1,1/) poiché questi sono gli indici che puntano all elemento di valore massimo (4) fra tutti quelli minori di 5.

Esempi: Funzioni di manipolazione (esempi) TRANSPOSE(MATRIX) Traspone un array di rango due. L argomento MATRIX può essere un array bidimensionale di tipo qualsiasi. Il risultato della funzione è un array avente stesso tipo e stessi parametri di kind dell argomento MATRIX e forma (/n,m/) essendo (/m,n/) la forma dell argomento. L elemento (i,j)_mo dell array risultante coincide con il valore di MATRIX(j,i). A titolo di esempio, definita la seguente matrice mat: 1 2 3 4 5 6 7 8 9 TRANSPOSE(mat) avrà valore: 1 4 7 2 5 8 3 6 9

Esempi: Funzioni algebriche (esempi) DOT_PRODUCT(VECTOR_A,VECTOR_B) Esegue il prodotto scalare di due vettori numerici (interi, reali o complessi) aventi stessa dimensione. Il risultato è uno scalare il cui tipo dipende dai vettori operandi VECTOR_A e VECTOR_B. In particolare: Se l argomento VECTOR_A è di tipo INTEGER o REAL allora il risultato avrà valore pari a SUM(VECTOR_A*VECTOR_B). Se l argomento VECTOR_A è di tipo COMPLEX, allora il risultato avrà valore pari a SUM(CONJG(VECTOR_A)*VECTOR_B). Se gli array operandi hanno dimensione nulla, il risultato vale zero se essi sono di tipo numerico oppure.false. se gli operandi sono di tipo logico.

Funzioni algebriche (esempi) Ad esempio, l istruzione: DOT_PRODUCT((/1,2,3/),(/3,4,5/)) restituisce il valore 26 (infatti: (1 3)+(2 4)+(3 5)=26) Invece, l istruzione: DOT_PRODUCT((/(1.0,2.0),(2.0,3.0)/),(/(1.0,1.0),(1.0,4.0)/)) fornisce l array (/17.0,4.0/). (infatti: (1-2j)(1+j)+(2-3j)(1+4j)=(1+2-j)+(2+12+5j)=17+4j)