
#line 1 "../gen/tmpl/lib.c"
/*
  gsl_Rstat.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_rstat.h>

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



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

static VALUE cRstat;

static void
rstat_free(void *ptr)
{
    gsl_rstat_free(ptr);
}

static size_t
rstat_memsize(const void *ptr)
{
    return sizeof(gsl_rstat_workspace);
}

static const rb_data_type_t rstat_data_type = {
    "Numo::GSL::Rstat",
    {NULL, rstat_free, rstat_memsize,},
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};



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

#line 5 "../gen/tmpl/c_new_void.c"
/*
  @overload new

  allocate instance of Rstat class.

This function allocates a workspace for computing running statistics.
The size of the workspace is O(1). */
static VALUE
rstat_s_new(VALUE self)
{
    gsl_rstat_workspace *w;
    w = gsl_rstat_alloc();
    if (!w) {
        rb_raise(rb_eNoMemError,"fail to allocate struct");
    }
    return TypedData_Wrap_Struct(cRstat, &rstat_data_type, (void*)w);
}


#line 1 "../gen/tmpl/c_void_f_void.c"
/*
  @overload reset

  This function resets the workspace w to its initial state,
so it can begin working on a new set of data.
*/
static VALUE
rstat_reset(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);
    gsl_rstat_reset(w);
    return Qnil;
}


#line 1 "../gen/tmpl/c_self_f_DFloat.c"
static void
iter_rstat_add(na_loop_t *const lp)
{
    size_t   i;
    char    *p1;
    ssize_t  s1;
    size_t  *idx1;
    double   x;
    gsl_rstat_workspace *w = (gsl_rstat_workspace*)(lp->opt_ptr);
    

    INIT_COUNTER(lp, i);
    INIT_PTR_IDX(lp, 0, p1, s1, idx1);

    if (idx1) {
        for (; i--;) {
            GET_DATA_INDEX(p1,idx1,double,x);
            gsl_rstat_add(x,w);
        }
    } else {
        for (; i--;) {
            GET_DATA_STRIDE(p1,s1,double,x);
            gsl_rstat_add(x,w);
        }
    }
}

