/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


package org.apache.sysds.runtime.matrix.data;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.stream.LongStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.math3.random.Well1024a;
import org.apache.sysds.hops.DataGenOp;
import org.apache.sysds.runtime.DMLRuntimeException;
import org.apache.sysds.runtime.controlprogram.parfor.util.IDSequence;
import org.apache.sysds.runtime.data.DenseBlock;
import org.apache.sysds.runtime.data.SparseBlock;
import org.apache.sysds.runtime.util.CommonThreadPool;
import org.apache.sysds.runtime.util.NormalPRNGenerator;
import org.apache.sysds.runtime.util.PRNGenerator;
import org.apache.sysds.runtime.util.PoissonPRNGenerator;
import org.apache.sysds.runtime.util.UniformPRNGenerator;
import org.apache.sysds.runtime.util.UtilFunctions;

public class LibMatrixDatagen 
{
	private static final Log LOG = LogFactory.getLog(LibMatrixDatagen.class.getName());
	private static final long PAR_NUMCELL_THRESHOLD = 512*1024; //Min 500k elements
	
	private static IDSequence _seqRandInput = new IDSequence(); 
	
	private LibMatrixDatagen() {
		//prevent instantiation via private constructor
	}

	public static boolean isShortcutRandOperation( double min, double max, double sparsity, RandomMatrixGenerator.PDF pdf )
	{
		return pdf == RandomMatrixGenerator.PDF.UNIFORM
			   && (  ( min == 0.0 && max == 0.0 ) //all zeros
				   ||( sparsity==1.0d && min == max )); //equal values
	}

	public static double updateSeqIncr(double seq_from, double seq_to, double seq_incr) {
		//handle default 1 to -1 for special case of from>to
		return (seq_from>seq_to && seq_incr==1)? -1 : seq_incr;
	}

	public static String generateUniqueSeedPath( String basedir ) {
		return basedir + "tmp" + _seqRandInput.getNextID() + ".randinput";
	}
	
	/**
	 * A matrix of random numbers is generated by using multiple seeds, one for each 
	 * block. Such block-level seeds are produced via Well equidistributed long-period linear 
	 * generator (Well1024a). For a given seed, this function sets up the block-level seeds.
	 * 
	 * This function is invoked from both CP (RandCPInstruction.processInstruction()) 
	 * as well as MR (RandMR.java while setting up the Rand job).
	 * 
	 * @param seed seed for random generator
	 * @return Well1024a pseudo-random number generator
	 */
	public static Well1024a setupSeedsForRand(long seed) 
	{
		long lSeed = (seed == DataGenOp.UNSPECIFIED_SEED ? DataGenOp.generateRandomSeed() : seed);
		LOG.trace("Setting up RandSeeds with initial seed = "+lSeed+".");

		Random random=new Random(lSeed);
		Well1024a bigrand=new Well1024a();
		//random.setSeed(lSeed);
		int[] seeds=new int[32];
		for(int s=0; s<seeds.length; s++)
			seeds[s]=random.nextInt();
		bigrand.setSeed(seeds);
		
		return bigrand;
	}

	@Deprecated
	public static LongStream computeNNZperBlock(long nrow, long ncol, int blen, double sparsity) {
		long lnumBlocks = (long) (Math.ceil((double)nrow/blen) * Math.ceil((double)ncol/blen));
		
		//sanity check max number of blocks (before cast to avoid overflow)
		if ( lnumBlocks > Integer.MAX_VALUE ) {
			throw new DMLRuntimeException("A random matrix of size [" + nrow + "," + ncol + "] can not be created. "
					+ "Number of blocks ("+lnumBlocks+") exceeds the maximum integer size. Try to increase the block size.");
		}

		int numBlocks = (int) lnumBlocks;
		int numColBlocks = (int) Math.ceil((double)ncol/blen);
		long nnz = (long) Math.ceil (nrow * (ncol*sparsity));
		
		if( nnz < numBlocks ) {
			//#1: ultra-sparse random number generation
			//nnz per block: 1 with probability P = nnz/numBlocks, 0 with probability 1-P
			//(note: this is an unbiased generator that, however, will never generate more than 
			//one non-zero per block, but it uses weights to account for different block sizes)
			double P = (double) nnz / numBlocks;
			Random runif = new Random(System.nanoTime());
			return LongStream.range(0, numBlocks).map( i -> {
				double lP = P / (blen*blen) *
					UtilFunctions.computeBlockSize(nrow, 1 + i / numColBlocks, blen) *
					UtilFunctions.computeBlockSize(ncol, 1 + i % numColBlocks, blen);
				return (runif.nextDouble() <= lP) ? 1 : 0;
			});
		}
		else {
			//#2: dense/sparse random number generation
			//nnz per block: lrlen * lclen * sparsity (note: this is a biased generator 
			//that might actually create fewer but never more non zeros than expected)
			return LongStream.range(0, numBlocks).map( i -> (long)(sparsity * 
				UtilFunctions.computeBlockSize(nrow, 1 + i / numColBlocks, blen) *
				UtilFunctions.computeBlockSize(ncol, 1 + i % numColBlocks, blen)));
		}
	}

