module conmod 1
contains


SUBROUTINE sort_up(arr) 1
IMPLICIT NONE
double precision, DIMENSION(:), INTENT(INOUT) :: arr
INTEGER :: i,j,n
double precision :: a
n=size(arr)
do j=2,n
	a=arr(j)
	do i=j-1,1,-1
		if (arr(i) <= a) exit
		arr(i+1)=arr(i)
	end do
	arr(i+1)=a
end do
END SUBROUTINE sort_up


SUBROUTINE sort_down(arr)
IMPLICIT NONE
double precision, DIMENSION(:), INTENT(INOUT) :: arr
INTEGER :: i,j,n
double precision :: a
n=size(arr)
do j=2,n
	a=arr(j)
	do i=j-1,1,-1
		if (arr(i) >= a) exit
		arr(i+1)=arr(i)
	end do
	arr(i+1)=a
end do
END SUBROUTINE sort_down



SUBROUTINE resort(arr,irr) 2
IMPLICIT NONE
double precision, DIMENSION(:), INTENT(INOUT) :: arr
double precision, DIMENSION(:), allocatable :: brr
INTEGER :: k,n,irr(:)
n=size(arr)
allocate(brr(n))
brr=arr
do k=1,n
arr(k)=brr(irr(k))
end do
deallocate(brr)
END SUBROUTINE resort 


SUBROUTINE isort(arr,irr) 2
IMPLICIT NONE
integer, DIMENSION(:), INTENT(INOUT) :: arr
integer, DIMENSION(:), allocatable :: brr
INTEGER :: k,n,irr(:)
n=size(arr)
allocate(brr(n))
brr=arr
do k=1,n
arr(k)=brr(irr(k))
end do
deallocate(brr)
END SUBROUTINE isort 


SUBROUTINE sort_up2(arr,irr) 1
IMPLICIT NONE
double precision, DIMENSION(:), INTENT(INOUT) :: arr
INTEGER :: i,j,k,m,n,irr(:)
double precision :: a
n=size(arr)
do k=1,n
irr(k)=k
end do
do j=2,n
	a=arr(j)
	m=irr(j)
	do i=j-1,1,-1
		if (arr(i) <= a) exit
		arr(i+1)=arr(i)
		irr(i+1)=irr(i)
	end do
	arr(i+1)=a
	irr(i+1)=m
end do
END SUBROUTINE sort_up2


SUBROUTINE sort_down2(arr,irr) 1
IMPLICIT NONE
double precision, DIMENSION(:), INTENT(INOUT) :: arr
INTEGER :: i,j,k,m,n,irr(:)
double precision :: a
n=size(arr)
do k=1,n
irr(k)=k
end do
do j=2,n
	a=arr(j)
	m=irr(j)
	do i=j-1,1,-1
		if (arr(i) >= a) exit
		arr(i+1)=arr(i)
		irr(i+1)=irr(i)
	end do
	arr(i+1)=a
	irr(i+1)=m
end do
END SUBROUTINE sort_down2


double precision function value(c,xx,yy) 16
implicit double precision (a-h,o-z)
dimension c(4,4)
value=&
	(((((c(4,4)*yy+c(3,4))*yy+c(2,4))*yy+c(1,4))*xx &
	+(((c(4,3)*yy+c(3,3))*yy+c(2,3))*yy+c(1,3)))*xx &
	+(((c(4,2)*yy+c(3,2))*yy+c(2,2))*yy+c(1,2)))*xx &
	+(((c(4,1)*yy+c(3,1))*yy+c(2,1))*yy+c(1,1))
return
end function value


double precision function dvdy(c,xx,yy) 4
implicit double precision (a-h,o-z)
dimension c(4,4)
dvdy=&
	(((((c(4,4)*3*yy+c(3,4)*2)*yy+c(2,4)))*xx &
	+(((c(4,3)*3*yy+c(3,3)*2)*yy+c(2,3))))*xx &
	+(((c(4,2)*3*yy+c(3,2)*2)*yy+c(2,2))))*xx &
	+(((c(4,1)*3*yy+c(3,1)*2)*yy+c(2,1)))
