/*
  range.c
  Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library)
    (C) Copyright 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_array.h"
#ifdef HAVE_NARRAY_H
#include "rb_gsl_with_narray.h"
#endif

static VALUE rb_gsl_range_new(int argc, VALUE *argv, VALUE klass)
{
  gsl_vector *v = NULL, *range = NULL;
  double a, b, x;
  size_t n, i;
  VALUE vnn, vaa;
  
  if (argc != 2 && argc != 3) 
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 3)", argc);
  
  switch (argc) {
  case 3:
    Need_Float(argv[0]); Need_Float(argv[1]); CHECK_FIXNUM(argv[2]);
    a = NUM2DBL(argv[0]);
    b = NUM2DBL(argv[1]);
    n = FIX2INT(argv[2]);
    break;
  case 2:
    if (FIXNUM_P(argv[0])) {
      vnn = argv[0];
      vaa = argv[1];
    } else {
      vnn = argv[1];
      vaa = argv[0];
    }
    CHECK_FIXNUM(vnn);
    n = FIX2INT(vnn);
    if (TYPE(vaa) == T_ARRAY) {
      a = NUM2DBL(rb_ary_entry(vaa, 0));
      b = NUM2DBL(rb_ary_entry(vaa, 1));
    } else {
      CHECK_VECTOR(vaa);
      Data_Get_Struct(vaa, gsl_vector, v);
      a = gsl_vector_get(v, 0);
      b = gsl_vector_get(v, 1);
    }
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 3)", argc);
  }
  x = (b - a)/(n-1);
  range = gsl_vector_alloc(n);
  gsl_vector_set(range, 0, a);
  for (i = 1; i < n; i++) gsl_vector_set(range, i, gsl_vector_get(range, i-1)+x);
  return Data_Wrap_Struct(klass, 0, gsl_vector_free, range);
}

void Init_gsl_range()
{
  rb_define_singleton_method(cgsl_range, "new", rb_gsl_range_new, -1);
  rb_define_singleton_method(cgsl_linspace, "new", rb_gsl_range_new, -1);
}
