/* This file is part of the Neper software package. */
/* Copyright (C) 2003-2014, Romain Quey. */
/* See the COPYING file in the top-level directory. */

#include"net_seed_weight_.h"

void
net_seed_weight_rand_distrib (char *weight, char ***pdistribf,
			      char ***pdistribp, double **pdistribw,
			      int *pdistribqty)
{
  int i, qty;
  char **distrib = NULL;

  ut_string_separate (weight, "+", &distrib, pdistribqty);
  (*pdistribw) = ut_alloc_1d (*pdistribqty);
  (*pdistribf) = ut_alloc_1d_pchar (*pdistribqty);
  (*pdistribp) = ut_alloc_1d_pchar (*pdistribqty);

  for (i = 0; i < *pdistribqty; i++)
  {
    char **tmp = NULL;
    ut_string_separate (distrib[i], "*", &tmp, &qty);
    (*pdistribf)[i] = ut_alloc_1d_char (strlen (distrib[i]) + 1);
    (*pdistribp)[i] = ut_alloc_1d_char (strlen (distrib[i]) + 1);
    if (qty == 1)
      (*pdistribw)[i] = 1;
    else if (qty == 2)
      sscanf (tmp[0], "%lf", &((*pdistribw)[i]));
    else
      abort ();

    ut_string_fnr (tmp[qty - 1], '(', ' ');
    ut_string_fnr (tmp[qty - 1], ',', ' ');
    ut_string_fnr (tmp[qty - 1], ')', ' ');
    sscanf (tmp[qty - 1], "%s", (*pdistribf)[i]);
    strcpy ((*pdistribp)[i], tmp[qty - 1] + strlen ((*pdistribf)[i]) + 1);
    (*pdistribp)[i][strlen ((*pdistribp)[i]) - 1] = '\0';

    ut_free_2d_char (tmp, qty);
  }
  ut_array_1d_scale (*pdistribw, *pdistribqty,
		     1. / ut_array_1d_sum (*pdistribw, *pdistribqty));

  ut_free_2d_char (distrib, qty);

  for (i = 0; i < *pdistribqty; i++)
    ut_print_message (0, 4, "`%s' with parms `%s' (%g).\n", (*pdistribf)[i],
		      (*pdistribp)[i], (*pdistribw)[i]);

  return;
}

void
net_seed_weight_rand_seeddistrib (struct SEEDSET GSet, double *distribw,
				  int distribqty, int **pseedd)
{
  int i;
  double *distribwcpy = ut_alloc_1d (distribqty);

  (*pseedd) = ut_alloc_1d_int (GSet.N + 1);

  // turning the weights into cumulative weights. 
  ut_array_1d_memcpy (distribwcpy, distribqty, distribw);
  for (i = 1; i < distribqty; i++)
    distribwcpy[i] += distribwcpy[i - 1];
  distribwcpy[distribqty - 1] = 1;	// gets rid of roundoff errors

  double *tmp = ut_alloc_1d (GSet.N + 1);
  int *pos = ut_alloc_1d_int (GSet.N + 1);

  gsl_rng *r = gsl_rng_alloc (gsl_rng_ranlxd2);
  gsl_rng_set (r, GSet.Random - 2);

  for (i = 1; i <= GSet.N; i++)
    tmp[i] = gsl_rng_uniform (r);
  ut_array_1d_sort_index (tmp + 1, GSet.N, pos + 1);
  ut_array_1d_int_addval (pos + 1, GSet.N, 1, pos + 1);

  int d = 0;
  for (i = 1; i <= GSet.N; i++)
  {
    if (i > ut_num_d2ri (GSet.N * distribwcpy[d]))
      d++;

    (*pseedd)[pos[i]] = d;
  }

  ut_free_1d (distribwcpy);
  gsl_rng_free (r);

  return;
}