return
end function dvdy 


double precision function dvdx(c,xx,yy) 4
implicit double precision (a-h,o-z)
dimension c(4,4)
dvdx=&
	((((c(4,4)*yy+c(3,4))*yy+c(2,4))*yy+c(1,4))*3*xx &
	+(((c(4,3)*yy+c(3,3))*yy+c(2,3))*yy+c(1,3))*2)*xx &
	+(((c(4,2)*yy+c(3,2))*yy+c(2,2))*yy+c(1,2))
return
end function dvdx 


end module conmod


subroutine square_con(q,xco,yco,cl,nc,ierr,idebug)  1,22
use conmod
!implicit double precision (a-h,o-z)
implicit none 
type four
sequence
double precision,dimension(4) :: val,d1,d2,d12
end type four
type(four) q,xco,yco
double precision,dimension(4) :: e,xv,yv
double precision,dimension(4,4) :: c,cxco,cyco 
double precision,allocatable :: sr(:),vr(:),&
	xa(:),ya(:),va(:),xp(:,:),yp(:,:)
integer, allocatable :: ia(:),is(:),mb(:),np(:),ic(:),icl(:),ih(:),icsa(:) 
double precision r(3),xs(300),ys(300),xout(1500),yout(1500)
double precision x,y,v,vv,den,alf,fac,dx,dy,s,vx,vy,dummy,&
	angle,dangle,anglel,dist,arco,pi,bet,xt,yt,dyt,dxt,del
integer ns,nwall,nsl,nsadl,ntodo,iout,icolor,newmt,&
	i,j,k,m,n,mt,nz,nk,nc,newmb,nr,iside,idesperate,icyc,ierr,&
	idebug
double precision :: cl(nc)
data xv /0.,1.,1.,0./
data yv /0.,0.,1.,1./


nz=12*nc
pi=4*atan(1.)

allocate(sr(3*nc),vr(3*nc),ia(3*nc),icl(3*nc))
allocate(xa(nz),ya(nz),va(nz),is(nz),mb(nz),&
	xp(100,nz),yp(100,nz),np(nz),ic(nz),ih(nz),icsa(nz))

call   sort_up(cl)

call bcucof(q%val,q%d1,q%d2,q%d12,1.d0,1.d0,c)
call bcucof(xco%val,xco%d1,xco%d2,xco%d12,1.d0,1.d0,cxco)
call bcucof(yco%val,yco%d1,yco%d2,yco%d12,1.d0,1.d0,cyco)
call grid_box(xv,yv)
call find_boundary_intersect
if (nk.eq.0) then
	call one_color
	goto 2001