    public static RandomMatrixGenerator createRandomMatrixGenerator(String pdfStr, int r, int c, int blen, double sp, double min, double max, String distParams) {
		RandomMatrixGenerator.PDF pdf = RandomMatrixGenerator.PDF.valueOf(pdfStr.toUpperCase());
		RandomMatrixGenerator rgen = null;
		switch (pdf) {
			case UNIFORM:
				rgen = new RandomMatrixGenerator(pdf, r, c, blen, sp, min, max);
				break;
			case NORMAL:
				rgen = new RandomMatrixGenerator(pdf, r, c, blen, sp);
				break;
			case POISSON:
				double mean = Double.NaN;
				try {
					mean = Double.parseDouble(distParams);
				} catch (NumberFormatException e) {
					throw new DMLRuntimeException("Failed to parse Poisson distribution parameter: " + distParams);
				}
				rgen = new RandomMatrixGenerator(pdf, r, c, blen, sp, min, max, mean);
				break;
			default:
				throw new DMLRuntimeException("Unsupported probability distribution \"" + pdf + "\" in rand() -- it must be one of \"uniform\", \"normal\", or \"poisson\"");
		}
		return rgen;
	}
	
	/**
	 * Function to generate a matrix of random numbers. This is invoked both
	 * from CP as well as from MR. In case of CP, it generates an entire matrix
	 * block-by-block. A <code>bigrand</code> is passed so that block-level
	 * seeds are generated internally. In case of MR, it generates a single
	 * block for given block-level seed <code>bSeed</code>.
	 * 
	 * When pdf="uniform", cell values are drawn from uniform distribution in
	 * range <code>[min,max]</code>.
	 * 
	 * When pdf="normal", cell values are drawn from standard normal
	 * distribution N(0,1). The range of generated values will always be
	 * (-Inf,+Inf).
	 * 
     * @param out output matrix block
     * @param rgen random matrix generator
     * @param bigrand Well1024a pseudo-random number generator
     * @param bSeed seed for random generator
     */
	public static void generateRandomMatrix( MatrixBlock out, RandomMatrixGenerator rgen, Well1024a bigrand, long bSeed ) {
		boolean invokedFromCP = (bigrand != null);
		int rows = rgen._rows;
		int cols = rgen._cols;
		int blen = rgen._blocksize;
		double sparsity = rgen._sparsity;
		
		// sanity check valid dimensions and sparsity
		checkMatrixDimensionsAndSparsity(rows, cols, sparsity);
		
		/*
		 * Setup min and max for distributions other than "uniform". Min and Max
		 * are set up in such a way that the usual logic of
		 * (max-min)*prng.nextDouble() is still valid. This is done primarily to
		 * share the same code across different distributions.
		 */
		double min = rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM ? rgen._min : 0;
		double max = rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM ? rgen._max : 1;
		
		// Special case shortcuts for efficiency
		if ( rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM) {
			if ( min == 0.0 && max == 0.0 || sparsity == 0 ) { //all zeros
				out.reset(rows, cols, true);
				return;
			} 
			else if( sparsity==1.0d && (min == max  //equal values, dense
					|| (Double.isNaN(min) && Double.isNaN(max))) ) { //min == max == NaN
				out.reset(rows, cols, min); 
				return;
			}
		}
		
		// Determine the sparsity of output matrix
		// if invoked from CP: estimated NNZ is for entire matrix (nnz=0, if 0 initialized)
		// if invoked from MR: estimated NNZ is for one block
		final long estnnz = (long) Math.ceil((min==0.0 && max==0.0) ? 0 : sparsity*rows*cols);
		boolean lsparse = MatrixBlock.evalSparseFormatInMemory( rows, cols, estnnz );
		out.reset(rows, cols, lsparse, estnnz);
		
		// allocate memory, incl sparse row allocation if safe
		out.allocateBlock();
		
		//prepare rand internal parameters
		int nrb = (int) Math.ceil((double)rows/blen);
		int ncb = (int) Math.ceil((double)cols/blen);
		long[] seeds = invokedFromCP ? generateSeedsForCP(bigrand, nrb, ncb) : null;
		
		genRandomNumbers(invokedFromCP, 0, nrb, 0, ncb, out, rgen, bSeed, seeds);
		
		out.recomputeNonZeros();
	}
	
