        SUBROUTINE fit_fun(funarg, nargs, parg, earg)
!       --------------------------------------------

	include 'fit.inc'

	integer funarg ! negative: ask, other values: see format 1100 at bottom
	integer nargs ! functions 2,3,4,7:
	              !   nargs=0: ask for parameters
	              !   nargs>0: preset parameters and errors
	              ! functions 0,1:
	              !   nargs=0: auto parameters
	              !   nargs=1: preset position, auto width/intensity
	              ! function 5: narg unused
	              ! function 6: auto parameters
	              !   nargs=0: normal, nargs=1: multiply with with parg(1)
	real parg(*)  ! preset parameter
	real earg(*)  ! preset error
	logical fixed, strange

	integer npfix,i,iexp,nsum,npuser,k,npeak
	integer jfifu, nu_user, narg
	real a,b,ukp,ukm,sumx,sumy,sumxx,sumxy,xr,yr,xl,yl,uk
	real wk, YVALmax, wmult

	real voigt ! function
	integer fit_userini

	jfifu=ififu
	nu_user=0
	if (up .eq. 0.0)
	1  stop 'error in FIT_FUN: FIT_INIT must be called first'
   13	if (funarg .lt. 0) then
	  WRITE (ISYSWR,1100) usertit
          READ (ISYSRD,1101,END=999,err=999) i
          IF (i.LT.0 .OR. i.GT.8) GO TO 13
	  ififu=i
	  narg=0
	else
	  ififu=funarg
	  narg=nargs
	endif
   
	wmult=1.0
	if (ififu .eq. 6) then ! for strange peak use gaussian to determine start values
	  if (narg .eq. 1) wmult=parg(1)
	  narg=0
	  ififu=0
	  strange=.true.
	else
	  strange=.false.
	endif
	
   10	NFCN=1
        ISW(1)=0
        ISW(2)=0
        ISW(3)=0
	SIGMA = 0.
	NPFIX = 0
	NPAR = 0
	DO 11 I= 1, MAXEXT
	  if (ififu .ne. 6) then
!	    U(I) = 0.0
            WERRS(I) = 0.
	  endif
          ICSW(I) = 0
          ICTO(I) = 0
          CFAC(I) = 0.
	  coff(I) = 0.
	  LCODE(I) = 0
   11     LCORSP (I) = 0

        IF (IFIFU.LE.1) THEN

C . . . . . SINGLE PEAK PARAMETERS  . .

	  pnam(1)= 'Bg(Pos) '
	  psho(1)= 'B'
	  pnam(2)= 'dBg/dx  '
	  psho(2)= 'D'
	  pnam(3)= 'Posi.  1'
	  psho(3)= 'P1'
	  pnam(4)= 'MaxInt 1'
	  psho(4)= 'M1'
	  pnam(5)= 'IntInt 1'
	  psho(5)= 'I1'
	  pnam(6)= 'Fwhm G 1'
	  psho(6)= 'G1'
	  pnam(7)= 'Fwhm L 1'
	  psho(7)= 'L1'
          do i=1,7
	    lcode(i) = 1     
	  enddo
	  if (ififu .eq. 0) then	! pure gaussian
	    lcode(7)=0
	    u(7)=0
	    werr(7)=0
	  endif
	  ififu=1
	  if (narg .eq. 1) then         ! preselected position
	    u(3)=parg(1)
	    lcode(3)=0			! fix pos for findauto
	  endif
	  nu=2
	  call fit_findauto
	  nu=7
	  if (narg .eq. 1) lcode(3)=1	! release position

	elseif (ififu .eq. 6) then

C . . . . . . STRANGE PEAK . . . . . 

	  PNAM(3)='Position'
	  psho(3)='P'
	  PNAM(4)='fw(Bg)  '
	  psho(4)='W'
	  NU=4
	  WERR(1)=1
	  LCODE(1)=1
	  WERR(2)=1
	  LCODE(2)=1
	  WERR(3)=0
	  LCODE(3)=0
	  WERR(4)=0
	  LCODE(4)=0
	  if (u(4) .gt. 0) then
	    U(4)=u(6)*wmult*sqrt(max(1.0,log(2*u(4)/werr(1))/1.25))
	  else
	    u(4)=u(6)
	  endif
	  call extoin
	  call fit_fit(0)

	ELSEIF (IFIFU.EQ.5) THEN