end if
ierr=10
ntodo=nk
mt=1
newmt=1
ih=0
icyc=0
do while (ntodo.gt.1)
	icyc=icyc+1
	if (icyc.gt.nk*nk) then
	ierr=1
	goto 2001
	end if
	if (newmt.ne.mt) then
		mt=newmt
	else
		mt=mod(mt,nk)+1
		newmt=mt
	end if
	m=mb(mt)
	write (79,'(i4,i4,f9.5,f9.5)', advance='yes') m,mt,va(m),va(mt)
	if (va(m).eq.va(mt).and.ih(mt).eq.0) then 
		call start_trip
		do while (nwall.lt.2)
			fac=min(2*fac,1.d0)
			call get_dx_dy; if (idebug.eq.1) write (79,*) " first";
			find_acceptable: do 
				anglel=atan2(dy,dx)
				x=x+dx
				y=y+dy
				if (idebug.eq.1) write(79,*)'x,y=',x,y,"before improve"
				call improve_root			
				call eval
				call get_dx_dy
				if (dx.eq.0) dy=ya(mt)-y
				if (dy.eq.0) dx=xa(mt)-x
				angle=atan2(dy,dx)
				dangle=min(abs(angle-anglel),2*pi-abs(angle-anglel))
				if (dangle.lt.pi/2.and.idebug.eq.1) write(79,*) "dangle=",dangle 
				if (dangle.lt.pi/2.) exit
				call jump_back
				if (idesperate.eq.1.and.idebug.eq.1) write(79,*) "desperate" 
				if (idesperate.eq.1) exit
			end do find_acceptable
			
			ns=ns+1
			xs(ns)=x
			ys(ns)=y
			if (idebug.eq.1) write (79,*) 'x,y=',x,y, " before chk" 
			
			call check_boundary	
			if (idebug.eq.1) write (79,*) 'x,y=',x,y, " after chk" 
			if (nwall.eq.2) then
				if (idebug.eq.1) write (79,*) "x,y=",x,y," nwall=2"
				if (abs(x).lt.0.001) then
				 x=0.; call improve_root_y;
				end if
				if (abs(1-x).lt.0.001) then
				 x=1.; call improve_root_y;
				end if
				if (abs(y).lt.0.001) then
				 y=0.; call improve_root_x;
				end if
				if (abs(1-y).lt.0.001) then
				 y=1.; call improve_root_x;
				end if
				dist=sqrt((x-xa(mt))**2+(y-ya(mt))**2)
				if (dist.lt.0.001) then
					call successful_trip
				else
					!write (*,*) ' wall, but not hit'
					write (79,'(a,4es10.3)') ' not hit',x,xa(mt),y,ya(mt)
				end if
			end if
			if (ns.ge.300) then
				write (79,'(a)') ' no wall'
				!write (*,*) m,mt,x,y
				stop
			end if
		end do
	else
		write (79,'(a)') ' do not try' 
	end if
end do
2001 continue
if (ierr.ne.0) then
if (ntodo.eq.2) then
	i=1
	do while (ih(i).eq.1.and.i.le.nk)
 		i=i+1
 	end do
	m=i
	do while (ih(i).eq.1.and.i.le.nk)
		 i=i+1
	 end do
	mt=i+1
	write (*,*) 'cheating with straight line',m,mt
	ns=2
	xs(1)=xa(m)
	ys(1)=ya(m)
	xs(2)=xa(mt)
	ys(2)=ya(mt)
	call successful_trip
else
	call one_color
end if
end if
deallocate(sr,vr,ia,icl)
deallocate(xa,ya,va,is,mb,&
	xp,yp,np,ic,ih,icsa)
return

contains

subroutine one_color 2,1
implicit none 
double precision qaver
xout(1)=0.
yout(1)=0.
xout(2)=1.
yout(2)=0.
xout(3)=1.
yout(3)=1.
xout(4)=0.
yout(4)=1.
iout=4
icolor=1
qaver=.25*(q%val(1)+q%val(2)+q%val(3)+q%val(4))

do i=1,nc
	if (cl(i).lt.qaver) icolor=i+1
end do
call ps_area(xout,yout,iout,icolor+2)
end subroutine one_color


subroutine jump_back 1,3
implicit none 
!write (*,'(a,i4,a,f7.3,a,f7.3)') 'saddle? ns=',ns,' x=',x,' y=',y
!!!if (nsl.eq.ns) nsadl=nsadl+1
nsadl=nsadl+1
if (idebug.eq.1) write (79,*) ' nsadl=', nsadl
x=xs(ns)
y=ys(ns)
fac=fac/4.
call eval
call get_dx_dy
if (nsadl.gt.10) then
	fac=0.1
	call get_dx_dy
	dummy=dx
	dx=dy
	dy=-dummy
	dx=(xa(mt)-x)*fac*abs(alf)
	dy=(ya(mt)-y)*fac*abs(alf)
	write (79,'(a,i4,a,2es11.3)',advance='yes') ' nsadl=',nsadl,' turn ',dx,dy
	nsadl=0	
	if (ns.eq.1) idesperate=1