	/**
	 * Function to generate a matrix of random numbers. This is invoked both
	 * from CP as well as from MR. In case of CP, it generates an entire matrix
	 * block-by-block. A <code>bigrand</code> is passed so that block-level
	 * seeds are generated internally. In case of MR, it generates a single
	 * block for given block-level seed <code>bSeed</code>.
	 * 
	 * When pdf="uniform", cell values are drawn from uniform distribution in
	 * range <code>[min,max]</code>.
	 * 
	 * When pdf="normal", cell values are drawn from standard normal
	 * distribution N(0,1). The range of generated values will always be
	 * (-Inf,+Inf).
	 * 
	 * 
	 * @param out output matrix block
	 * @param rgen random matrix generator
	 * @param bigrand Well1024a pseudo-random number generator
	 * @param bSeed seed for random generator
	 * @param k ?
	 */
	public static void generateRandomMatrix( MatrixBlock out, RandomMatrixGenerator rgen, Well1024a bigrand, long bSeed, int k ) {
		int rows = rgen._rows;
		int cols = rgen._cols;
		int blen = rgen._blocksize;
		double sparsity = rgen._sparsity;
		
		//sanity check valid dimensions and sparsity
		checkMatrixDimensionsAndSparsity(rows, cols, sparsity);
		
		/*
		 * Setup min and max for distributions other than "uniform". Min and Max
		 * are set up in such a way that the usual logic of
		 * (max-min)*prng.nextDouble() is still valid. This is done primarily to
		 * share the same code across different distributions.
		 */
		double min = rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM ? rgen._min : 0;
		double max = rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM ? rgen._max : 1;
		
		//determine the sparsity of output matrix (multi-threaded always invoked from CP):
		//estimated NNZ is for entire matrix (nnz=0, if 0 initialized)
		final long estnnz = ((min==0.0 && max==0.0) ? 0 : (long)(sparsity * rows * cols));
		boolean lsparse = MatrixBlock.evalSparseFormatInMemory( rows, cols, estnnz );
		
		//fallback to sequential if single rowblock or too few cells or if MatrixBlock is not thread safe
		if( k<=1 || (rows <= blen && lsparse) || (long)rows*cols < PAR_NUMCELL_THRESHOLD 
			|| !MatrixBlock.isThreadSafe(lsparse) ) {
			generateRandomMatrix(out, rgen, bigrand, bSeed);
			return;
		}

		//special case shortcuts for efficiency
		if ( rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM) {
			if ( min == 0.0 && max == 0.0 ) { //all zeros
				out.reset(rows, cols, false);
				return;
			} 
			else if( sparsity==1.0d && min == max ) { //equal values
				out.reset(rows, cols, min); 
				return;
			}
		}
		
		// allocate memory, incl sparse row allocation if safe
		out.reset(rows, cols, lsparse, estnnz);
		out.allocateBlock();
		
		int nrb = (int) Math.ceil((double)rows/blen);
		int ncb = (int) Math.ceil((double)cols/blen);
		
		//default: parallelization over row blocks, fallback to parallelization
		//over column blocks if possible and necessary (higher degree of par)
		boolean parcol = (!out.sparse && nrb<k && ncb>nrb);
		int parnb = parcol ? ncb : nrb;
		
		//generate seeds independent of parallelizations
		long[] seeds = generateSeedsForCP(bigrand, nrb, ncb);
		long nnz = 0;
		try {
			ExecutorService pool = CommonThreadPool.get(k);
			ArrayList<RandTask> tasks = new ArrayList<>();
			int blklen = ((int)(Math.ceil((double)parnb/k)));
			for( int i=0; i<k & i*blklen<parnb; i++ ) {
				int rl = parcol ? 0 : i*blklen; 
				int ru = parcol ? nrb : Math.min((i+1)*blklen, parnb);
				int cl = parcol ? i*blklen : 0; 
				int cu = parcol ? Math.min((i+1)*blklen, parnb) : ncb;
				long[] lseeds = sliceSeedsForCP(seeds, rl, ru, cl, cu, nrb, ncb);
				tasks.add(new RandTask(rl, ru, cl, cu, out, rgen, bSeed, lseeds) );
			}
			//execute, handle errors, and aggregate nnz
			List<Future<Long>> ret = pool.invokeAll(tasks);
			pool.shutdown();
			for(Future<Long> rc : ret) 
				nnz += rc.get();
		} 
		catch (Exception e) {
			throw new DMLRuntimeException(e);
		}
		
		out.setNonZeros(nnz);
	}
	