C. . . . . CRITCAL EXPONENT PARAMETERS . .

	  do i=1,7
	    psho(i)=' '
	  enddo
          PNAM(1)= 'TC    '
          PNAM(2)= 'BETA  '
          PNAM(3)= 'CONST '
          PNAM(4)= 'BG    '
  201	  WRITE (ISYSWR,1200)
          READ(ISYSRD,1101,ERR=201,END=999) IEXP
  202	  WRITE (ISYSWR,1201)
          READ(ISYSRD,1107,ERR=202,END=999) U(1),WERR(1),A,B
          IF  (A)  212,210,212
  210	  IF  (B)  212,211,212
  211	  LCODE(1) = 1
	  GO TO 220
  212	  UKP = U(1)+ABS(WERR(1))
          UKM = U(1)-ABS(WERR(1))
          IF (A.GE.UKM) GOTO 213
          IF (B.LE.UKP) GOTO 213
          LCODE(1) = 4
          ALIM(1) = A
          BLIM(1) = B
          GOTO 220
  213	  WRITE (ISYSWR,1111)
          GOTO 202
  220	  IF (WERR(1).EQ.0.) LCODE(1) = 0
          NU = 3
          U(6) = -1.
          IF (IEXP.EQ.2) U(6) = 1.
          IF (IEXP.EQ.4) U(6) = 1.
          IF (IEXP.GE.2) PNAM(2)= 'GAMMA '
          IF (IEXP.GE.4) PNAM(2)= 'NY    '
          IF (IEXP.GE.4) GOTO 230
          NU = 4
  221	  WRITE (ISYSWR,1202)
          READ(ISYSRD,1107,ERR=221,END=999) U(4),WERR(4)
          IF (WERR(4).NE.0.) LCODE(4) = 1
  230	  NSUM = 0
          SUMX = 0.
          SUMY = 0.
          SUMXX = 0.
          SUMXY = 0.
          DO 231 I = NXMIN,NXMAX
            XR = U(6)*(XVAL(I)-U(1))/U(1)
            IF (XR.LT.1E-5) GOTO 231
            YR = YVAL(I) - U(4)
            IF (YR.LT.1E-10) GOTO 231
            XL = ALOG(XR)
            YL = ALOG(YR)
            SUMX = SUMX + XL
            SUMY = SUMY + YL
            SUMXX = SUMXX + XL*XL
            SUMXY = SUMXY + XL*YL
            NSUM = NSUM + 1
  231	  CONTINUE
          IF (NSUM.GE.2) GOTO 232
          WRITE (ISYSWR,1203)
          GOTO 10
  232	  U(2) = (SUMXY-SUMX*SUMY/NSUM)/(SUMXX-SUMX*SUMX/NSUM)
          WERR(2) = ABS(0.1*U(2))
          LCODE(2) = 1
          U(3) = EXP(SUMY/NSUM-U(2)*SUMX/NSUM)
          WERR(3) = ABS(0.1*U(3))
          LCODE(3) = 1
	  u(5)=0.
          IF (IEXP.GT.0) GOTO 259
  250	  NU = 7
          PNAM(4)= 'CRI.A '
          PNAM(5)= 'CRI.C '
          PNAM(6)= 'CRI.S '
          PNAM(7)= 'BG    '
          U(7) = U(4)
          WERR(7) = WERR(4)
          LCODE(7) = LCODE(4)
          U(6) = 3.
          WERR(6) = 0.
          LCODE(6) = 0
          LCODE(5) = 1
          LCODE(4) = 1
          NSUM = 0
          SUMX = 0.
          SUMY = 0.
          SUMXX = 0.
          SUMXY = 0.
          DO 255 I = NXMIN,NXMAX
            XR = (XVAL(I)-U(1))/U(1)
            IF (XR.GT.-1.E-4) GOTO 251
            YR = YVAL(I) - U(3)*((-XR)**U(2)) - U(7)
            XR = -XR*U(6)
            GOTO 252
  251	    IF (XR.LT.1.E-4) GOTO 255
            YR = YVAL(I) - U(7)
  252	    IF (YR.LT.1E-10) GOTO 255
            XL = XR
            YL = ALOG(YR)
            SUMX = SUMX + XL
            SUMY = SUMY + YL
            SUMXX = SUMXX + XL*XL
            SUMXY = SUMXY + XL*YL
            NSUM = NSUM + 1
  255	  CONTINUE
          IF (NSUM.GE.2) GOTO 256
          PNAM(2)= 'CR.SCAT.'
          WRITE (ISYSWR,1203) PNAM(2)
          GOTO 10
  256	  U(4) = (SUMXY-SUMX*SUMY/NSUM)/(SUMXX-SUMX*SUMX/NSUM)
          WERR(4) = ABS(0.1*U(4))
          U(5) = EXP(SUMY/NSUM-U(4)*SUMX/NSUM)
          WERR(5) = ABS(0.1*U(5))
  259	  CONTINUE

	ELSEIF (IFIFU .EQ. 8) THEN

