#include "externals.h"
#include "types.h"


*###[ ffcb2p:
	subroutine ffcb2p(cb2i,cb1,cb0,ca0i,cp,xm1,xm2,piDpj,ier)
***#[*comment:***********************************************************
*									*
*	Compute the PV B2, the coefficients of p(mu)p(nu) and g(mu,nu)	*
*	of 1/(ipi^2)\int d^nQ Q(mu)Q(nu)/(Q^2-m_1^2)/((Q+p)^2-m_2^2)	*
*	originally based on aaxbx by Andre Aeppli.			*
*									*
*	Input:	cb1	   complex	vector two point function	*
*		cb0	   complex	scalar two point function	*
*		ca0i(2)	   complex	scalar onepoint function with	*
*						m1,m2			*
*		cp	   complex	p.p in B&D metric		*
*		xm1,2	   complex	m_1^2,m_2^2			*
*		piDpj(3,3) complex	dotproducts between s1,s2,p	*
*		ier	   integer	digits lost so far		*
*									*
*	Output:	cb2i(2)	   complex	B21,B22: coeffs of p*p, g in B2	*
*									*
***#]*comment:***********************************************************
*  #[ declarations:
	implicit none
*
*	arguments
*
	integer ier
	ComplexType cp,xm1,xm2,piDpj(3,3)
	ComplexType cb2i(2),cb1,cb0,ca0i(2)
	RealType rm1,rm2,rp,rpiDpj(3,3),sprec
*
*	local variables
*
	integer i,j
	ComplexType dm1p,dm2p,dm1m2
*
*	common blocks
*
*
#include "ff.h"
*
*  #] declarations:
*  #[ real case:
	if ( Im(xm1).eq.0 .and. Im(xm2).eq.0 ) then
	    rm1 = Re(xm1)
	    rm2 = Re(xm2)
	    rp  = Re(cp)
	    do 20 j=1,3
		do 10 i=1,3
		    rpiDpj(i,j) = Re(piDpj(i,j))
   10		continue
   20	    continue
	    sprec = precx
	    precx = precc
	    call ffxb2p(cb2i,cb1,cb0,ca0i,rp,rm1,rm2,rpiDpj,ier)
	    precx = sprec
	    return
	endif
*  #] real case:
*  #[ work:
*
	dm1p = xm1 - cp
	dm2p = xm2 - cp
	dm1m2= xm1 - xm2
	call ffcb2q(cb2i,cb1,cb0,ca0i,cp,xm1,xm2,dm1p,dm2p,dm1m2,
     +		piDpj,ier)
*
*  #] work:
*###] ffcb2p:
	end
*###[ ffcb2q:
	subroutine ffcb2q(cb2i,cb1,cb0,ca0i,cp,xm1,xm2,dm1p,dm2p,dm1m2,
     +		piDpj,ier)
***#[*comment:***********************************************************
*									*
*	Compute the PV B2, the coefficients of p(mu)p(nu) and g(mu,nu)	*
*	of 1/(ipi^2)\int d^nQ Q(mu)Q(nu)/(Q^2-m_1^2)/((Q+p)^2-m_2^2)	*
*	originally based on aaxbx by Andre Aeppli.			*
*									*
*	Input:	cb1	   complex	vector two point function	*
*		cb0	   complex	scalar two point function	*
*		ca0i(2)	   complex	scalar onepoint function with	*
*						m1,m2			*
*		cp	   complex	p.p in B&D metric		*
*		xm1,2	   complex	m_1^2,m_2^2			*
*		piDpj(3,3) complex	dotproducts between s1,s2,p	*
*		ier	   integer	digits lost so far		*
*									*
*	Output:	cb2i(2)	   complex	B21,B22: coeffs of p*p, g in B2	*
*									*
***#]*comment:***********************************************************
*  #[ declarations:
	implicit none
*
*	arguments
*
	integer ier
	ComplexType cp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj(3,3)
	ComplexType cb2i(2),cb1,cb0,ca0i(2)
*
*	local variables
*
	integer i,j,ier0,ier1,ithres,init
	logical lreal,llogmm
	RealType xmax,xmxsav,absc,xmxp
	RealType rm1,rm2,rp,rm1p,rm2p,rm1m2,rpiDpj(3,3),sprec
	ComplexType cs(14),cc,slam,xlo3,csom,clam,xlogmm,zfflo1,alp,
     +		bet,xnoe,xnoe2,zfflo3
	ComplexType cqi(3),cqiqj(3,3)
	save init