	/**
	 * Method to generate a sequence according to the given parameters. The
	 * generated sequence is always in dense format.
	 * 
	 * Both end points specified <code>from</code> and <code>to</code> must be
	 * included in the generated sequence i.e., [from,to] both inclusive. Note
	 * that, <code>to</code> is included only if (to-from) is perfectly
	 * divisible by <code>incr</code>.
	 * 
	 * For example, seq(0,1,0.5) generates (0.0 0.5 1.0) 
	 *      whereas seq(0,1,0.6) generates (0.0 0.6) but not (0.0 0.6 1.0)
	 * 
	 * @param out output matrix block
	 * @param from lower end point
	 * @param to upper end point
	 * @param incr increment value
	 */
	public static void generateSequence(MatrixBlock out, double from, double to, double incr) {
		//check valid increment value
		if( (from > to && incr > 0) || incr == 0 )
			throw new DMLRuntimeException("Wrong sequence increment: from="+from+", to="+to+ ", incr="+incr);
		
		//prepare output matrix
		int rows = (int) UtilFunctions.getSeqLength(from, to, incr);
		int cols = 1; // sequence vector always dense
		out.reset(rows, cols, false);
		out.allocateDenseBlock();
	
		//compute sequence data
		double[] c = out.getDenseBlockValues();
		double cur = from;
		for(int i=0; i < rows; i++) {
			c[i] = cur;
			cur += incr;
		}
		
		out.recomputeNonZeros();
	}

	/**
     * Generates a sample of size <code>size</code> from a range of values [1,range].
     * <code>replace</code> defines if sampling is done with or without replacement.
	 * 
	 * @param out output matrix block
	 * @param range range upper bound
	 * @param size sample size
	 * @param replace if true, sample with replacement
	 * @param seed seed for random generator
	 */
	public static void generateSample(MatrixBlock out, long range, int size, boolean replace, long seed) {
		//set meta data and allocate dense block
		out.reset(size, 1, false);
		double[] a = out.allocateBlock().getDenseBlockValues();
		seed = (seed == -1 ? System.nanoTime() : seed);
		
		if ( !replace ) 
		{
			// reservoir sampling
			for(int i=0; i < size; i++) 
				a[i] = i + 1;
			
			Random rand = new Random(seed);
			for(int i=size+1; i <= range; i++) {
				if(rand.nextInt(i) < size)
					a[rand.nextInt(size)] = i;
			}
			
			// randomize the sample (Algorithm P from Knuth's ACP)
			// needed especially when the difference between range and size is small)
			for( int i = 0; i < size-1; i++ ) {
				//generate index in i <= j < size
				int j = rand.nextInt(size - i) + i;
				//swap i^th and j^th entry
				double tmp = a[i];
				a[i] = a[j];
				a[j] = tmp;
			}
		}
		else {
			Random r = new Random(seed);
			for(int i=0; i < size; i++) 
				a[i] = 1+nextLong(r, range);
		}
		
		out.setNonZeros(size);
		out.examSparsity();
	}

