text: /*
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 3 of the License, or
   * (at your option) any later version.
   *
   * Written (W) 2012 Heiko Strathmann
   */
  
  #include <shogun/lib/config.h>
  
  #include <shogun/features/DataGenerator.h>
  #include <shogun/mathematics/Math.h>
  #include <shogun/distributions/Gaussian.h>
  
  using namespace shogun;
  
  CDataGenerator::CDataGenerator() : CSGObject()
  {
  	init();
  }
  
  CDataGenerator::~CDataGenerator()
  {
  
  }
  
  void CDataGenerator::init()
  {
  }
  
  SGMatrix<float64_t> CDataGenerator::generate_checkboard_data(int32_t num_classes,
  		int32_t dim, int32_t num_points, float64_t overlap)
  {
  	int32_t points_per_class = num_points / num_classes;
  
  	int32_t grid_size = (int32_t ) CMath::ceil(CMath::sqrt((float64_t ) num_classes));
  	float64_t cell_size = (float64_t ) 1 / grid_size;
  	SGVector<float64_t> grid_idx(dim);
  	for (index_t i=0; i<dim; i++)
  		grid_idx[i] = 0;
  
  	SGMatrix<float64_t> points(dim+1, num_points);
  	int32_t points_idx = 0;
  	for (int32_t class_idx=0; class_idx<num_classes; class_idx++)
  	{
  		SGVector<float64_t> class_dim_centers(dim);
  		for (index_t i=0; i<dim; i++)
  			class_dim_centers[i] = (grid_idx[i] * cell_size + (grid_idx[i] + 1) * cell_size) / 2;
  
  		for (index_t p=points_idx; p<points_per_class+points_idx; p++)
  		{
  			for (index_t i=0; i<dim; i++)
  			{
  				do
  				{
  					points(i, p) = CMath::normal_random(class_dim_centers[i], cell_size*0.5);
  					if ((points(i, p)>(grid_idx[i]+1)*cell_size) ||
  							(points(i, p)<grid_idx[i]*cell_size))
  					{
  						if (!(CMath::random(0.0, 1.0)<overlap))
  							continue;
  					}
  					break;
  				} while (true);
  			}
  			points(dim, p) = class_idx;
  		}
  		points_idx += points_per_class;
  		for (index_t i=dim-1; i>=0; i--)
  		{
  			grid_idx[i]++;
  			if (grid_idx[i]>=grid_size)
  				grid_idx[i] = 0;
  			else
  				break;
  		}
  	}
  	return points;
  }
  
  SGMatrix<float64_t> CDataGenerator::generate_mean_data(index_t m,
  		index_t dim, float64_t mean_shift,
  		SGMatrix<float64_t> target)
  {
  	/* evtl. allocate space */
  	SGMatrix<float64_t> result=SGMatrix<float64_t>::get_allocated_matrix(
  			dim, 2*m, target);
  
  	/* fill matrix with normal data */
  	for (index_t i=0; i<2*m; ++i)
  	{
  		for (index_t j=0; j<dim; ++j)
  			result(j,i)=CMath::randn_double();
  
  		/* mean shift for second half */
  		if (i>=m)
  			result(0,i)+=mean_shift;
  	}
  
  	return result;
  }
  
  SGMatrix<float64_t> CDataGenerator::generate_sym_mix_gauss(index_t m,
  		float64_t d, float64_t angle, SGMatrix<float64_t> target)
  {
  	/* evtl. allocate space */
  	SGMatrix<float64_t> result=SGMatrix<float64_t>::get_allocated_matrix(
  			2, m, target);
  
  	/* rotation matrix */
  	SGMatrix<float64_t> rot=SGMatrix<float64_t>(2,2);
  	rot(0, 0)=CMath::cos(angle);
  	rot(0, 1)=-CMath::sin(angle);
  	rot(1, 0)=CMath::sin(angle);
  	rot(1, 1)=CMath::cos(angle);
  
  	/* generate signal in each dimension which is an equal mixture of two
  	 * Gaussians */
  	for (index_t i=0; i<m; ++i)
  	{
  		result(0,i)=CMath::randn_double() + (CMath::random(0, 1) ? d : -d);
  		result(1,i)=CMath::randn_double() + (CMath::random(0, 1) ? d : -d);
  	}
  
  	/* rotate result */
  	if (angle)
  		result=SGMatrix<float64_t>::matrix_multiply(rot, result);
  
  	return result;
  }
  #ifdef HAVE_LAPACK
  SGMatrix<float64_t> CDataGenerator::generate_gaussians(index_t m, index_t n, index_t dim)
  {
  	/* evtl. allocate space */
  	SGMatrix<float64_t> result =
  		SGMatrix<float64_t>::get_allocated_matrix(dim, n*m);
  
  	float64_t grid_distance = 5.0;
  	for (index_t i = 0; i < n; ++i)
  	{
  		SGVector<float64_t> mean(dim);
  		SGMatrix<float64_t> cov = SGMatrix<float64_t>::create_identity_matrix(dim, 1.0);
  
  		mean.zero();
  		for (index_t k = 0; k < dim; ++k)
  		{
  			mean[k] = (i+1)*grid_distance;
  			if (k % (i+1) == 0)
  				mean[k] *= -1;
  		}
  		CGaussian* g = new CGaussian(mean, cov, DIAG);
  		for (index_t j = 0; j < m; ++j)
  		{
  			SGVector<float64_t> v = g->sample();
  			memcpy((result.matrix+j*result.num_rows+i*m*dim), v.vector, dim*sizeof(float64_t));
  			SG_FREE(v.vector);
  		}
  
  		SG_UNREF(g);
  	}
  
  	return result;
  }
  #endif /* HAVE_LAPACK */
  