/*
  dht.c
  Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library)
    (C) Copyright 2001-2004 by Yoshiki Tsunesada

  Ruby/GSL is free software: you can redistribute it and/or modify it
  under the terms of the GNU General Public License.
  This library is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY.
*/

#include "rb_gsl.h"
#include "rb_gsl_array.h"
#include <gsl/gsl_dht.h>

static VALUE rb_gsl_dht_new(int argc, VALUE *argv, VALUE klass)
{
  gsl_dht *t = NULL;
  switch (argc) {
  case 1:
    CHECK_FIXNUM(argv[0]);
    t = gsl_dht_alloc(FIX2INT(argv[0]));
    break;
  case 3:
    CHECK_FIXNUM(argv[0]);
    Need_Float(argv[1]); Need_Float(argv[2]);
    t = gsl_dht_new(FIX2INT(argv[0]), NUM2DBL(argv[1]), NUM2DBL(argv[2]));
   break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 3)", argc);
    break;
  }
  return Data_Wrap_Struct(klass, 0, gsl_dht_free, t);
}

static VALUE rb_gsl_dht_init(VALUE obj, VALUE nu, VALUE xmax)
{
  gsl_dht *t = NULL;
  Need_Float(nu); Need_Float(xmax);
  Data_Get_Struct(obj, gsl_dht, t);
  gsl_dht_init(t, NUM2DBL(nu), NUM2DBL(xmax));
  return obj;
}

static VALUE rb_gsl_dht_apply(int argc, VALUE *argv, VALUE obj)
{
  gsl_dht *t = NULL;
  gsl_vector *vin = NULL, *vout = NULL;
  switch (argc) {
  case 2:
    CHECK_VECTOR(argv[0]); CHECK_VECTOR(argv[1]);
    Data_Get_Struct(obj, gsl_dht, t);
    Data_Get_Struct(argv[0], gsl_vector, vin);
    Data_Get_Struct(argv[1], gsl_vector, vout);
    return INT2FIX(gsl_dht_apply(t, vin->data, vout->data));
    break;
  case 1:
    CHECK_VECTOR(argv[0]); 
    Data_Get_Struct(obj, gsl_dht, t);
    Data_Get_Struct(argv[0], gsl_vector, vin);
    vout = gsl_vector_alloc(vin->size);
    gsl_dht_apply(t, vin->data, vout->data);
    return Data_Wrap_Struct(CLASS_OF(argv[0]), 0, gsl_vector_free, vout);
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc);
    break;
  }
  return Qnil; /* never reach here */
}

static VALUE rb_gsl_dht_x_sample(VALUE obj, VALUE n)
{
  gsl_dht *t = NULL;
  CHECK_FIXNUM(n);
  Data_Get_Struct(obj, gsl_dht, t);
  return rb_float_new(gsl_dht_x_sample(t, FIX2INT(n)));
}

static VALUE rb_gsl_dht_k_sample(VALUE obj, VALUE n)
{
  gsl_dht *t = NULL;
  CHECK_FIXNUM(n);
  Data_Get_Struct(obj, gsl_dht, t);
  return rb_float_new(gsl_dht_k_sample(t, FIX2INT(n)));
}

void Init_gsl_dht()
{
  VALUE cgsl_dht;
  cgsl_dht = rb_define_class_under(mgsl, "Dht", rb_cObject);
  rb_define_singleton_method(cgsl_dht, "new", rb_gsl_dht_new, -1);
  rb_define_singleton_method(cgsl_dht, "alloc", rb_gsl_dht_new, -1);
  rb_define_method(cgsl_dht, "init", rb_gsl_dht_init, 2);
  rb_define_method(cgsl_dht, "apply", rb_gsl_dht_apply, -1);
  rb_define_method(cgsl_dht, "x_sample", rb_gsl_dht_x_sample, 1);
  rb_define_method(cgsl_dht, "k_sample", rb_gsl_dht_k_sample, 1);
}
