Viewing contents of file '../idllib/contrib/meron/m_convol.pro'
Function M_Convol, far, gar, nocenter = noc, reverse = rev, clip = cli, $
    edge_val = edv, edge_truncate = edt

;+
; NAME:
;	M_CONVOL
; VERSION:
;	3.0
; PURPOSE:
;	Calculates the convolution of two functions represented by arrays.
; CATEGORY:
;	Mathematical, array function.
; CALLING SEQUENCE:
;	Result = M_CONVOL (FAR, GAR [, keywords])
; INPUTS:
;    FAR
;	Array, numeric, otherwise arbitrary.
;    GAR
;	Ditto.
; OPTIONAL INPUT PARAMETERS:
;	None.
; KEYWORD PARAMETERS:
;    /NOCENTER
;	Switch.  Prevents centering one array over the other (corresponds to
;	the CENTER = 0 setting in IDL CONVOL.  The default is CENTERED.
;    /REVERSE
;	Switch.  Reverses the direction, i.e instead of f(x-x')g(x') the
;	integrand becomes f(x+x')g(x').
;    /CLIP
;	Switch.  If set, the edges of the result (which cannot be fully 
;	convolved) are set to zero, same as the default behavior of IDL CONVOL.
;	The default behaviour of M_CONVOL corresponds to the IDL CONVOL 
;	EDGE_WRAP SETTING.
;    EDGE_VAL
;	Accepts a value to be used for all the "beyond the edge " elements.
;	if EDGE_VAL is provided, /CLIP is ignored.  EDGE_VAL and EDGE_TRUNCATE
;	are mutually exclusive
;    /EDGE_TRUNCATE
;	Switch.  If set, the "beyond the edge" elements are obtained by a
;	propagation of the edge elements of FAR.  EDGE_TRUNCATE and EDGE_VAL
;	are mutually exclusive
; OUTPUTS:
;	Returns the result of the convolution with dimensions corresponding to 
;	the bigger of the two arrays.
; OPTIONAL OUTPUT PARAMETERS:
;	None.
; COMMON BLOCKS:
;	None.
; SIDE EFFECTS:
;	None.
; RESTRICTIONS:
;	None.
; PROCEDURE:
;	Uses FFT.  Faster then the IDL CONVOL, and differs from it in few 
;	significant aspects, as follows:
;
;	1) The two arrays are treated symmetrically, i.e. the result stays the 
;	same if they are exchanged (with the exception that when /REVERSE is
;	set, it is always the second array that's reversed.
;	2) The problem with IDL CONVOL, where the centered convolution is 
;	calculated in a reversed direction (versus standard mathematical 
;	practice) has been corrected.
;	3) The arrays don't have to be of the same dimensionality.  If they're 
;	not they are imbedded in an array big enough to contained both and 
;	padded with zeroes (default), a constant value (if EDGE_VAL is used)
;	or the edge elements of FAR (if EDGE_TRUNCATE is used).
;
;	Calls CAST, EXTEND_ARRAY, FPU_FIX and TYPE from MIDL.
; MODIFICATION HISTORY:
;	Created 15-NOV-1996 by Mati Meron.
;	Modified 20-JAN-1997 by Mati Meron.  Streamlined (through the use of
;	EXTEND_ARRAY and added keyword EDGE_TRUNCATE.
;	Modified 15-SEP-1998 by Mati Meron.  Underflow filtering added.
;-

    ndm = 7
    if keyword_set(noc) then cefl = 0 else cefl = 1
    if keyword_set(rev) then refl = 1 else refl = 0
    clfl = keyword_set(cli)
    edfl = keyword_set(edt) or n_elements(edv) ne 0
    typ = Type(far) > Type(gar)

    sif = size([far])
    sig = size([gar])
    ndf = sif(0)
    ndg = sig(0)
    if ndf lt ndm then nf=[replicate(1l,ndm-ndf),sif(1:ndf)] else nf=sif(1:ndf)
    if ndg lt ndm then ng=[replicate(1l,ndm-ndg),sig(1:ndg)] else ng=sig(1:ndg)

    p = nf > ng
    q = nf < ng
    if edfl then begin
	clfl = 1
	l = ((1 - refl)*(q - 1) + refl*cefl*q)/(1 + cefl)
	p = p + q - 1
    endif else l = replicate(0l,ndm)

    prod = 1l
    for i = 0, ndm - 1 do prod = prod*p(i)
    sir = [ndm,p,typ,prod]

    wfar = Extend_array(far,l,newsize=sir,value=edv,edge=edt)
    wgar = Extend_array(gar,newsize=sir)

    if refl then res = conj(fft(conj(wgar))) else res = fft(wgar)
    res = reform(FPU_fix(prod*fft(fft(wfar)*res,/inverse)),sir(1:ndm))

    s = (2*refl - 1)*(q/2)
    if cefl then res = shift(res,s(0),s(1),s(2),s(3),s(4),s(5),s(6))

    if clfl then begin
	l = ((1 - refl)*(q - 1) + refl*cefl*q)/(1 + cefl)
	h = l + p - q

	res = res(l(0):h(0),l(1):h(1),l(2):h(2),l(3):h(3), $
		l(4):h(4),l(5):h(5),l(6):h(6))
	if not edfl then res = Extend_array(res,l,newsize=sir)
    endif

    return, Cast(reform(res),typ,typ)
end