end if 
nsl=ns
end subroutine jump_back


subroutine start_trip 1,1
implicit none 
x=xa(m)
y=ya(m)
v=va(m)
ns=1
xs(ns)=x
ys(ns)=y
alf=.05
call eval
if (idebug.eq.1) write (79,*) x,y,vv
if (idebug.eq.1) write (79,*) 'alf before=',alf
if (is(m).eq.4.and.vy.lt.0.) alf=-alf
if (is(m).eq.2.and.vy.gt.0.) alf=-alf
if (is(m).eq.1.and.vx.gt.0.) alf=-alf
if (is(m).eq.3.and.vx.lt.0.) alf=-alf
if (idebug.eq.1) write (79,*) 'alf  after=',alf
nwall=0
fac=1.
nsl=-99
nsadl=0
idesperate=0
end subroutine start_trip


subroutine eval 3,3
implicit none
vv=value(c,x,y)
vx=dvdx(c,x,y)
vy=dvdy(c,x,y)
end subroutine eval


subroutine get_dx_dy 4
implicit none
den=vx**2+vy**2
if (den.le.0.) then
	write (*,*) ' vx=0 and vy=0, stop'
	stop
end if
s=sqrt(den)
dx=fac*alf*vy/s
dy=-fac*alf*vx/s
if (idebug.eq.1) write (79,'(a,4es11.4)') 'dx,dy,x,y=',dx,dy,x,y
end subroutine get_dx_dy


subroutine successful_trip 2,4
implicit none 
ih(mt)=1
ih(m)=1
x=xa(mt)
y=ya(mt)
xs(ns)=x
ys(ns)=y
ntodo=ntodo-2
iout=0
do i=1,ns
	iout=iout+1
	xout(iout)=xs(i)
	yout(iout)=ys(i)
end do
icolor=0
if (v.lt.0.) icolor=1
call ps_line(xout,yout,iout,icolor)
do i=1,np(mt)
	iout=iout+1
	xout(iout)=xp(i,mt)
	yout(iout)=yp(i,mt)
end do
do i=1,iout
	!	write (*,'(a,f9.5,a,f9.5)') ' x=',xout(i),'   y=',yout(i)
end do
icsa(m)=icshft()
icolor=ic(m)+icsa(m)
write (79,*) ' success, ntodo=',ntodo,'  icolor=',icolor
write (79,'(20i2)') (ih(i),i=1,nk)
call ps_area(xout,yout,iout,icolor+2)
newmt=mod(mt,nk)+1
do while (ih(newmt).eq.1.and.ntodo.ne.0)
	newmt=mod(newmt,nk)+1
end do
newmb=mod(nk+m-2,nk)+1
do while (ih(newmb).eq.1.and.ntodo.ne.0)
	newmb=mod(nk+newmb-2,nk)+1
end do
write (79,*) 'newmb=',newmb,' ih=',ih(newmb),'newmt=',newmt,' ih=',ih(newmt)
mb(newmt)=newmb
do i=ns,1,-1 
	np(newmt)=np(newmt)+1
	xp(np(newmt),newmt)=xs(i)
	yp(np(newmt),newmt)=ys(i)
end do
if (newmt.ne.m) then
	do i=1,np(m)
		np(newmt)=np(newmt)+1
		xp(np(newmt),newmt)=xp(i,m)
		yp(np(newmt),newmt)=yp(i,m)
	end do
end if
if (ntodo.eq.0) then
	! write (*,*) ' ntodo=',ntodo
	iout=0
	do i=1,np(newmt)
		!write (*,'(a,f9.5,a,f9.5)') ' xp=',xp(i,newmt),'   yp=',yp(i,newmt)
		iout=iout+1
		xout(iout)=xp(i,newmt)
		yout(iout)=yp(i,newmt)
	end do
	icolor=ic(newmt)+1-icsa(newmt)
	call ps_area(xout,yout,iout,icolor+2)
	ierr=0
