[SYSTEMDS-2688] Performance diag V2M operations (shallow data copy)

For diag V2M, we already output the sparse result in a space-efficient
CSR representation. However, for the special case of input vectors v
with nrow(v)==nnz(v) -- which often happens in practice -- we now use a
shallow copy of the data array because the CSR values array is
equivalent. Similarly, we now reuse a integer single seq(0,nrow(v)) for
both the pointer and column index arrays (by setting the available
logical size of the column index array to the nnz, this shared array is
logically truncated by the last entry).

For a scenario of 1000 diag V2M operations over a (? x 1) input vectors,
we got the following improvements:
* 1000 times diag(1M x 1): 9.1s -> 3.6s
* 1000 times diag(10M x 1): 81.9s -> 22.5s
diff --git a/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixReorg.java b/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixReorg.java
index c4c3425..891dfbe 100644
--- a/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixReorg.java
+++ b/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixReorg.java
@@ -1057,16 +1057,27 @@
 		if( out.sparse  ) { //SPARSE
 			if( SPARSE_OUTPUTS_IN_CSR ) {
 				int[] rptr = new int[in.rlen+1];
-				int[] cix = new int[(int)in.nonZeros];
-				double[] vals = new double[(int)in.nonZeros];
-				for( int i=0, pos=0; i<rlen; i++ ) {
-					double val = in.quickGetValue(i, 0);
-					if( val != 0 ) {
-						cix[pos] = i;
-						vals[pos] = val;
-						pos++;
+				int[] cix = null;
+				double[] vals = null;
+				//case a: fully dense vector
+				if( rlen == in.nonZeros && !in.sparse ) {
+					//reuse single seq for rptr and cix (cix truncated by 1)
+					rptr = cix = UtilFunctions.getSeqArray(0, rlen, 1);
+					vals = in.getDenseBlockValues(); //shallow copy
+				}
+				//case b: more general input
+				else {
+					cix = new int[(int)in.nonZeros];
+					vals = new double[(int)in.nonZeros];
+					for( int i=0, pos=0; i<rlen; i++ ) {
+						double val = in.quickGetValue(i, 0);
+						if( val != 0 ) {
+							cix[pos] = i;
+							vals[pos] = val;
+							pos++;
+						}
+						rptr[i+1]=pos;
 					}
-					rptr[i+1]=pos;
 				}
 				out.sparseBlock = new SparseBlockCSR(
 					rptr, cix, vals, (int)in.nonZeros);
diff --git a/src/test/java/org/apache/sysds/test/functions/privacy/PrivacyLineageTest.java b/src/test/java/org/apache/sysds/test/functions/privacy/PrivacyLineageTest.java
index 96a1f3e..d284e8b 100644
--- a/src/test/java/org/apache/sysds/test/functions/privacy/PrivacyLineageTest.java
+++ b/src/test/java/org/apache/sysds/test/functions/privacy/PrivacyLineageTest.java
@@ -77,7 +77,7 @@
 		finegrainedAssertions();
 	}
 
-	private void finegrainedAssertions(){
+	private static void finegrainedAssertions(){
 		String outputFineGrained = readDMLMetaDataValueCatchException("C", OUTPUT_DIR, DataExpression.FINE_GRAINED_PRIVACY);
 		Assert.assertEquals(
 			"{\"Private\":[[[0,0],[0,19]],[[1,0],[1,19]],[[2,0],[2,19]],[[3,0],[3,19]],[[4,0],[4,19]]],\"PrivateAggregation\":[]}",