docs: public static DMatrixSparseCSC triangleLower(int dimen , int hessenberg, int nz_total,
                                                   double min , double max , Random rand ) {
  
          // number of elements which are along the diagonal
          int diag_total = dimen-hessenberg;
  
          // pre compute element count in each row
          int rowStart[] = new int[dimen];
          int rowEnd[] = new int[dimen];
          // diagonal is manditory and these indexes refer to a triangle -1 dimension
          int N = 0;
          for (int i = 0; i < dimen; i++) {
              if( i < dimen-1+hessenberg) rowStart[i] = N;
              N += i < hessenberg ? dimen : dimen-1-i+hessenberg;;
              if( i < dimen-1+hessenberg) rowEnd[i] = N;
          }
          N += dimen-hessenberg;
  
          // contrain the total number of non-zero elements
          nz_total = Math.min(N,nz_total);
          nz_total = Math.max(diag_total,nz_total);
  
          // number of elements which are not the diagonal elements
          int off_total = nz_total-diag_total;
  
          int[] selected = UtilEjml.shuffled(N-diag_total, off_total, rand);
          Arrays.sort(selected,0,off_total);
  
          DMatrixSparseCSC L = new DMatrixSparseCSC(dimen,dimen,nz_total);
  
          // compute the number of elements in each column
          int hist[] = new int[ dimen ];
          int s_index = 0;
          for (int col = 0; col < dimen; col++) {
              if( col >= hessenberg )
                  hist[col]++;
              while( s_index < off_total && selected[s_index] < rowEnd[col]  ) {
                  hist[col]++;
                  s_index++;
              }
          }
  
          // define col_idx
          L.histogramToStructure(hist);
  
          int nz_index = 0;
          s_index = 0;
          for (int col = 0; col < dimen; col++) {
              int offset = col >= hessenberg ? col - hessenberg+1 : 0;
  
              // assign the diagonal element a value
              if( col >= hessenberg ) {
                  L.nz_rows[nz_index] = col-hessenberg;
                  L.nz_values[nz_index++] = rand.nextDouble() * (max - min) + min;
              }
  
              // assign the other elements values
              while( s_index < off_total && selected[s_index] < rowEnd[col]  ) {
                  // the extra + 1 is because random elements were not allowed along the diagonal
                  int row = selected[s_index++] - rowStart[col] + offset;
  
                  L.nz_rows[nz_index] = row;
                  L.nz_values[nz_index++] = rand.nextDouble()*(max-min)+min;
              }
          }
  
          return L;
      }