// Attempt to implement IDL's curvefit into DPUSER

// This is the procedure that describes your model
procedure curpro, X, A, F {
  F = A[1] * sin(X + A[2], /deg) + A[3]
}

// initial estimates
x = [0,90,180,270,360]
y = [0,1,0,-1,0]
weights = [1,1,1,1,1]
a = [1,0,0]

// Now the real curvefit

function curvefit, x, y, a, weights {
tol = 1e-3
itmax = 20
eps = .000345267
nterms = nelements(a)
nfree = nelements(y) - nterms
if (nfree <= 0) print "Curvefit: not enough data points"
flambda = 0.001
diag = [0:nterms-1] * (nterms + 1)
pder = fits(nelements(y), nterms)
yfit = yfit1 = 0
for iter=1, itmax {
  curpro x, a, yfit
  for term=1, nterms {
    p = a
    inc = eps * abs(p[term])
    if (inc == 0) inc = eps
    p[term] += inc
    curpro x, p, yfit1
    pder[*,term] = (yfit1-yfit)/inc
  }
  beta = transpose((y - yfit) * weights) # pder
  alpha = transpose(pder) # (weights # transpose((fits(nterms) + 1)) * pder)

  sigma1 = fits(nelements(diag))
  for i=1, nelements(sigma1) sigma1[i] = sqrt(1/alpha[i,i])
//  sigma1 = sqrt(1 / alpha[diag,*])
  sigma = sigma1
  chisq1 = total(weights * (y - yfit) * (y - yfit)) / nfree
  chisq = chisq1

  yfit1 = yfit

  C = fits(nelements(diag))
  for i=1, nelements(C) C[i] = sqrt(alpha[i,i])
//  c = sqrt(alpha[diag])
  C = C # transpose(C)

  lambdaCount = 0

  cont = 1
  while (cont == 1) {
    lambdaCount++
    array = alpha / C
    for i=1, nelements(diag) array[i,i] *= 1 + flambda
    if (nelements(array) == 1) {
      array = 1 / array
    } else {
      array = invert(array)
    }
    b = a + array/C # transpose(beta)
    curpro x, b, yfit
    chisq = total(weights * (y - yfit) * (y - yfit)) / nfree
    for i=1, nelements(diag) sigma[i] = sqrt(array[i,i] / alpha[i,i])
    if (lambdaCount > 30 && chisq >= chisq1) {
      yfit = yfit1
      sigma = sigma1
      chisq = chisq1
      print "Failed to converge"
      cont = 0
//      break
      iter = itmax
    }
    flambda *= 10
    if (chisq <= chisq1) cont = 0
  }
  flambda /= 100
  a = b
  if (((chisq1 - chisq) / chisq1) <= tol) iter = itmax
}
curvefit = yfit
}

//print curvefit(x,y,a,weights),/values
//print hhh,/values


