!
module decimale
implicit none
integer,parameter::p=selected_real_kind(12,300)
integer,dimension(:),allocatable::pi,vp,vpm,vpq,rs1,rs2
integer::base=100000
contains !
!
! Calcola π con la formula di David Bailey, Peter Borwein e Simon Plouffe usata
! tradizionalmente ossia senza sfruttare la possibilità di calcolo veloce in caso
! di uso della base esadecimale.
!
subroutine fa_pi()
integer::k,kc,n
n=size(pi,1)
pi(1:)=0
vp(1:)=0
vp(1)=4*base/10
kc=max(64,8*min(n/23,100))
k=0
do
if(modulo(k,kc)+8==kc)write(*,*)k/8,n
call divido(rs1,vp,k+1)
call sommo (rs2,rs1,pi)
call divido(vpm,vp,2)
call divido(rs1,vpm,k+4)
call divido(vpq,vpm,2)
call divido(vp,vpq,k+5)
call sommo (vpm,rs1,vp)
call divido(rs1,vpq,k+6)
call sommo (vp,rs1,vpm)
call cambiosegno(rs1,vp)
call sommo(pi,rs2,rs1)
call divido(vp,vpq,4)
if(valezero(vp))exit
k=k+8
end do
return
end subroutine fa_pi
!
subroutine imposta(ncf)
integer,intent(in)::ncf
integer::n
n=50*(abs(ncf)/50)+75
allocate(pi(n),vp(n),vpm(n),vpq(n),rs1(n),rs2(n))
pi(:)=0
vp=pi
vpm=pi
vpq=pi
rs1=pi
rs2=pi
return
end subroutine imposta
!
subroutine stampa(vc,str,nw)
integer,dimension(:),intent(in)::vc
integer,intent(in),optional::nw
character(*),intent(in),optional::str
integer::j,nu
nu=6
if(present(nw))nu=nw
if(present(str))write(nu,*)str
do j=1,size(vc,1),10
if(j+9>size(vc,1)) exit
write(nu,*) stri(vc(j:j+9))
end do
if(nu==6) read(*,*)
return
contains
function stri(nn)result(s)
integer,intent(in),dimension(:)::nn
character(len=5*size(nn,1))::s
integer::k,kk,m
do k=1,size(nn,1)
m=nn(k)
kk=m/10000
s(5*k-4:5*k-4)=char(48+kk)
m=m-10000*kk
kk=m/1000
s(5*k-3:5*k-3)=char(48+kk)
m=m-1000*kk
kk=m/100
s(5*k-2:5*k-2)=char(48+kk)
m=m-100*kk
kk=m/10
s(5*k-1:5*k-1)=char(48+kk)
m=m-10*kk
s(5*k:5*k)=char(48+m)
end do
return
end function stri
end subroutine stampa
!
function valezero(va)result(z)
integer,dimension(:),intent(in)::va
logical::z
integer::k
do k=1,size(va,1)
z=va(k)==0
if(.not.z)return
end do
return
end function valezero
!
subroutine cambiosegno(wc,va)
integer,dimension(:),intent(in)::va
integer,dimension(:),intent(out)::wc
integer::j,jj,ns
ns=min(size(va,1),size(wc,1))
jj=0
do j=ns,1,-1
if(va(j)==0) then
wc(j)=0
else
wc(j)=base-va(j)
jj=j-1
exit
end if
end do
do j=jj,1,-1
wc(j)=base-va(j)-1
end do
return
end subroutine cambiosegno
!
subroutine sommo(wc,va,vb)
integer,dimension(:),intent(in)::va,vb
integer,dimension(:),intent(out)::wc
integer::j,ns,unm
ns=min(size(va,1),size(vb,1),size(wc,1))
unm=0
do j=ns,1,-1
unm=unm+va(j)+vb(j)
wc(j)=modulo(unm,base)
unm=unm/base
end do
return
end subroutine sommo
!
subroutine divido(wc,vc,nm)
integer,intent(in)::nm
integer,dimension(:),intent(in)::vc
integer,dimension(:),intent(out)::wc
integer:: ns,j,jj
real(kind=p)::unm,nmr
ns=min(size(vc,1),size(wc,1))
jj=0
do j=1,ns
if(vc(j)==0)then
wc(j)=vc(j)
else
jj=j
exit
end if
end do
if(jj==0) return
unm=0.0_p
nmr=nm
do j=jj,ns
unm=base*unm+vc(j)
wc(j)=unm/nm
unm=unm-wc(j)*nmr
end do
return
end subroutine divido
!
end module decimale
!
program fa
use decimale
implicit none
character(*),parameter::t=char(60),x=char(62)//char(60)
integer::ncf,t1,t2
write(*,*)"Calcolo delle cifre decimali di PI"
write(*,*)"(durata del calcolo proporzionale al quadrato delle cifre richieste)"
write(*,*)" "
write(*,*)"Assegna quante cifre (consigliabile almeno un centinaio...)"
read(*,*) ncf
call imposta(ncf)
write(*,*)"Usa sei vettori di ",size(pi,1)," cifre ossia in tutto",24*size(pi,1),&
" ottetti"
write(*,*)
if(ncf>2000) then
open(file="pi-cifre.htm",unit=12,status="replace",action="write")
write(12,"(1a)")t//"html"//x//"head"//x//"title>pi"
write(12,"(1a)")t//"/title"//x//"/head"//x//"body>"
write(*,*)"Scrivera' sul file pi-cifre.htm"
write(*,*)"Attendere..."
call system_clock(t1)
write(*,*)"t1=",t1
call fa_pi()
call system_clock(t2)
write(*,*)"t2=",t2," Diff.",t2-t1
call stampa(pi,t//"h2>π"//t//"/h2"//x//"pre>",12)
write(12,"(1a)")t//"/pre"//x//"/body"//x//"/html>"
close(12)
write(*,*)"Un invio per finire..."
read(*,*)
else
write(*,*)"Attendere...."
call fa_pi()
call stampa(pi,"pi")
end if
stop
end program fa
!