* for Absoft only
*	external csqrt
*	ComplexType csqrt
*
*	common blocks
*
#include "ff.h"
*
*	statement function
*
	absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
*  #] declarations:
*  #[ real cases:
	if ( Im(xm1).eq.0 .and. Im(xm2).eq.0 ) then
	    lreal = .TRUE.
	elseif ( nschem.le.4 ) then
	    lreal = .TRUE.
	    if ( init.eq.0 ) then
		init = 1
		print *,'ffcb2q: nschem <= 4, ignoring complex masses:',
     +			nschem
	    endif
	elseif ( nschem.le.6 ) then
	    if ( init.eq.0 ) then
		init = 1
		print *,'ffcb2q: nschem = 5,6 complex masses near ',
     +			'threshold: ',nschem
	    endif
	    cqi(1) = xm1
	    cqi(2) = xm2
	    cqi(3) = cp
	    cqiqj(1,2) = dm1m2
	    cqiqj(2,1) = -cqiqj(1,2)
	    cqiqj(1,3) = dm1p
	    cqiqj(3,1) = -cqiqj(1,3)
	    cqiqj(2,3) = dm2p
	    cqiqj(3,2) = -cqiqj(2,3)
	    cqiqj(1,1) = 0
	    cqiqj(2,2) = 0
	    cqiqj(3,3) = 0
	    call ffthre(ithres,cqi,cqiqj,3,1,2,3)
	    if ( ithres.eq.0 .or. ithres.eq.1 .and. nschem.eq.5 ) then
		lreal = .TRUE.
	    else
		lreal = .FALSE.
	    endif
	else
	    lreal = .FALSE.
	endif
	if ( lreal ) then
	    rm1 = Re(xm1)
	    rm2 = Re(xm2)
	    rp  = Re(cp)
	    rm1p  = Re(dm1p)
	    rm2p  = Re(dm2p)
	    rm1m2 = Re(dm1m2)
	    do 20 j=1,3
		do 10 i=1,3
		    rpiDpj(i,j) = Re(piDpj(i,j))
   10		continue
   20	    continue
	    sprec = precx
	    precx = precc
	    call ffxb2q(cb2i,cb1,cb0,ca0i,rp,rm1,rm2,rm1m2,rpiDpj,ier)
	    precx = sprec
	    return
	endif
*  #] real cases:
*  #[ normal case:
	ier0 = ier
	ier1 = ier
*
*	with thanks to Andre Aeppli, off whom I stole the original
*
	if ( Re(cp) .ne. 0) then
	    cs(1) = ca0i(2)
	    cs(2) = xm1*cb0
	    cs(3) = 2*piDpj(1,3)*cb1
	    cs(4) = (xm1+xm2)/2
	    cs(5) = -cp/6
	    cb2i(1) = cs(1) - cs(2) + 2*cs(3) - cs(4) - cs(5)
	    cb2i(2) = cs(1) + 2*cs(2) - cs(3) + 2*cs(4) + 2*cs(5)
	    xmax = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),absc(cs(5)))
	    xmxsav = xmax
	    if ( absc(cb2i(1)) .ge. xloss*xmax ) goto 100
*  #] normal case:
*  #[   improve: m1=m2:
*
*	    a relatively simple case: dm1m2 = 0 (bi0.frm)
*
	    if ( dm1m2.eq.0 ) then
		slam = sqrt(cp**2-4*xm1*cp)
		xlo3 = zfflo3((cp-slam)/(2*xm1),ier)
		cs(1) = cp*(-1/Re(3) + slam/(4*xm1))
		cs(2) = cp**2*(-slam/(4*xm1**2) - 3/(4*xm1))
		cs(3) = cp**3/(4*xm1**2)
		cs(4) = cp/xm1*ca0i(1)
		cs(5) = xlo3/cp*(-xm1*slam)
		cs(6) = xlo3*slam
		csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5) + cs(6)
		xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
     +			absc(cs(5)),absc(cs(6)))
		if ( xmxp.lt.xmax ) then
		    cb2i(1) = csom
		    xmax = xmxp
		endif
		if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
	    endif
*  #]   improve: m1=m2: 
*  #[   improve: |cp| < xm1 < xm2:
*
*	    try again (see bi.frm)
*
	    clam =  4*(piDpj(1,3)**2 - xm1*cp)
	    if ( xm1.eq.0 .or. xm2.eq.0 ) then
		xlogmm = 0
	    elseif ( absc(dm1m2).lt.xloss*absc(xm1) ) then
		xlogmm = zfflo1(dm1m2/xm1,ier)
	    else
		xlogmm = log(xm2/xm1)
	    endif
	    if ( abs(Re(cp)).lt.xloss*absc(xm2) .and.
     +			Re(xm1).lt.Re(xm2) ) then
		slam = sqrt(clam)
		alp = (2*xm1*xm2/(2*piDpj(1,2)+slam) + xm1)/(slam-dm1m2)