end if
write (79,'(a)') ' hit '
end subroutine successful_trip 


function icshft() 1,2
implicit none 
integer icshft
vx=dvdx(c,xout(1),yout(1))
vy=dvdy(c,xout(1),yout(1))
dummy=(xout(2)-xout(1))*vy-(yout(2)-yout(1))*vx
icshft=0
if (dummy.lt.0.) icshft=1 
end function icshft


subroutine find_boundary_intersect 1,11
implicit none 
nk=0
do iside=1,4
	!write (*,'(es10.3)') c
	if (iside.eq.1) call edgey(e,c,0.d0)
	if (iside.eq.2) call edgex(e,c,1.d0)
	if (iside.eq.3) call edgey(e,c,1.d0)
	if (iside.eq.4) call edgex(e,c,0.d0)
	nr=0.
	do i=1,nc
		call real_roots(e,r,cl(i),n)
		! write (*,'(3i4,4f9.5)') iside,nc,n,e !tempor
		do k=1,n
			nr=nr+1
			sr(nr)=r(k)
			vr(nr)=cl(i)
			icl(nr)=i
		end do
	end do
	if (iside.eq.1.or.iside.eq.2) then
		call   sort_up2(sr(1:nr),ia)
		call resort(vr(1:nr),ia)
		call isort(icl(1:nr),ia)
	end if
	if (iside.eq.3.or.iside.eq.4) then
		call sort_down2(sr(1:nr),ia)
		call resort(vr(1:nr),ia)
		call isort(icl(1:nr),ia)
	end if
	do i=1,nr
		nk=nk+1
		va(nk)=vr(i)
		is(nk)=iside
		ic(nk)=icl(i)
		if (iside.eq.1) then
			xa(nk)=sr(i)
			ya(nk)=0.
		end if
		if (iside.eq.2) then
			ya(nk)=sr(i)
			xa(nk)=1.
		end if
		if (iside.eq.3) then
			xa(nk)=sr(i)
			ya(nk)=1.
		end if
		if (iside.eq.4) then
			ya(nk)=sr(i)
			xa(nk)=0.
		end if
	end do
end do


if (mod(nk,2).ne.0) then
	write (*,*) ' nk=',nk,'...not even...stop'
end if

do i=2,nk
	mb(i)=i-1
	np(i)=0
end do
mb(1)=nk
np(1)=0 !tempor but OK?

	
do i=1,nk
	n=is(i)
	if (mb(i).lt.i) then
		do while (n.ne.is(mb(i))) 
			np(i)=np(i)+1
			xp(np(i),i)=xv(n)
			yp(np(i),i)=yv(n)
			n=n-1
			if (n.eq.0) n=4
		end do
	else
		n=n+4
		do while (n.ne.is(mb(i))) 
			np(i)=np(i)+1
			xp(np(i),i)=xv(mod(n-1,4)+1)
			yp(np(i),i)=yv(mod(n-1,4)+1)
			n=n-1
		end do
	end if
end do


do i=1,nk
	write (79,'(i4,3f9.4,4i5)') i,xa(i),ya(i),va(i),is(i),mb(i),np(i),ic(i)
	!do j=1,np(i)
		!write (*,*) xp(j,i),yp(j,i) 
	!end do
end do

end subroutine find_boundary_intersect



subroutine check_boundary 1,5
implicit none 
x=xs(ns-1)
y=ys(ns-1)
xt=xs(ns)
yt=ys(ns)
dx=xt-x
dy=yt-y