C . . . . . . PLOT ONLY

	  nu=0
	  RETURN

  	ELSE				! standard input
	  if (ififu.eq.7) then
	    if (usernp .eq. 0 .or. userfun .eq. 0) then
	      print *,'No user function implemented'
	      goto 999
	    endif
	    npuser=usernp
	    do k=1,npuser
	      pnam(k)=userpar(k)
	      psho(k)=usersho(k)
	      lcode(k)=1
	    enddo
	    if (nu .eq. 0) nu=1
	    nu_user=fit_userini(jfifu)
	    if (nu_user .gt. 0) npuser=nu_user
	    nu=0	! nu is incremented for each check parameter below
	  else ! multi-voigt based functions
	    nu=0
	    if (narg .eq. 0) then
	      print *
	  print *,'    Hint: In general, it is easier to use Single',
	1          ' Gaussian'
	  print *,'    for start and then add new peaks graphically or'
	      print *,'    with command NEWPEAK'
	    endif
	    npeak=maxpeak
	    if (ififu .eq. 4) npeak=2
	    npuser=2+npeak*5
	    write(pnam, 291) 'Bg(Pos1)','dBg/dx  ',
	1     ('Posi. ',i
	1     ,'MaxInt',i
	1     ,'IntInt',i
	1     ,'Fwhm G',i
	1     ,'Fwhm L',i, i=1,npeak)
291	    format (a8/a8,999(/a6,i2))
	    write(psho, 292) 'B','D',
	1     ('P',i,'M',i,'I',i,'G',i,'L',i, i=1,npeak)
292	    format (a1/a1,45(/a1,i1),999(5(/a1,i2)))
	    do k=1,npuser
	      lcode(k)=1
	    enddo
	  endif
C. . . . . . . . . . . . . . . . . . .
C. . . . . LOOP TO SET PARAMETERS  . .
          DO 590 K=1,npuser
521	    if (nu_user .gt. 0) then
	      uk=u(k)
	      wk=0
	      fixed=.true.
	      a=0
	      b=0
	    elseif (funarg .lt. 0 .or. narg .eq. 0) then
	      if (k .eq. 1) WRITE (ISYSWR,1102)
	      if (ififu .eq. 2 .and. k .gt. 2 .and. mod(k,5) .eq. 2 .or.
	1         ififu .eq. 4 .and. k .eq. 7) then		! do not ask for lorentzian HW
	        u(k)=0
	        werr(k)=0
	        lcode(k)=0
	        nu=nu+1
	        goto 590
	      endif
	      if (ififu .le. 4 .and. mod(k,5) .eq. 0) then	! Int.Int.
	        lcode(k)=0
	        nu=nu+1
	        goto 590
	      endif
522	      WRITE (ISYSWR,1106) K,PNAM(K),': '
              READ (ISYSRD,'(4F20.0)',ERR=522,END=529)
	1                   UK,WK,A,B
	      fixed=wk .eq. 0
              IF (UK.EQ.999.) goto 529
	    else
	      if (k .gt. narg) goto 529
	      uk=parg(k)
	      wk=earg(k)
	      fixed=wk .eq. 0.0
	      a=0
	      b=0
	    endif
C. . . . . LIMIT CHECK . . . . . . .
	    IF (A .EQ. 0.0 .AND. B .EQ. 0.0) GOTO 540
	    UKP = UK+ABS(WK)
	    UKM = UK-ABS(WK)
	    if (a .ge. ukm .or. b .le. ukp) then
	      WRITE (ISYSWR,1111)
	      if (funarg .lt. 0 .or. narg .eq. 0) goto 521
	      a=ukm
	      b=ukp
	    endif
	    LCODE(K) = 4
	    ALIM(K) = A
	    BLIM(K) = B
C. . . . . FWHM 1 EQUAL TO ZERO . . . . 
  540	    if (ififu .le. 4 .and. uk .eq. 0 .and.
	1       k .gt. 1 .and. mod(k,5) .eq. 1) then	! gaussian hw
	      if (k .eq. 5) then
	        if (ififu .eq. 2) then
	          WRITE (ISYSWR,1112)
	          if (funarg .lt. 0 .or. narg .eq. 0) goto 521
	          uk=1
	        endif
	        goto 570
	      endif
C. . . . . FWHM CORRELATION . . .
  560	      ICSW(K) = 1
	      ICTO(K) = 5
	      CFAC(K) = 1.
	      WERRS(K) = WK
	      UK = U(5)
	      WK = 0.
	      WRITE(ISYSWR,1110) K,PNAM(K)