	private static long[] generateSeedsForCP(Well1024a bigrand, int nrb, int ncb)
	{
		int numBlocks = nrb * ncb;
		long[] seeds = new long[numBlocks];
		for( int l = 0; l < numBlocks; l++ )
			seeds[l] = bigrand.nextLong();
		
		return seeds;
	}

	private static long[] sliceSeedsForCP(long[] seeds, int rl, int ru, int cl, int cu, int nrb, int ncb)
	{
		int numBlocks = (ru-rl) * (cu-cl);
		long[] lseeds = new long[numBlocks];
		for( int i = rl; i < ru; i++ )
			System.arraycopy(seeds, i*ncb+cl, lseeds, (i-rl)*(cu-cl), cu-cl);
		
		return lseeds;
	}

	private static void genRandomNumbers(boolean invokedFromCP, int rl, int ru, int cl, int cu, MatrixBlock out, RandomMatrixGenerator rgen, long bSeed, long[] seeds) {
		int rows = rgen._rows;
		int cols = rgen._cols;
		int blen = rgen._blocksize;
		double sparsity = rgen._sparsity;
		double min = rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM ? rgen._min : 0;
		double max = rgen._pdf == RandomMatrixGenerator.PDF.UNIFORM ? rgen._max : 1;
		double range = max - min;
		int clen = out.clen;
		int estnnzRow = (int)(sparsity * cols);
		
		int nrb = (int) Math.ceil((double)rows/blen);
		int ncb = (int) Math.ceil((double)cols/blen);
		int counter = 0;

		// Setup Pseudo Random Number Generator for cell values based on 'pdf'.
		PRNGenerator valuePRNG = rgen._valuePRNG;
		if (valuePRNG == null) {
			switch (rgen._pdf) {
				case UNIFORM: valuePRNG = new UniformPRNGenerator(); break;
				case NORMAL:  valuePRNG = new NormalPRNGenerator(); break;
				case POISSON: valuePRNG = new PoissonPRNGenerator(); break;
				default:
					throw new DMLRuntimeException("Unsupported distribution function for Rand: " + rgen._pdf);
			}
		}
		
		//preallocate prng for non-zero entries
		UniformPRNGenerator nnzPRNG = new UniformPRNGenerator(0);
		
		//preallocate sparse rows if safe
		if( out.sparse && estnnzRow > 0 && cl==0 && cu==ncb )
			for( int i=rl*blen; i<Math.min(ru*blen, rows); i++ )
				out.sparseBlock.allocate(i, estnnzRow);
		
		// loop through row-block indices
		for(int rbi = rl; rbi < ru; rbi++) {
			int blockrows = (rbi == nrb-1 ? (rows-rbi*blen) : blen);
			int rowoffset = rbi*blen;

			// loop through column-block indices
			for(int cbj = cl; cbj < cu; cbj++) {
				int blockcols = (cbj == ncb-1 ? (cols-cbj*blen) : blen);
				int coloffset = cbj*blen;
				
				// select the appropriate block-level seed and init PRNG
				long seed = !invokedFromCP ?  bSeed : seeds[counter++]; 
				valuePRNG.setSeed(seed);
				
				// Initialize the PRNGenerator for determining cells that contain a non-zero value
				// Note that, "pdf" parameter applies only to cell values and the individual cells 
				// are always selected uniformly at random.
				nnzPRNG.setSeed(seed);
				
				// block-level sparsity, which may differ from overall sparsity in the matrix.
				// (e.g., border blocks may fall under skinny matrix turn point, in CP this would be 
				// irrelevant but we need to ensure consistency with MR)
				boolean localSparse = MatrixBlock.evalSparseFormatInMemory(
					blockrows, blockcols, (long)(sparsity*blockrows*blockcols));
				if ( localSparse ) {
					SparseBlock c = out.sparseBlock;
					// Prob [k-1 zeros before a nonzero] = Prob [k-1 < log(uniform)/log(1-p) < k] = p*(1-p)^(k-1), where p=sparsity
					double log1mp = Math.log(1-sparsity);
					int idx = 0;  // takes values in range [1, blen*blen] (both ends including)
					long blocksize = blockrows*blockcols;
					while(idx < blocksize) {
						//compute skip to next index
						idx = idx + (int) Math.ceil(Math.log(nnzPRNG.nextDouble())/log1mp);
						if ( idx > blocksize) break;
						// translate idx into (r,c) within the block
						int rix = (idx-1)/blockcols;
						int cix = (idx-1)%blockcols;
						double val = min + (range * valuePRNG.nextDouble());
						c.allocate(rowoffset+rix, estnnzRow, clen);
						c.append(rowoffset+rix, coloffset+cix, val);
					}
				}
				else {
					if (sparsity == 1.0) {
						DenseBlock c = out.getDenseBlock();
						for(int ii = 0; ii < blockrows; ii++) {
							double[] cvals = c.values(rowoffset+ii);
							int cix = c.pos(rowoffset+ii, coloffset);
							for(int jj = 0; jj < blockcols; jj++)
								cvals[cix+jj] = min + (range * valuePRNG.nextDouble());
						}
					}
					else {
						if (out.sparse ) {
							/* This case evaluated only when this function is invoked from CP. 
							 * In this case:
							 *     sparse=true -> entire matrix is in sparse format and hence denseBlock=null
							 *     localSparse=false -> local block is dense, and hence on MR side a denseBlock will be allocated
							 * i.e., we need to generate data in a dense-style but set values in sparseRows
							 * 
							 */
							// In this case, entire matrix is in sparse format but the current block is dense
							SparseBlock c = out.sparseBlock;
							for(int ii=0; ii < blockrows; ii++) {
								for(int jj=0; jj < blockcols; jj++) {
									if(nnzPRNG.nextDouble() <= sparsity) {
										double val = min + (range * valuePRNG.nextDouble());
										c.allocate(ii+rowoffset, estnnzRow, clen);
										c.append(ii+rowoffset, jj+coloffset, val);
									}
								}
							}
						}
						else {
							DenseBlock c = out.getDenseBlock();
							for(int ii = 0; ii < blockrows; ii++) {
								double[] cvals = c.values(rowoffset+ii);
								int cix = c.pos(rowoffset+ii, coloffset);
								for(int jj = 0; jj < blockcols; jj++)
									if(nnzPRNG.nextDouble() <= sparsity)
										cvals[cix+jj] =  min + (range * valuePRNG.nextDouble());
							}
						}
					}
				} // sparse or dense 
			} // cbj
		} // rbi
	}