if (xt.lt.0.or.xt.gt.1.or.yt.lt.0.or.yt.gt.1.) then
	nwall=nwall+1
	if (xt.gt.1.) then
		dxt=min(1.-x,dx)
		dyt=dy*dxt/dx
		xt=x+dxt
		yt=y+dyt
		dx=dxt
		dy=dyt
		!x=xt; y=yt; call improve_root_y
	end if
	if (xt.lt.0.) then
		dxt=max(-x,dx)
		dyt=dy*dxt/dx
		xt=x+dxt
		yt=y+dyt
		dx=dxt
		dy=dyt
		!x=xt; y=yt; call improve_root_y
	end if
	x=xt
	y=yt
	if (yt.gt.1.) then
		dyt=min(1.-y,dy)
		dxt=dx*dyt/dy
		xt=x+dxt
		yt=y+dyt
		!x=xt; y=yt; call improve_root_x
	end if
	if (yt.lt.0.) then
		dyt=max(-y,dy)
		dxt=dx*dyt/dy
		xt=x+dxt
		yt=y+dyt
		!x=xt; y=yt; call improve_root_x
	end if
end if
x=xt
y=yt
call improve_root
xs(ns)=x
ys(ns)=y
end subroutine check_boundary


subroutine improve_root 2,3
implicit none 
do i=1,5 
	vv=value(c,x,y)
	vx=dvdx(c,x,y)
	vy=dvdy(c,x,y)
	den=vx**2+vy**2
	bet=-(vv-v)/den
	x=x+bet*vx
	y=y+bet*vy
end do
end subroutine improve_root


subroutine improve_root_x !not used 4,2
implicit none 
do i=1,5
	vv=value(c,x,y)
	vx=dvdx(c,x,y)
	x=x-(vv-v)/vx
end do
end subroutine improve_root_x


subroutine improve_root_y !not used 4,2
implicit none 
do i=1,5
	vv=value(c,x,y)
	vy=dvdy(c,x,y)
	y=y-(vv-v)/vy
end do
end subroutine improve_root_y



subroutine ps_area(x,y,n,icolor) 3,4
integer n,icolor
double precision x(n),y(n)
character jnum*4
write(jnum(2:4),'(i3.3)') icolor 
write(jnum(1:1),'(a)') 'C' 
write (97,'(a)') jnum 
write (97,'(f8.5,f8.5,a)') value(cxco,x(1),y(1)),value(cyco,x(1),y(1)),' M'
do i=2,n
	write (97,'(f8.5,f8.5,a)') value(cxco,x(i),y(i)),value(cyco,x(i),y(i)),' L'
end do
write (97,*) ' P'
end subroutine ps_area


subroutine ps_line(x,y,n,icolor) 1,4
integer n,icolor
double precision x(n),y(n)
character jnum*4
write(jnum(2:4),'(i3.3)') icolor 
write(jnum(1:1),'(a)') 'C' 
write (98,'(a)') jnum 
write (98,'(f8.5,f8.5,a)') value(cxco,x(1),y(1)),value(cyco,x(1),y(1)),' M'
do i=2,n
	write (98,'(f8.5,f8.5,a)') value(cxco,x(i),y(i)),value(cyco,x(i),y(i)),' L'
end do
write (98,*) ' S'
end subroutine ps_line


subroutine grid_box(x,y) 1,4
double precision x(4),y(4)
double precision xq,yq,xz,yz
do n=1,4
xq=x(n)
yq=y(n)
xz=x(mod(n,4)+1)-xq
yz=y(mod(n,4)+1)-yq
write (99,'(f8.5,f8.5,a)') value(cxco,xq,yq),value(cyco,xq,yq),' M'
do i=1,10
	write (99,'(f8.5,f8.5,a)') value(cxco,xq+.1*i*xz,yq+.1*i*yz),&
							   value(cyco,xq+.1*i*xz,yq+.1*i*yz),' L'
end do
end do
write (99,*) ' G'
end subroutine grid_box 
end subroutine square_con 


subroutine ps_area_old(x,y,n,icolor)
double precision x(n),y(n)
integer n,icolor
character jnum*4
write(jnum(2:4),'(i3.3)') icolor 
write(jnum(1:1),'(a)') 'C' 
write (97,'(a)') jnum 
write (97,'(f8.5,f8.5,a)') x(1),y(1),' M'
do i=2,n
	write (97,'(f8.5,f8.5,a)') x(i),y(i),' L'
