
#line 1 "../gen/tmpl/lib.c"
/*
  gsl_Ran.c
  Ruby/Numo::GSL - GSL wrapper for Ruby/Numo::NArray

  created on: 2017-03-11
  Copyright (C) 2017 Masahiro Tanaka
*/

#include <ruby.h>
#include <assert.h>
#include "numo/narray.h"
#include "numo/template.h"
#include "../numo_gsl.h"
#line 15 "../gen/tmpl/lib.c"
#include <gsl/gsl_randist.h>

#line 18 "../gen/tmpl/lib.c"
static VALUE mG;



#line 1 "../gen/tmpl/module.c"
/*
  module definition: Numo::GSL::Ran
*/

#line 6 "../gen/tmpl/module.c"
static VALUE mRan;



#line 1 "../gen/tmpl/class.c"
/*
  class definition: Numo::GSL::Ran::Discrete
*/

static VALUE cDiscrete;

static void
ran_discrete_free(void *ptr)
{
    gsl_ran_discrete_free(ptr);
}

static size_t
ran_discrete_memsize(const void *ptr)
{
    return sizeof(gsl_ran_discrete_t);
}

static const rb_data_type_t ran_discrete_data_type = {
    "Numo::GSL::Ran::Discrete",
    {NULL, ran_discrete_free, ran_discrete_memsize,},
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};


#line 1 "../gen/tmpl/c_new_DFloat.c"

#line 5 "../gen/tmpl/c_new_DFloat.c"
/*
  @overload new(K)
  @param  [DFloat]  K

  allocate instance of Discrete class.

  This function returns a pointer to a structure that contains the lookup
table for the discrete random number generator.  The array P[] contains
the probabilities of the discrete events; these array elements must all be 
positive, but they needn't add up to one (so you can think of them more
generally as ``weights'')---the preprocessor will normalize appropriately.
This return value is used
as an argument for the gsl_ran_discrete function below.
 */
static VALUE
ran_discrete_s_new(VALUE self, VALUE v1)
{
    narray_t *na;
    double *d;
    gsl_ran_discrete_t *w;

    v1 = rb_funcall(cDF,rb_intern("cast"),1,v1);
    GetNArray(v1,na);
    d = (double*)na_get_pointer_for_read(v1);
    w = gsl_ran_discrete_preproc(na->size, d);
    RB_GC_GUARD(v1);
    if (!w) {
        rb_raise(rb_eNoMemError,"fail to allocate struct");
    }
    return TypedData_Wrap_Struct(cDiscrete, &ran_discrete_data_type, (void*)w);
}


#line 1 "../gen/tmpl/c_DFloat_f_SZ.c"
static void
iter_ran_discrete_pdf(na_loop_t *const lp)
{
    size_t   i;
    char    *p1, *p2;
    ssize_t  s1, s2;
    size_t   x;
    double   y;
    gsl_ran_discrete_t *w = (gsl_ran_discrete_t*)(lp->opt_ptr);
    

    INIT_COUNTER(lp, i);
    INIT_PTR(lp, 0, p1, s1);
    INIT_PTR(lp, 1, p2, s2);

    for (; i--; ) {
        GET_DATA_STRIDE(p1,s1,size_t,x);
        y = gsl_ran_discrete_pdf(x,w);
        SET_DATA_STRIDE(p2,s2,double,y);
    }
}

/*
  @overload pdf(g)
  @param  [UInt]      g
  @return [DFloat]    result

  Returns the probability P[k] of observing the variable k.
Since P[k] is not stored as part of the lookup table, it must be
recomputed; this computation takes O(K), so if K is large
and you care about the original array P[k] used to create the
lookup table, then you should just keep this original array P[k]
around.
*/
static VALUE
ran_discrete_pdf(VALUE self, VALUE v1)
{
    gsl_ran_discrete_t *w;
    ndfunc_arg_in_t ain[1] = {{cSZ,0}};
    ndfunc_arg_out_t aout[1] = {{cDF,0}};
    ndfunc_t ndf = {iter_ran_discrete_pdf, STRIDE_LOOP|NDF_EXTRACT, 1,1, ain,aout};

    TypedData_Get_Struct(self, gsl_ran_discrete_t, &ran_discrete_data_type, w);

    return na_ndloop3(&ndf, w, 1, v1);
}


#line 28 "../gen/tmpl/lib.c"
void
Init_ran(void)
{
    VALUE mN;
    mN = rb_define_module("Numo");
    mG = rb_define_module_under(mN, "GSL");

    


#line 1 "../gen/tmpl/init_module.c"

    /*
      Document-module: Numo::GSL::Ran
      
    */
    {
    
    mRan = rb_define_module_under(mG, "Ran");
    
    
#line 12 "../gen/tmpl/init_module.c"
    }

#line 1 "../gen/tmpl/init_class.c"

    /*
      Document-class: Numo::GSL::Ran::Discrete
      
    */
    {
    cDiscrete = rb_define_class_under(mRan, "Discrete", rb_cObject);
    
    rb_define_singleton_method(cDiscrete, "new", ran_discrete_s_new, 1);
    rb_define_method(cDiscrete, "pdf", ran_discrete_pdf, 1);
#line 10 "../gen/tmpl/init_class.c"
    }
#line 41 "../gen/tmpl/lib.c"
}
