/* File: gen.c
   Generate a random matrix.
   Result is delivered to standard output.

   Usage: gen rows columns entries

   Example: To produce a 5x10 matrix with 12 non-zero 
   entries, use the command:

   gen 5 10 12 >test.txt

*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>

typedef struct {
   int row ;
   int col ;
} entry ;


main(int argc, char *argv[]) {
 
int rows, columns, entries ;
int i, j, k, n, r, repeated ;
long int seed ;
double value ;
entry *previous ; 

   
   /* Sanity check */
   if (argc != 4) {
      fprintf(stderr, "Usage: gen rows columns entries\n") ;
      exit(1) ;
   }

   /* Get arguments */
   r = sscanf(argv[1],"%d", &rows) ;
   if (r != 1) {
      fprintf(stderr, "%s not an integer!\n", argv[1]) ;
      exit(1) ;
   }

   r = sscanf(argv[2],"%d", &columns) ;
   if (r != 1) {
      fprintf(stderr, "%s not an integer!\n", argv[1]) ;
      exit(1) ;
   }

   r = sscanf(argv[3],"%d", &entries) ;
   if (r != 1) {
      fprintf(stderr, "%s not an integer!\n", argv[1]) ;
      exit(1) ;
   }

   fprintf(stderr, "Rows: %d Columns: %d Entires: %d\n",
      rows, columns, entries) ;


   /* Does the input make sense? */

   if (rows < 1 || columns < 1) {
      fprintf(stderr, "Number of rows and columns must be positive\n") ;
      exit(1) ;
   }

   if (entries > rows * columns) {
      fprintf(stderr, "Error: Too many entries!\n") ;
      exit(1) ;
   }

   if (entries > 0.3*rows*columns) {
      fprintf(stderr, "Warning: this matrix is not very sparse!\n") ;
   }
   
   if (entries > 20000) {
      fprintf(stderr, "Warning: this could take a while...\n") ;
   }

   /* Set random seed to time in seconds since 01/01/70 */
   seed = (long) time(NULL) ;
   fprintf(stderr, "Set random seed to %ld\n", seed) ;
   srand48(seed) ;


   /* Initialization for main loop */
   n = 0 ;
   previous = malloc(entries * sizeof(entry)) ;
   if (previous == NULL) {
      fprintf(stderr, "Could not allocate that much memory\n!") ;
      exit(1) ;
   }

   /* Print row and column info */
   printf("%d %d\n", rows, columns) ;

   /* Main loop */
   while (n < entries) {
      /* Make a random entry with 0.01 <= value <= 200.01 */
      i = ( (int) lrand48() ) % rows ;
      j = ( (int) lrand48() ) % columns ;
      value =  ( ( ( (int) lrand48() ) % 20000 ) + 1.0) / 100.0 ;

      /* Make sure we don't generate two values for the same entry */
      repeated = 0 ;
      for (k = 0 ; k < n ; k++) {
         if ( (previous[k].row == i) && (previous[k].col == j) ) {
            repeated = 1 ;
            break ;
         }
      }
      if (repeated) continue ;

      /* output random entry */
      printf("%d %d %lf\n", i, j, value) ;

      /* remember that this entry was used */
      previous[n].row = i ;
      previous[n].col = j ;
      n++ ;
   }
}