/*
  @overload add(w)
  @param  [DFloat]   w
  @return [Rstat]  self

  This function adds the data point x to the statistical
accumulator, updating calculations of the mean, variance,
standard deviation, skewness, kurtosis, and median.
*/
static VALUE
rstat_add(VALUE self, VALUE v1)
{
    gsl_rstat_workspace *w;
    ndfunc_arg_in_t ain[1] = {{cDF,0}};
    ndfunc_t ndf = {iter_rstat_add, FULL_LOOP, 1,0, ain,0};

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

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


#line 1 "../gen/tmpl/c_sizet_f_void.c"
/*
  @overload n()
  @return [Integer]

  This function returns the number of data so far added to the accumulator.
*/
static VALUE
rstat_n(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return SIZET2NUM(gsl_rstat_n(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload min
  @return [Float]

  This function returns the minimum value added to the accumulator.
*/
static VALUE
rstat_min(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_min(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload max
  @return [Float]

  This function returns the maximum value added to the accumulator.
*/
static VALUE
rstat_max(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_max(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload mean
  @return [Float]

  This function returns the mean of all data added to the accumulator,
defined as

\Hat\mu = (1/N) \sum x_i

*/
static VALUE
rstat_mean(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_mean(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload variance
  @return [Float]

  This function returns the variance of all data added to the accumulator,
defined as

\Hat\sigma^2 = (1/(N-1)) \sum (x_i - \Hat\mu)^2

*/
static VALUE
rstat_variance(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_variance(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload sd
  @return [Float]

  This function returns the standard deviation of all data added to the
accumulator, defined as the square root of the variance given above.
*/
static VALUE
rstat_sd(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_sd(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload skew
  @return [Float]

  This function returns the skewness of all data added to the accumulator,
defined as

skew = (1/N) \sum ((x_i - \Hat\mu)/\Hat\sigma)^3

*/
static VALUE
rstat_skew(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_skew(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload kurtosis
  @return [Float]

  This function returns the kurtosis of all data added to the accumulator,
defined as

kurtosis = ((1/N) \sum ((x_i - \Hat\mu)/\Hat\sigma)^4)  - 3

*/
static VALUE
rstat_kurtosis(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_kurtosis(w));
}


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload median
  @return [Float]

  This function returns an estimate of the median of the data added to
the accumulator.
*/
static VALUE
rstat_median(VALUE self)
{
    gsl_rstat_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_workspace, &rstat_data_type, w);

    return DBL2NUM(gsl_rstat_median(w));
}




#line 1 "../gen/tmpl/class.c"
/*
  class definition: Numo::GSL::Rstat::Quantile
*/

static VALUE cQuantile;

static void
rstat_quantile_free(void *ptr)
{
    gsl_rstat_quantile_free(ptr);
}

static size_t
rstat_quantile_memsize(const void *ptr)
{
    return sizeof(gsl_rstat_quantile_workspace);
}

static const rb_data_type_t rstat_quantile_data_type = {
    "Numo::GSL::Rstat::Quantile",
    {NULL, rstat_quantile_free, rstat_quantile_memsize,},
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};



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

#line 5 "../gen/tmpl/c_new_double.c"
/*
  @overload new(p)
  @param [Float] p

  allocate instance of Quantile class.

 This function allocates a workspace for the dynamic estimation of
p-quantiles, where p is between 0 and 1.
The median corresponds to p = 0.5. The size of the workspace
is O(1).
 */
static VALUE
rstat_quantile_s_new(VALUE self, VALUE p)
{
    gsl_rstat_quantile_workspace *w;
    w = gsl_rstat_quantile_alloc(NUM2DBL(p));
    if (!w) {
        rb_raise(rb_eNoMemError,"fail to allocate struct");
    }
    return TypedData_Wrap_Struct(cQuantile, &rstat_quantile_data_type, (void*)w);
}


#line 1 "../gen/tmpl/c_self_f_DFloat.c"
static void
iter_rstat_quantile_add(na_loop_t *const lp)
{
    size_t   i;
    char    *p1;
    ssize_t  s1;
    size_t  *idx1;
    double   x;
    gsl_rstat_quantile_workspace *w = (gsl_rstat_quantile_workspace*)(lp->opt_ptr);
    

    INIT_COUNTER(lp, i);
    INIT_PTR_IDX(lp, 0, p1, s1, idx1);

    if (idx1) {
        for (; i--;) {
            GET_DATA_INDEX(p1,idx1,double,x);
            gsl_rstat_quantile_add(x,w);
        }
    } else {
        for (; i--;) {
            GET_DATA_STRIDE(p1,s1,double,x);
            gsl_rstat_quantile_add(x,w);
        }
    }
}

/*
  @overload add(w)
  @param  [DFloat]   w
  @return [Quantile]  self

  This function updates the estimate of the p-quantile with
the new data point x.
*/
static VALUE
rstat_quantile_add(VALUE self, VALUE v1)
{
    gsl_rstat_quantile_workspace *w;
    ndfunc_arg_in_t ain[1] = {{cDF,0}};
    ndfunc_t ndf = {iter_rstat_quantile_add, FULL_LOOP, 1,0, ain,0};

    TypedData_Get_Struct(self, gsl_rstat_quantile_workspace, &rstat_quantile_data_type, w);

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


#line 1 "../gen/tmpl/c_double_f_void.c"
/*
  @overload get
  @return [Float]

  This function returns the current estimate of the p-quantile.
*/
static VALUE
rstat_quantile_get(VALUE self)
{
    gsl_rstat_quantile_workspace *w;

    TypedData_Get_Struct(self, gsl_rstat_quantile_workspace, &rstat_quantile_data_type, w);

    return DBL2NUM(gsl_rstat_quantile_get(w));
}


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

    


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

    /*
      Document-class: Numo::GSL::Rstat
      
    */
    {
    cRstat = rb_define_class_under(mG, "Rstat", rb_cObject);
    
    rb_undef_alloc_func(cRstat);
    rb_define_singleton_method(cRstat, "new", rstat_s_new, 0);
    rb_define_method(cRstat, "reset", rstat_reset, 0);
    rb_define_method(cRstat, "add", rstat_add, 1);
    rb_define_method(cRstat, "n", rstat_n, 0);
    rb_define_method(cRstat, "min", rstat_min, 0);
    rb_define_method(cRstat, "max", rstat_max, 0);
    rb_define_method(cRstat, "mean", rstat_mean, 0);
    rb_define_method(cRstat, "variance", rstat_variance, 0);
    rb_define_method(cRstat, "sd", rstat_sd, 0);
    rb_define_method(cRstat, "skew", rstat_skew, 0);
    rb_define_method(cRstat, "kurtosis", rstat_kurtosis, 0);
    rb_define_method(cRstat, "median", rstat_median, 0);
    rb_define_alias(cRstat, "size", "n");
    rb_define_alias(cRstat, "length", "n");
#line 10 "../gen/tmpl/init_class.c"
    }

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

    /*
      Document-class: Numo::GSL::Rstat::Quantile
      
    */
    {
    cQuantile = rb_define_class_under(cRstat, "Quantile", rb_cObject);
    
    rb_undef_alloc_func(cQuantile);
    rb_define_singleton_method(cQuantile, "new", rstat_quantile_s_new, 1);
    rb_define_method(cQuantile, "add", rstat_quantile_add, 1);
    rb_define_method(cQuantile, "get", rstat_quantile_get, 0);
#line 10 "../gen/tmpl/init_class.c"
    }
#line 41 "../gen/tmpl/lib.c"
}
