Introdução à Programação na linguagem F
Jaime Ramos, Amílcar Sernadas e Paulo Mateus
DMIST, Setembro de 2005
Capítulo 2 Complementos de programação em F
Objectivos
Vectores e matrizes. Programação imperativa sobre vectores e matrizes. Programação recursiva sobre
vectores.
Vectores
Para declarar uma variável vectorial, é necessário indicar qual o tamanho do vector em causa e qual o tipo
de objectos desse vector. Na instrução seguinte declara-se uma variável v para guardar vectores de
números inteiros com tamanho 5:
integer, dimension(5) :: v
Alternativamente, podia ter sido utilizada a declaração seguinte, em que se delimitam o limite inferior e
superior do vector
integer, dimension(1:5) :: v
Para aceder aos elementos do vector, utiliza-se a expressão v(i), que se refere ao elemento na posição i
do vector guardado em v.
Pretende-se definir uma função que recebe como argumento um vector de tamanho 5 e retorna a soma dos
seus elementos. Como primeira solução, considere-se a seguinte função:
function somaVec1(v) result(s)
integer, dimension(5), intent(in) :: v
integer :: s, i
s=0
do i=1,5
s=s+v(i)
end do
end function somaVec1
Tal como pretendido, esta função recebe como argumento um vector de tamanho 5, soma as suas
componentes uma a uma recorrendo a um ciclo do e devolve essa soma. O programa seguinte ilustra a
utilização desta função: lê do terminal cinco números inteiros, guarda-os num vector, e calcula a soma
dos seus elementos recorrendo à função anterior.
program exemplo11
integer, dimension(5) :: v
integer :: i
do i=1,5
print *,"Introduza um numero:"
read *,v(i)
end do
print *,"O resultado e:",somaVec1(v)
contains
function somaVec1(v) result(s)
integer, dimension(5), intent(in) :: v
integer :: s, i
s=0
2
do i=1,5
s=s+v(i)
end do
end function somaVec1
end program exemplo11
Considere-se a seguinte execução:
Introduza um numero:
1
Introduza um numero:
2
Introduza um numero:
3
Introduza um numero:
4
Introduza um numero:
5
O resultado e: 15
A pergunta seguinte surge naturalmente: e se pretendermos somar os elementos de vectores com outros
tamanhos? Podem surgir duas situações: ou o vector tem tamanho superior a 5 e nesse caso a função
apenas soma os cinco primeiros elementos, ou o vector tem tamanho inferior a 5 e nesse caso ocorre um
erro de compilação.
No entanto a função anterior pode ser generalizada para vectores de qualquer tamanho. O problema da
declaração do parâmetro resolve-se recorrendo à declaração:
integer, dimension(:), intent(in) :: v
Neste caso está-se a declarar um parâmetro que consiste um vector de tamanho arbitrário. O limite do
ciclo resolve-se recorrendo à função size. A função seguinte soma os elementos de um vector de
números inteiros de dimensão arbitrária:
function somaVec(v) result(s)
integer, dimension(:), intent(in) :: v
integer :: s, I
s=0
do i=1,size(v)
s=s+v(i)
end do
end function somaVec
O programa seguinte lê seis números inteiros do terminal, guarda-os num vector e, recorrendo à função
anterior, soma-os e apresenta o resultado:
program exemplo12
integer, dimension(6) :: v
integer :: i
do i=1,6
print *,"Introduza um numero:"
read *,v(i)
end do
print *,"O resultado e:",somaVec(v)
contains
function somaVec(v) result(s)
3
integer, dimension(:), intent(in) :: v
integer :: s, i
s=0
do i=1,size(v)
s=s+v(i)
end do
end function somaVec
end program exemplo12
Considere-se a seguinte execução:
Introduza um numero:
1
Introduza um numero:
2
Introduza um numero:
3
Introduza um numero:
4
Introduza um numero:
5
Introduza um numero:
6
O resultado e: 21
No próximo exemplo, define-se uma função para contar o número de números primos que ocorrem num
vector de números inteiros, recorrendo à função prime definida no capítulo anterior. A função contaP
recebe como argumento um vector de números inteiros e devolve o número de números primos que
ocorrem nesse vector. O programa seguinte começa por construir um vector com dez números inteiros
gerados aleatoriamente (entre 1 e 100) recorrendo à subrotina random, que gera números aleatórios entre
0 e 1. Em seguida chama a função contaP para contar quantos desses números gerados foram números
primos.
program contaprimos
integer, dimension(10) :: v
integer :: i
real :: x
do i=1,10
call random_number(x)
v(i)=int(x*100)+1
end do
print *,"Numero de primos:",contaP(v)
contains
function prime(n) result(b)
integer, intent(in) :: n
logical :: b
integer :: i, d
if (n<=1) then
b= .false.
else
d=0
do i=2,n-1
if (n-(n/i)*i == 0) then
d=d+1
end if
end do
4
if (d==0) then
b=.true.
else
b=.false.
end if
end if
end function prime
function contaP(v) result(s)
integer, dimension(:), intent(in) :: v
integer :: s, i
s=0
do i=1,size(v)
if (prime(v(i))) then
s=s+1
end if
end do
end function contaP
end program contaprimos
Considerem-se os seguintes exemplos de execução:
Numero de primos: 1
Numero de primos: 4
Considere-se agora o problema de calcular o produto interno de dois vectores. A função seguinte calcula
o produto interno de dois vectores, desde que eles sejam do mesmo tamanho. No caso de vectores com
tamanhos diferentes, o resultado é uma mensagem de erro no ecrã. O valor devolvido neste caso é
arbitrário.
function prodInterno(v1,v2) result(x)
real, dimension(:), intent(in) :: v1,v2
real :: x
integer :: i
if (size(v1)/=size(v2)) then
print *,"Erro! Os vectores nao sao do mesmo tamanho!"
else
x=0
do i=1,size(v1)
x=x+(v1(i)*v2(i))
end do
end if
end function prodInterno
Deixa-se como exercício testar esta função.
Considere-se o problema de calcular o produto de um vector por um escalar. A primeira solução consiste
numa função que recebe como argumentos o vector v e o escalar x e devolve o vector u resultante do
produto do vector pelo escalar, que deverá ser do mesmo tamanho do vector argumento. Como é que se
declara esse vector? Através da declaração:
integer, dimension(size(v)) :: u
A este tipo de declaração, em que o tamanho de um vector é fixado a partir do tamanho de outros
argumentos, dá-se o nome de vector automático.
Uma solução para a função prodEscalar é a seguinte:
function prodEscalar(v,x) result(u)
integer, dimension(:), intent(in) :: v
5
integer, intent(in) :: x
integer, dimension(size(v)) :: u
integer :: i
do i=1,size(v)
u(i)=v(i)*x
end do
end function prodEscalar
Apresenta-se em seguida um programa para testar esta função. Este programa atribui à variável v o vector
(1,2,3,4,5); repare-se na atribuição simultânea de um vector a uma variável.
program prodEscalar1
integer, dimension(5) :: v
v(1:5)=(/ 1,2,3,4,5 /)
print *,prodEscalar(v,2)
contains
function prodEscalar(v,x) result(u)
integer, dimension(:), intent(in) :: v
integer, intent(in) :: x
integer, dimension(size(v)) :: u
integer :: i
do i=1,size(v)
u(i)=v(i)*x
end do
end function prodEscalar
end program prodEscalar1
O resultado de execução deste programa é:
2 4 6 8 10
Alternativamente, podíamos ter optado por definir uma subrotina. Deixa-se como exercício definir uma
subrotina com três parâmetros, dois de entrada, o vector e o número, e um de saída, o vector resultado.
Alternativamente, pode definir-se uma subrotina que altera directamente o vector, evitando assim a
utilização de dois vectores. Para tal, declara-se o vector como parâmetro de entrada e saída (inout).
subroutine prodEscalar(v,x)
integer, dimension(:), intent(inout) :: v
integer, intent(in) :: x
integer :: i
do i=1,size(v)
v(i)=v(i)*x
end do
end subroutine prodEscalar
O programa anterior pode ser ligeiramente alterado para testar esta subrotina:
program prodEscalar2
integer, dimension(5) :: v
v(1:5)=(/ 1,2,3,4,5 /)
call prodEscalar(v,2)
print *,v
6
contains
subroutine prodEscalar(v,x)
integer, dimension(:), intent(inout) :: v
integer, intent(in) :: x
integer :: i
do i=1,size(v)
v(i)=v(i)*x
end do
end subroutine prodEscalar
end program prodEscalar2
O resultado de execução é o mesmo e omite-se.
Finalmente, apresenta-se uma subrotina para ordenar vectores de números inteiros (in situ), baseada no
método da selecção. Este método consiste em procurar o elemento mínimo e colocá-lo na primeira
posição o vector, em seguida procurar o menor elemento do vector de entre os restantes e colocá-lo na
segunda posição, e assim sucessivamente.
program selsort
integer, dimension(5) :: v
integer :: i
do i=1,5
print *,"Introduza um numero:"
read *,v(i)
end do
call selectSort(v)
print *,v
contains
subroutine swap(v,m,k)
integer, dimension(:), intent(inout) :: v
integer, intent(in) :: m,k
integer :: x
x=v(m)
v(m)=v(k)
v(k)=x
end subroutine swap
subroutine selectSort(v)
integer, dimension(:), intent(inout) :: v
integer :: m, k
if (size(v)>1) then
do m=1,size(v)-1
do k=m+1,size(v)
if(v(m)>v(k)) then
call swap(v,m,k)
end if
end do
end do
end if
end subroutine selectSort
end program selsort
7
Este programa, para além da subrotina selectSort, utiliza ainda a subrotina swap que permite trocar
os elementos nas posições m e k do vector v.
Ao executar este programa, obtém-se o seguinte resultado:
Introduza um numero:
9
Introduza um numero:
4
Introduza um numero:
7
Introduza um numero:
3
Introduza um numero:
10
Vector ordenado: 3 4 7 9 10
Matrizes
A declaração de matrizes é semelhante à dos vectores, mas em vez de apenas uma dimensão, há que
considerar duas (ou mais) dimensões. A instrução seguinte permite declarar uma variável m para guardar
matrizes 4x3:
integer, dimension (4,3) :: m
ou, alternativamente, como para vectores:
integer, dimension (1:4,1:3) :: m
A função pré-definida size continua a poder ser aplicada a matrizes. Neste caso, há que utilizar um
segundo argumento indicando a dimensão de que se pretende calcular o tamanho, isto é, size(m,1)
permite obter o tamanho da dimensão 1, ou seja, o número de linhas (no caso do exemplo, 4),
size(m,2) permite obter o tamanho da dimensão 2, ou seja, o número de colunas (no caso do exemplo,
3). Esta função pode ser aplicada a estruturas de qualquer dimensão.
Como primeiro exemplo, apresenta-se uma função para somar todos os elementos de uma matriz.
function somaEl(m) result(x)
real, dimension(:,:), intent(in) :: m
real :: x
integer :: i, j
x=0
do i=1,size(m,1)
do j=1,size(m,2)
x=x+m(i,j)
end do
end do
end function somaEl
Esta função recorre a dois ciclos encaixados, o primeiro para percorrer as linhas da matriz e o segundo
para percorrer as colunas. Para cada valor de i e j, soma-se o valor da entrada correspondente da matriz
a x. Esta função foi definida num módulo mmatrices, que inclui outras operações sobre matrizes,
apresentadas em seguida. O programa seguinte utiliza esta função para somar os elementos de uma
matriz.
program testsomaEl
real, dimension(3,2) :: m
8
m(1,1)=1
m(1,2)=3
m(2,1)=2
m(2,2)=1
m(3,1)=1.5
m(3,2)=2.5
print *,somaEl(m)
contains
function somaEl(m) result(x)
real, dimension(:,:), intent(in) :: m
real :: x
integer :: i, j
x=0
do i=1,size(m,1)
do j=1,size(m,2)
x=x+m(i,j)
end do
end do
end function somaEl
end program testsomaEl
Com efeito,
11.0000000
Tal como no caso dos vectores, podemos definir uma subrotina prodEscalar para multiplicar uma
matriz por um escalar. A chamada desta subrotina altera a matriz, ficando o argumento com o resultado
da multiplicação da matriz pelo escalar.
subroutine prodEscalar(m,x)
real, dimension(:,:), intent(inout) :: m
real, intent (in) :: x
integer :: i,j
do i=1,size(m,1)
do j=1,size(m,2)
m(i,j)=m(i,j)*x
end do
end do
end subroutine prodEscalar
Deixa-se como exercício resolver o problema anterior recorrendo a uma função e testar quer a subrotina
quer a função.
Considere-se agora o problema de somar duas matrizes. Pretendemos definir uma função que receba
como argumentos duas matrizes compatíveis (com o mesmo número de linhas e de colunas) e devolva
como resultado a matriz resultante da soma. Tal como no caso vectorial, há que declarar a matriz
resultado com as mesmas dimensões das matrizes argumento:
function somaM(m1,m2) result(a)
real, dimension(:,:), intent(in) :: m1,m2
real, dimension(size(m1,1),size(m1,2)) :: a
Este tipo de declaração (vectores e matrizes automáticas) já tinha sido utilizado anteriormente, para o
caso dos vectores. Note-se, no entanto, que este tipo de declaração apenas pode ser aplicada ao tamanho.
O número de dimensões está fixo, ou seja, no caso da matriz a anterior, esta tem sempre duas dimensões
(linhas e colunas). A função somaM que soma duas matrizes é a seguinte:
9
function somaM(m1,m2) result(a)
real, dimension(:,:), intent(in) :: m1,m2
real, dimension(size(m1,1),size(m1,2)) :: a
integer :: i,j
if ((size(m1,1)==size(m2,1)).and.(size(m1,2)==size(m2,2))) then
do i=1,size(m1,1)
do j=1,size(m1,2)
a(i,j)=m1(i,j)+m2(i,j)
end do
end do
else
print *,"Erro! As matrizes não são da mesma forma"
end if
end function somaM
O programa seguinte testa esta função:
program testsomaM
real, dimension(3,2) :: m1,m2,m
m1(1,1:2)=(/ 3,2 /)
m1(2,1:2)=(/ 2,1 /)
m1(3,1:2)=(/ 1.5,4.5 /)
m2(1,1:2)=(/ 4.5,3.0 /)
m2(2,1:2)=(/ 1.2,1.5 /)
m2(3,1:2)=(/ 2,3 /)
m=somaM(m1,m2)
print *,m(1,1),m(1,2)
print *,m(2,1),m(2,2)
print *,m(3,1),m(3,2)
contains
function somaM(m1,m2) result(a)
real, dimension(:,:), intent(in) :: m1,m2
real, dimension(size(m1,1),size(m1,2)) :: a
integer :: i,j
if ((size(m1,1)==size(m2,1)).and.(size(m1,2)==size(m2,2))) then
do i=1,size(m1,1)
do j=1,size(m1,2)
a(i,j)=m1(i,j)+m2(i,j)
end do
end do
else
print *,"Erro! As matrizes não são da mesma forma"
end if
end function somaM
end program testsomaM
Com efeito,
7.5000000
3.2000000
3.5000000
5.0000000
2.5000000
7.5000000
10
Alternativamente, podemos optar por definir uma subrotina que some as duas matrizes, alterando a
primeira, que fica com o resultado da soma.
subroutine somaM(m1,m2)
real, dimension(:,:), intent(inout) :: m1
real, dimension(:,:), intent(in) :: m2
integer :: i,j
if ((size(m1,1)==size(m2,1)).and.(size(m1,2)==size(m2,2))) then
do i=1,size(m1,1)
do j=1,size(m1,2)
m1(i,j)=m1(i,j)+m2(i,j)
end do
end do
else
print *,"Erro! As matrizes não são da mesma forma"
end if
end subroutine somaM
Neste caso, o resultado da soma de m1 e m2 é deixado em m2, como se comprova com o programa
seguinte:
program testsomaM1
real, dimension(3,2) :: m1,m2
m1(1,1:2)=(/ 3,2 /)
m1(2,1:2)=(/ 2,1 /)
m1(3,1:2)=(/ 1.5,4.5 /)
m2(1,1:2)=(/ 4.5,3.0 /)
m2(2,1:2)=(/ 1.2,1.5 /)
m2(3,1:2)=(/ 2,3 /)
call somaM(m1,m2)
print *,m1(1,1),m1(1,2)
print *,m1(2,1),m1(2,2)
print *,m1(3,1),m1(3,2)
contains
subroutine somaM(m1,m2)
real, dimension(:,:), intent(inout) :: m1
real, dimension(:,:), intent(in) :: m2
integer :: i,j
if ((size(m1,1)==size(m2,1)).and.(size(m1,2)==size(m2,2))) then
do i=1,size(m1,1)
do j=1,size(m1,2)
m1(i,j)=m1(i,j)+m2(i,j)
end do
end do
else
print *,"Erro! As matrizes não são da mesma forma"
end if
end subroutine somaM
end program testsomaM1
7.5000000
3.2000000
3.5000000
5.0000000
2.5000000
7.5000000
11
Considere-se agora o problema de pesquisar um elemento numa matriz. A primeira solução capitaliza no
facto de pesquisar numa linha ser equivalente a pesquisar num vector. Assim, a solução consiste em
utilizar a uma função de pesquisa em vector e aplicá-la a cada uma das linhas.
function pesquisaV(x,v) result(b)
real, intent(in) :: x
real, dimension(:), intent(in) :: v
logical :: b
integer :: j
b=.false.
do j=1,size(v)
if (x==v(j)) then
b=.true.
exit
end if
end do
end function pesquisaV
Esta função percorre os elementos do vector um a um até encontrar o elemento x e, caso encontre, coloca
a variável resultado a .true. e termina a execução do ciclo do (atraves do comando exit). Podemos
agora utilizar esta função para pesquisar numa linha de uma matriz. Podemos referir-nos a uma
determinada linha i de uma matriz m através da expressão:
m(i,1:size(m,2))
assim como nos podemos referir a uma determinada coluna j da mesma matriz através da expressão
m(1:size(m,1),j)
Assim, pesquisar se um elemento ocorre numa matriz consiste em pesquisar se ele ocorre em alguma das
linhas e, caso ocorra, terminar a pesquisa com sucesso. Apresenta-se em seguida uma função para
pesquisar um elemento numa matriz, utilizando o método descrito:
function pesquisa(x,m) result(b)
real, dimension(:,:), intent(in) :: m
real, intent(in) :: x
logical :: b
integer :: i
b=.false.
do i=1,size(m,1)
if (pesquisaV(x,m(i,1:size(m,2)))) then
b=.true.
exit
end if
end do
end function pesquisa
Alternativamente, podíamos ter optado por definir a função de pesquisa anterior sem recorrer à função
auxiliar sobre vectores. Esta solução tem a vantagem de não duplicar informação, que resulta de calcular
cada uma das linhas para em seguida lhes aplicar a função pesquisaV. Neste caso, há que recorrer a
dois ciclos. A pesquisa termina quando se percorrer a matriz toda ou quando se encontrar o elemento.
function pesquisa(x,m) result(b)
real, dimension(:,:), intent(in) :: m
real, intent(in) :: x
logical :: b
integer :: i, j
b=.false.
12
do i=1,size(m,1)
do j=1,size(m,2)
if (x==m(i,j)) then
b=.true.
exit
end if
end do
if (b) then
exit
end if
end do
end function pesquisa
Por fim, considere-se a função para multiplicar duas matrizes, desde que estas sejam compatíveis. Tal
como no exemplo anterior, começamos por apresentar uma solução que recorre a uma função auxiliar
para calcular o produto interno de uma linha por uma coluna, ou seja, uma função que recebe dois
vectores do mesmo tamanho e calcula o respectivo produto interno.
function prodLC(l,c) result(x)
real, dimension(:), intent(in) :: l,c
real :: x
integer :: k
x=0
do k=1,size(l)
x=x+l(k)*c(k)
end do
end function prodLC
Recorrendo a esta função, podemos definir o produto de duas matrizes, desde que estas sejam
compatíveis, calculando para cada (i,j) o produto interno da linha i da primeira matriz pela coluna j
da segunda matriz.
function prodM(m1,m2) result(a)
real, dimension(:,:), intent(in) :: m1,m2
real, dimension(size(m1,1),size(m2,2)) :: a
integer :: i,j
if (size(m1,2)==size(m2,1)) then
do i=1,size(m1,1)
do j=1,size(m2,2)
a(i,j)=prodLC(m1(i,1:size(m1,2)),m2(1:size(m2,1),j))
end do
end do
else
print *,"Erro! As matrizes nao sao compativeis"
end if
end function prodM
Alternativamente, podemos definir a função directamente, como se ilustra em seguida:
function prodM(m1,m2) result(a)
real, dimension(:,:), intent(in) :: m1,m2
real, dimension(size(m1,1),size(m2,2)) :: a
real :: x
integer :: i,j,k
if (size(m1,2)==size(m2,1)) then
do i=1,size(m1,1)
do j=1,size(m2,2)
x=0
13
do k=1,size(m1,2)
x=x+m1(i,k)*m2(k,j)
end do
a(i,j)=x
end do
end do
else
print *,"Erro! As matrizes nao sao compativeis"
end if
end function prodM
Deixa-se como exercício testar as funções anteriores.
Programação recursiva
Apresentam-se em seguida algumas das funções sobre vectores apresentadas anteriormente, mas
desenvolvidas num estilo recursivo. Como já se viu, uma função ou subrotina recursiva deve ser
declarada como tal, ou seja, com a declaração recursive.
Como primeiro exemplo, considere-se o problema de somar os elementos de um vector. A função
somaVecR recebe como argumento um vector e devolve a soma dos seus elementos. Utiliza a função
recursiva auxiliar somaVecAux, que tem dois argumentos, um vector e uma posição, e calcula a soma
dos elementos do vector a partir da posição dada. Note-se que a soma dos elementos de um vector pode
ser definida recursivamente, observando que a soma dos elementos a partir de uma dada posição é o
resultado de somar o elemento que está nessa posição com a soma dos elementos nas posições seguintes,
isto é:
somaVecAux(v,i)=v(i)+somaVecAux(v,i+1)
Claro que a expressão anterior apenas se verifica se i for menor ou igual do que o comprimento do
vector. Caso exceda este valor, a soma dos elementos do vector deverá ser 0.
Apresenta-se em seguida a definição destas duas funções:
function somaVec(v) result(x)
integer, dimension(:), intent(in) :: v
integer :: x
x=somaVecAux(v,1)
end function somaVec
recursive function somaVecAux(v,i) result(x)
integer, dimension(:), intent(in) :: v
integer, intent(in) :: i
integer :: x
if (i>size(v)) then
x=0
else
x=v(i)+somaVecAux(v,i+1)
end if
end function somaVecAux
Deixa-se como exercício testar esta função.
Considera-se em seguida o problema de calcular o produto interno de dois vectores. Novamente,
considera-se uma função prodInterno, que recorre a uma função recursiva auxiliar prodIntAux
para calcular o produto interno de dois vectores a partir de uma determinada posição. Observa-se
facilmente que o problema de calcular o produto interno a partir de uma determinada posição pode ser
14
definido recursivamente somando o produto da posição que está a ser considerada dois vectores com o
produto interno dos dois vectores a partir da posição seguinte:
prodIntAux(v1,v2,i)=v1(i)*v2(i)+prodIntAux(v1,v2,i+1)
Novamente, a condição anterior só se verifica se i for menor do que o comprimento dos dois vectores. A
função principal deverá começar por testar se os dois vectores são do mesmo tamanho.
function prodInterno(v1,v2) result(x)
integer, dimension(:), intent(in) :: v1,v2
integer :: x
if (size(v1)/=size(v2)) then
print *,"Erro! Os vectores nao sao do mesmo tamanho."
else
x=prodIntAux(v1,v2,1)
end if
end function prodInterno
recursive function prodIntAux(v1,v2,i) result(x)
integer, dimension(:), intent(in) :: v1,v2
integer, intent(in) :: i
integer :: x
if (i>size(v1)) then
x=0
else
x=v1(i)*v2(i)+prodIntAux(v1,v2,i+1)
end if
end function prodIntAux
Em seguida considera-se o problema de pesquisar um número num vector ordenado. Neste caso, recorrese ao algoritmo de pesquisa binária: sabendo que o vector está ordenado (por ordem crescente), para
procurar um elemento x nesse vector basta comparar o elemento com o elemento no meio do vector. Uma
de três situações pode acontecer: x é igual ao elemento do meio, e nesse caso termina-se a pesquisa com
sucesso; x é maior do que o elemento do meio, e nesse caso basta pesquisar do elemento do meio para a
direita; x é menor do que o elemento do meio, e neste caso apenas é necessário pesquisar do elemento do
meio para a esquerda. Esta pesquisa é feita recursivamente. Neste caso, no entanto, há que considerar
duas posições do vector delimitando os extremos do intervalo do vector onde está a ser efectuada a
pesquisa (que podem não coincidir com os extremos do vector). Apresenta-se em seguida a definição da
função recursiva para pesquisar se um determinado elemento ocorre entre duas posições de um vector
ordenado:
recursive function pesquisaAux(x,v,p,u) result(b)
integer, intent(in) :: x,p,u
integer, dimension(:), intent(in) :: v
logical :: b
integer :: m
if (u<p) then
b=.false.
else
m=(p+u)/2
if (x==v(m)) then
b=.true.
elseif (x>v(m)) then
b=pesquisaAux(x,v,m+1,u)
else
b=pesquisaAux(x,v,p,m-1)
end if
end if
15
end function pesquisaAux
Esta função é utilizada pela função de pesquisa binária:
function pesquisa(x,v) result(b)
integer, intent(in) :: x
integer, dimension(:), intent(in) :: v
logical :: b
b=pesquisaAux(x,v,1,size(v))
end function pesquisa
Finalmente, conisdera-se o problema de multiplicar um vector por um escalar. Neste caso, optou-se por
definir uma subrotina recursiva que altera directamente o vector argumento. Para tal, é necessário definir
o parâmetro correspondente ao vector como sendo de entrada e saída (inout). De resto, a subrotina
recursiva é em tudo semelhante à função para somar os elementos de um vector.
recursive subroutine prodEscalarAux(v,x,i)
integer, dimension(:), intent(inout) :: v
integer, intent(in) :: x,i
if (i==size(v)) then
v(i)=v(i)*x
else
v(i)=v(i)*x
call prodEscalarAux(v,x,i+1)
end if
end subroutine prodEscalarAux
A função que calcula o produto escalar utiliza a função auxiliar anterior:
subroutine prodEscalar(v,x)
integer, dimension(:), intent(inout) :: v
integer, intent(in) :: x
call prodEscalarAux(v,x,1)
end subroutine prodEscalar
recursive subroutine prodEscalarAux(v,x,i)
integer, dimension(:), intent(inout) :: v
integer, intent(in) :: x,i
if (i==size(v)) then
v(i)=v(i)*x
else
v(i)=v(i)*x
call prodEscalarAux(v,x,i+1)
end if
end subroutine prodEscalarAux
16
Download

Capítulo 2