#!/usr/bin/env ruby
#require("gsl")
#require("../gsl_test2.rb")
require("./test_multifit.rb")
include GSL::Test
include Math

Brown_N = 20;
Brown_P = 4;

Brown_X = GSL::Matrix.alloc([24.3485677, 4.71448798, -2.19486633, 2.69405755],
  [22.4116222, 3.93075538, -1.42344852, 2.5233557],
  [17.88886, 2.9290853, 0.125174936, -3.96823353],
  [17.3237176, 2.99606803, 2.03285653, 2.28992327],
  [17.0906508, 3.02485425, 0.296995153, 0.0876226126],
  [16.578006, 3.1036312, -0.18617941, 0.103262914],
  [15.692993, 3.33088442, 0.0706406887, 1.05923955],
  [14.3232177, 3.85604218, -2.3762839, -3.09486813],
  [14.1279266, 3.97896121, 0.446109351, 1.40023753],
  [13.6081961, 4.16435075, -1.51250057, -1.52510626],
  [13.4295245, 4.22697223, -0.196985195, 0.532009293],
  [13.0176117, 4.3579261, -0.353131208, 0.301377627],
  [12.2713535, 4.62398535, -0.00183585584, 0.894170703],
  [11.0316144, 5.13967727, -2.38978772, -2.89510064],
  [10.8807981, 5.24558004, 0.230495952, 1.27315117],
  [10.4029264, 5.41141257, -1.5116632, -1.47615921],
  [10.2574435, 5.46211045, -0.299855732, 0.451893162],
  [9.87863876, 5.57914292, -0.368885288, 0.358086545],
  [9.1894983, 5.82082741, -0.230157969, 0.621476534],
  [8.00589008, 6.27788753, -1.46022815, -1.33468082])

Brown_F = GSL::Vector.alloc(
                     2474.05541,
                     1924.69004,
                     1280.63194,
                     1244.81867,
                     1190.53739,
                     1159.34935,
                     1108.44426,
                     1090.11073,
                     1015.92942,
                     1002.43533,
                     971.221084,
                     949.589435,
                     911.359899,
                     906.522994,
                     840.525729,
                     833.950164,
                     807.557511,
                     791.00924,
                     761.09598,
                     726.787783)

Brown_cov = GSL::Matrix.alloc(
                       [ 1.8893186910e-01, -4.7099989571e-02,  5.2154168404e-01,  1.6608168209e-02],
                       [-4.7099989571e-02,  1.1761534388e-02, -1.2987843074e-01, -4.1615942391e-03],
                       [ 5.2154168404e-01, -1.2987843074e-01,  1.4653936514e+00,  1.5738321686e-02],
                       [ 1.6608168209e-02, -4.1615942391e-03,  1.5738321686e-02,  4.2348042340e-02]
                     )

Brown_x0 = GSL::Vector.alloc(25, 5, -5, -1)

brown_f = Proc.new { |x, t, y, f|
  for i in 0...Brown_N
    ti = 0.2 * (i + 1);
    ui = x[0] + x[1] * ti - exp(ti);
    vi = x[2] + x[3] * sin(ti) - cos(ti);
    f[i] = ui*ui + vi*vi
  end
  GSL::SUCCESS
}

brown_df = Proc.new { |x, t, y, df|
  for i in 0...Brown_N
    ti = 0.2 * (i + 1);
    ui = x[0] + x[1] * ti - exp(ti);
    vi = x[2] + x[3] * sin(ti) - cos(ti);
    df.set(i, 0, 2.0*ui)
    df.set(i, 1, 2.0*ui*ti)
    df.set(i, 2, 2.0*vi)
    df.set(i, 3, 2.0*vi*sin(ti))
  end
  GSL::SUCCESS
}

fdf = GSL::MultiFit::Function_fdf.alloc(brown_f, brown_df, Brown_P)

fdf.set_data(GSL::Vector.alloc(Brown_N), GSL::Vector.alloc(Brown_N))

test_lmder(fdf, Brown_x0, Brown_X.vector_view, Brown_F, Brown_cov.vector_view)