	private static void checkMatrixDimensionsAndSparsity(int rows, int cols, double sp) {
		if( rows < 0 || cols < 0 || sp < 0 || sp > 1)
			throw new DMLRuntimeException("Invalid matrix characteristics: "+rows+"x"+cols+", "+sp);
	}
	
	// modified version of java.util.nextInt
	private static long nextLong(Random r, long n) {
		if (n <= 0)
			throw new IllegalArgumentException("n must be positive");
		long bits, val;
		do {
			bits = (r.nextLong() << 1) >>> 1;
			val = bits % n;
		} while (bits - val + (n-1) < 0L);
		return val;
	}

	private static class RandTask implements Callable<Long> 
	{
		private int _rl = -1;
		private int _ru = -1;
		private int _cl = -1;
		private int _cu = -1;
		private MatrixBlock _out = null;
		private RandomMatrixGenerator _rgen = new RandomMatrixGenerator();
		private long _bSeed = 0;
		private long[] _seeds = null;
		
		public RandTask(int rl, int ru, int cl, int cu, MatrixBlock out, RandomMatrixGenerator rgen, long bSeed, long[] seeds) {
			_rl = rl;
			_ru = ru;
			_cl = cl;
			_cu = cu;
			_out = out;
			_rgen.init(rgen._pdf, rgen._rows, rgen._cols, rgen._blocksize, rgen._sparsity, rgen._min, rgen._max, rgen._mean);
			_bSeed = bSeed;
			_seeds = seeds;
		}

		@Override
		public Long call() {
			//execute rand operations (with block indexes)
			genRandomNumbers(true, _rl, _ru, _cl, _cu, _out, _rgen, _bSeed, _seeds);
			//thread-local maintenance of non-zero values
			int blen =_rgen._blocksize;
			return _out.recomputeNonZeros(_rl*blen, Math.min(_ru*blen,_rgen._rows)-1,
				_cl*blen, Math.min(_cu*blen, _rgen._cols)-1);
		}
	}
}