end do
write (97,*) ' P'
end subroutine ps_area_old



subroutine edgey(e,c,y) 2
implicit double precision (a-h,o-z)
dimension  e(4),c(4,4)
do n=1,4
	e(n)=(c(1,n)+y*(c(2,n)+y*(c(3,n)+y*c(4,n))))
end do
return
end subroutine edgey


subroutine edgex(e,c,x) 2
implicit double precision (a-h,o-z)
dimension  e(4),c(4,4)
do n=1,4
	e(n)=(c(n,1)+x*(c(n,2)+x*(c(n,3)+x*c(n,4))))
end do
return
end subroutine edgex



SUBROUTINE BCUCOF(Y,Y1,Y2,Y12,D1,D2,CL) 3
implicit double precision (a-h,o-z)
DIMENSION Y(4),Y1(4),Y2(4),Y12(4),CL(16),X(16),WT(16,16)
DATA WT/1.,0.,-3.,2.,4*0.,-3.,0.,9.,-6.,2.,0.,-6.,&
	4.,8*0.,3.,0.,-9.,6.,-2.,0.,6.,-4.,10*0.,9.,-6.,&
	2*0.,-6.,4.,2*0.,3.,-2.,6*0.,-9.,6.,2*0.,6.,-4.,&
	4*0.,1.,0.,-3.,2.,-2.,0.,6.,-4.,1.,0.,-3.,2.,8*0.,&
	-1.,0.,3.,-2.,1.,0.,-3.,2.,10*0.,-3.,2.,2*0.,3.,&
	-2.,6*0.,3.,-2.,2*0.,-6.,4.,2*0.,3.,-2.,0.,1.,-2.,&
	1.,5*0.,-3.,6.,-3.,0.,2.,-4.,2.,9*0.,3.,-6.,3.,0.,&
	-2.,4.,-2.,10*0.,-3.,3.,2*0.,2.,-2.,2*0.,-1.,1.,&
	6*0.,3.,-3.,2*0.,-2.,2.,5*0.,1.,-2.,1.,0.,-2.,4.,&
	-2.,0.,1.,-2.,1.,9*0.,-1.,2.,-1.,0.,1.,-2.,1.,10*0.,&
	1.,-1.,2*0.,-1.,1.,6*0.,-1.,1.,2*0.,2.,-2.,2*0.,-1.,1./
D1D2=D1*D2
DO  I=1,4
	X(I)=Y(I)
	X(I+4)=Y1(I)*D1
	X(I+8)=Y2(I)*D2
	X(I+12)=Y12(I)*D1D2
END DO
DO  I=1,16
	CL(I)=&
		WT(I,1)*X(1)&
		+WT(I,2)*X(2)&
		+WT(I,3)*X(3)&
		+WT(I,4)*X(4)&
		+WT(I,5)*X(5)&
		+WT(I,6)*X(6)&
		+WT(I,7)*X(7)&
		+WT(I,8)*X(8)&
		+WT(I,9)*X(9)&
		+WT(I,10)*X(10)&
		+WT(I,11)*X(11)&
		+WT(I,12)*X(12)&
		+WT(I,13)*X(13)&
		+WT(I,14)*X(14)&
		+WT(I,15)*X(15)&
		+WT(I,16)*X(16)
end do
RETURN
END subroutine bcucof


subroutine real_roots(e,s,v,nn) 1,3
double precision :: r(6),e(4),ec(4),v,s(3)
call roots(e,r,v,n)
nn=0
do i=1,n
	if (r(2*i).eq.0.and.&
		r(2*i-1).ge.0.and.r(2*i-1).le.1.) then
		nn=nn+1
		s(nn)=r(2*i-1)
	end if
end do
if (nn.gt.1) call remove_double(s,nn)
do ii=1,nn-1
	do i=1,nn-1
		if (s(i).gt.s(i+1)) call exchange(s(i),s(i+1)) 
	end do