*		bet = [xm2-xm1-cp-slam]
		bet = 4*xm1*cp/(2*piDpj(1,3)+slam)
		cs(1) = cp/xm2*ca0i(2)
		cs(2) = xlogmm*bet*(-2*xm1**2*xm2 - 2*xm1**3)
     +		/((-dm1m2+slam)*(2*piDpj(1,2)+slam)*(2*piDpj(1,3)+slam))
		cs(3) = xlogmm*(-4*cp*xm1**3)
     +		/((-dm1m2+slam)*(2*piDpj(1,2)+slam)*(2*piDpj(1,3)+slam))
		xnoe = 1/(2*piDpj(2,3)+slam)
		xnoe2 = xnoe**2
		cs(4) = xnoe2*xm1*bet*(cp-4*xm2)
		cs(5) = xnoe2*xm1*2*cp*xm2
		cs(6) = xnoe2*xm1**2*bet
		cs(7) = xnoe2*xm1**2*4*cp
		cs(8) = xnoe2*bet*(cp*xm2+3*xm2**2)
		cs(9) = xnoe2*(-6*cp*xm2**2)
		cs(10)= cp*(7/6.d0 - 2*xm1*slam*xnoe2 +
     +			4*xm2*slam*xnoe2 - 2*slam*xnoe)
		cs(11)= cp**2*( -2*slam*xnoe2 )
		xlo3 = zfflo3(2*cp*xnoe,ier)
		cs(12) = xlo3*dm1m2**2*slam/cp**2
		cs(13) = xlo3*(xm1 - 2*xm2)*slam/cp
		cs(14) = xlo3*slam
		csom = 0
		xmxp = 0
		do 50 i=1,14
		    csom = csom + cs(i)
		    xmxp = max(xmxp,absc(cs(i)))
   50		continue
		if ( xmxp.lt.xmax ) then
		    cb2i(1) = csom
		    xmax = xmxp
		endif
		if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
	    endif
*  #]   improve: |cp| < xm1 < xm2:
*  #[   improve: |cp| < xm2 < xm1:
	    if ( abs(Re(cp)).lt.xloss*absc(xm1) .and. 
     +	    		Re(xm2).lt.Re(xm1) ) then
		slam = sqrt(clam)
		alp = (2*xm2*xm1/(2*piDpj(1,2)+slam) + xm2)/(slam+dm1m2)