C. . . . . END FWHM COR . . . . . 
	    endif
  570	    NU=NU+1
	    U(K) = UK
	    WERR(K) = WK
	    if (fixed) then
	      lcode(k)=0
	      werr(k)=0
	    endif
  590	  CONTINUE
	  goto 599

529	  if (ififu .le. 4 .and. mod(nu,5) .ne. 2) then
	     nu=nu-mod(nu+2,5)
	     WRITE (ISYSWR, '(/X,A,/)')
	1      'Not all parameters are defined -> last peak removed'
	  endif

599	  continue
	ENDIF
	if (ififu .le. 4) then	! calculate int.intensities
	  ififu=1
	  do k=4,nu,5
	    YVALmax=voigt(0.0, u(k+2), u(k+3))
	    u(k+1)=u(k)/YVALmax
	    if (lcode(k) .ne. 1) then	! fixed or limited Max.Int
	      werr(k)=0
	      icsw(k+1)=-1
	      icto(k+1)=k
	    else
	      werr(k+1)=werr(k)/YVALmax
	      lcode(k)=0
	      lcode(k+1)=1
	      icsw(k)=-1
	      icto(k)=k+1
	    endif
	  enddo
	endif

	call extoin
	call fit_check_range

	if (ififu .eq. 8) return
        if (isyswr .ne. 0) WRITE (ISYSWR,2000)
 2000	FORMAT (/' First entry to FCN')
	call fnctn(x, amin)
	if (strange) then
	  strange=.false.
	  write(isyswr,'(/x,a/)')
	1   '--- STRANGE peak: fit one gaussian'
	  call fit_fit(0)
	  write(isyswr,'(/x,a/)')
	1   '--- STRANGE peak: calculate P and W from gaussian'
	  ififu=6
	  goto 10
	endif
	if (ififu .eq. 6) then
	  write(isyswr,'(/x,a/)')
	1   '--- STRANGE peak: fit background'
	  call fit_fit(0)
	  return
	endif

        CALL FIT_PRINT (1)
	WK=AMIN
        NFCN=1
	call fnctn(x, wk)
        IF (WK.EQ.AMIN) RETURN
        WRITE (ISYSWR,2001) AMIN,WK
 2001	FORMAT (/' FCN is time-dependent: 1. Call F=',E16.7
	1       /24X,                    '2. Call F=',E16.7)
  999   RETURN

 1100 FORMAT(
	1/8X,'Single Gaussian     = 0'
	1/8X,'Single Voigtian     = 1 (Lorentzian folded with Gaussian)',
	1/8X,'Multi Gaussian      = 2'
	1/8X,'Multi Voigtian      = 3'
	1/8X,'Gaussian + Voigtian = 4'
	1/8X,'Crit.Exponent       = 5'
	1/8X,'Strange             = 6'
	1/8X,A,              '    = 7 (User function)'
	1/8X,'Plot only           = 8'//
	1/8X,'Select function [0] : ',$)

 1101 FORMAT (I1)
 1102 FORMAT(/,'    Parameter:       Value,Error,(Lower-,Upper-Lim'
     1,'it)    end = 999',/)
 1103 FORMAT (/,'  Only ',I2,' variable parameters allowed',/)
 1106 FORMAT (I6,4X,A8,A,$)
 1107 FORMAT (4F10.0)
 1110 FORMAT ('+',I5,4X,A8,'  =   Fwhm G 1')
 1111 FORMAT (8X,'Input error:    Parameter out of limits')
 1112 FORMAT (8X,'Input error:    Fwhm G 1 = 0.')
 1200 FORMAT(/,'    EXPONENT:   BRAGG+CRIT.SCATTERING:    = 0 ',
     ,/,       '                ORD.PARAMETER: BETA,T<TC  = 1 ',
     ,/,       '                FLUCTUATIONS: GAMMA,T>TC  = 2 ',
     ,/,       '                              GAMMA,T<TC  = 3 ',
     ,/,       '                CORREL.LENGTH:  NY ,T>TC  = 4 ',
     ,/,       '                                NY ,T<TC  = 5    ',$)
 1201 FORMAT(/,'    ORDERING TEMPERATURE   ',
     ,         ' VALUE,ERROR,(LOWER-,UPPER-LIMIT) : ',$)
 1202 FORMAT(/,'    TEMP.INDEP.BACKGROUND   VALUE,ERROR : ',$)
 1203 FORMAT(/,'    NOT ENOUGH DATAPOINTS TO DETERMINE ',A8)
	END