end do
return
end subroutine real_roots


subroutine remove_double(s,nn) 1
double precision:: s(3)
integer nn
if (nn.eq.2) then
	if (s(2).eq.s(1)) nn=0
else if (nn.eq.3) then
	if (s(2).eq.s(1)) then
		nn=1
		s(1)=s(3)
	else if (s(3).eq.s(1)) then
		s(1)=s(2)
		nn=1
	else if (s(2).eq.s(3)) then
		nn=1
	end if
end if
end subroutine remove_double


subroutine exchange(a,b) 1
double precision a,b,c
c=a
a=b
b=c
return
end subroutine exchange



subroutine roots(e,r,v,n) 1,3
double precision :: r(6),e(4),ec(4),v
ec=e
r=0.
n=0
ec(1)=ec(1)-v
!write (*,*) 'in roots ec(4)',ec
!if (sum(abs(ec(2:4))).lt.abs(ec(1))) return
if (abs(ec(4)).gt.1.e-8*maxval(abs(ec))) then 
	do n=1,4
		ec(n)=ec(n)/ec(4)
	end do
	call cubik (ec,r)
	n=3
else if (abs(ec(3)).gt.1.e-8*maxval(abs(ec))) then 
	call quadratic(ec,r)
	n=2
else if (abs(ec(2)).gt.1.e-8*maxval(abs(ec))) then 
	call linear(ec,r)
	n=1
else
	n=0
end if
end subroutine roots


subroutine cubik (c,x) 1
implicit double precision (a-h,o-z)
dimension  c(3),x(6)
! solve x**3+c(3)*x**2+c(2)*x+c(1)=0.	
! complex roots are x=x(1)+ix(2), etc.
q=(c(3)**2-3*c(2))/9.
r=(2*c(3)**3-9*c(3)*c(2)+27*c(1))/54.
if (r**2.lt.q**3) then
	!	 three real roots
	del=8*datan(1.d0)/3.
	sq=2*dsqrt(q)
	th3=dacos(r/dsqrt(q**3))/3.
	a3=c(3)/3.
	x(1)=-sq*dcos(th3)-a3
	x(2)=0.
	x(3)=-sq*dcos(th3+del)-a3
	x(4)=0.
	x(5)=-sq*dcos(th3-del)-a3
	x(6)=0.
else
	! one real and two complex conjugates
	a=-dsign(1.d0,r)*(dabs(r)+dsqrt(r**2-q**3))**(1./3.)
	b=0.
	if(a.ne.0.) b=q/a
	x(1)=(a+b)-c(3)/3.
	x(2)=0.
	x(3)=-.5*(a+b)-c(3)/3.
	x(4)=.5*dsqrt(3.d0)*(a-b)
	x(5)=x(3)
	x(6)=-x(4)
end if
return
end


subroutine quadratic (c,x) 1
implicit double precision (a-h,o-z)
dimension  c(3),x(4)
complex(kind(1.d0)) qq,rr
! solve c(3)*x**2+c(2)*x+c(1)=0.	
d=c(2)*c(2)-4*c(3)*c(1)
if (d.ge.0.) then
	q=-0.5*(c(2)+sign(sqrt(d),c(2)))
	x(1)=q/c(3)
	x(2)=0.
	x(3)=c(1)/q
	x(4)=0.
else
	qq=cmplx(-0.5*c(2),-0.5*sign(sqrt(-d),c(2)))
	rr=qq/c(3)
	x(1)=real(rr)
	x(2)=aimag(rr)
	rr=c(1)/qq
	x(3)=real(rr)
	x(4)=aimag(rr)
end if
return
end subroutine quadratic


subroutine linear(c,x) 1
implicit double precision (a-h,o-z)
dimension  c(2),x(2)
x(1)=-c(1)/c(2)
x(2)=0.
return
end subroutine linear