*		bet = [xm1-xm2-cp-slam]
		bet = 4*xm2*cp/(-2*piDpj(2,3)+slam)
		xnoe = 1/(-2*piDpj(1,3)+slam)
		xnoe2 = xnoe**2
		cs(1) = cp/xm1*ca0i(1)
		cs(2) = -xlogmm*bet*(12*cp*xm1*xm2+6*cp*xm2**2-
     +		6*cp**2*xm2-2*xm1*xm2**2-2*xm2**3)
     +		/((dm1m2+slam)*(2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
		cs(3) = -xlogmm*(-24*cp*xm1**2*xm2-4*cp*xm2**3+36*
     +		cp**2*xm1*xm2+12*cp**2*xm2**2-12*cp**3*xm2)
     +		/((dm1m2+slam)*(2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
		cs(4) = xnoe2*xm2*bet*(cp-4*xm1)
		cs(5) = xnoe2*xm2*(-10*cp*xm1)
		cs(6) = xnoe2*xm2**2*bet
		cs(7) = xnoe2*xm2**2*4*cp
		cs(8) = xnoe2*bet*(cp*xm1+3*xm1**2)
		cs(9) = xnoe2*6*cp*xm1**2
		cs(10)= cp*(7/6.d0 - 2*xm1*slam*xnoe2 +
     +			4*xm2*slam*xnoe2 - 2*slam*xnoe)
		cs(11)= cp**2*( -2*slam*xnoe2 )
		xlo3 = zfflo3(2*cp*xnoe,ier)
		cs(12) = xlo3*dm1m2**2*slam/cp**2
		cs(13) = xlo3*(xm1 - 2*xm2)*slam/cp
		cs(14) = xlo3*slam
		csom = 0
		xmxp = 0
		do 60 i=1,14
		    csom = csom + cs(i)
		    xmxp = max(xmxp,absc(cs(i)))
   60		continue
		if ( xmxp.lt.xmax ) then
		    cb2i(1) = csom
		    xmax = xmxp
		endif
		if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
	    endif
*  #]   improve: |cp| < xm2 < xm1:
*  #[   wrap up:
  100	    continue
	    xmax = xmxsav
	    cb2i(1) = Re(1/(3*cp)) * cb2i(1)
	    cb2i(2) = Re(1/6.d0)   * cb2i(2)
*  #]   wrap up:
*  #[ cp=0, m1!=m2:
	elseif (dm1m2 .ne. 0) then
*		#[ B21:
		llogmm = .FALSE.
*
*		B21 (see thesis, b21.frm)
*
		cs(1) = xm1**2/3/dm1m2**3*ca0i(1)
		cs(2) = (-xm1**2 + xm1*xm2 - xm2**2/3)/dm1m2**3*ca0i(2)
		cs(3) = (5*xm1**3/18 - xm1*xm2**2/2 + 2*xm2**3/9)
     +			/dm1m2**3
		cb2i(1) = cs(1)+cs(2)+cs(3)
		xmax = max(absc(cs(2)),absc(cs(3)))
		if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
*
*		ma ~ mb
*
		if ( absc(dm1m2).lt.xloss*absc(xm1) ) then
		    xlogmm = zfflo1(dm1m2/xm1,ier)
		else
		    xlogmm = log(xm2/xm1)
		endif
		llogmm = .TRUE.
		cs(1) = (xm1/dm1m2)/6
		cs(2) = (xm1/dm1m2)**2/3
		cs(3) = (xm1/dm1m2)**3*xlogmm/3
		cs(4) = -2/Re(9) + ca0i(1)/(3*xm1)
		cs(5) = -xlogmm/3
		csom = cs(1)+cs(2)+cs(3)+cs(4)+cs(5)
		xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
     +			absc(cs(5)))
		if ( xmxp.lt.xmax ) then
		    xmax = xmxp
		    cb2i(1) = csom
		    if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
		endif
*
*		and last try
*
		xlo3 = zfflo3(dm1m2/xm1,ier)
		cs(1) = (dm1m2/xm1)**2/6
		cs(2) = (dm1m2/xm1)/3
		cs(3) = xlo3/(3*(dm1m2/xm1)**3)
*same		cs(4) = -2/Re(9) + ca0i(1)/(3*xm1)
		cs(5) = -xlo3/3
		csom = cs(1)+cs(2)+cs(3)+cs(4)+cs(5)
		xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
     +			absc(cs(5)))
		if ( xmxp.lt.xmax ) then
		    xmax = xmxp
		    cb2i(1) = csom
		    if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
		endif
*
*		give up
*
  160		continue
*		#] B21:
*		#[ B22:
*
*		B22
*
		cs(1) = +xm1/(4*dm1m2)*ca0i(1)
		cs(2) = -xm2/(4*dm1m2)*ca0i(2)
		cs(3) = (xm1+xm2)/8
		cb2i(2) = cs(1) + cs(2) + cs(3)
		xmax = max(absc(cs(2)),absc(cs(3)))
		if ( absc(cb2i(2)).gt.xloss*xmax ) goto 210
*
*		second try, close together
*
		if ( .not.llogmm ) then
		    if ( abs(dm1m2).lt.xloss*absc(xm1) ) then
			xlogmm = zfflo1(dm1m2/xm1,ier)
		    else
			xlogmm = log(xm2/xm1)
		    endif
		endif
		cs(1) = dm1m2*( -1/Re(8) - ca0i(1)/(4*xm1) )
		cs(2) = dm1m2*xlogmm/4
		cs(3) = xm1*(xm1/dm1m2)/4*xlogmm
		cs(4) = xm1*( 1/Re(4) + ca0i(1)/(2*xm1) )
		cs(5) = -xm1*xlogmm/2
		csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
		xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
     +			absc(cs(5)))
		if ( xmxp.lt.xmax ) then
		    xmax = xmxp
		    cb2i(2) = csom
		endif
		if ( absc(cb2i(2)).gt.xloss*xmax ) goto 210
*
*		give up
*
  210		continue
*		#] B22:
*  #] cp=0, m1!=m2:
*  #[ cp=0, m1==m2:
	else
*
*	    taken over from ffxb2a, which in turns stem from my thesis GJ
*
	    cb2i(1) = cb0/3
	    cb2i(2) = xm1/2*(cb0 + 1)
	endif
*  #] cp=0, m1==m2:
*  #[ finish up:
	ier = max(ier0,ier1)
*  #] finish up:
*###] ffcb2q:
	end
