This is an automated email from the ASF dual-hosted git repository.

leerho pushed a commit to branch remove_duplicate_doubles_sorted_views
in repository https://gitbox.apache.org/repos/asf/datasketches-java.git

commit 5f8fc5c22dcaf2dfeb30f68b97d872e711237f94
Author: Lee Rhodes <[email protected]>
AuthorDate: Wed Mar 20 16:38:22 2024 -0700

    Removed the duplicate Doubles Sorted Views between KLL and Classic
    quantiles.
    
    This had a rippling effect across a number of classes.
---
 .../apache/datasketches/kll/KllDoublesSketch.java  | 167 ++++++++--
 .../kll/KllDoublesSketchSortedView.java            | 129 +-------
 .../apache/datasketches/kll/KllItemsSketch.java    |   3 +-
 .../quantiles/CompactDoublesSketch.java            |   2 +-
 .../quantiles/DirectDoublesSketchAccessor.java     |   1 +
 .../quantiles/DirectUpdateDoublesSketch.java       |   2 +-
 .../quantiles/DoublesArrayAccessor.java            |   3 +-
 .../quantiles/DoublesBufferAccessor.java           |   4 +-
 .../datasketches/quantiles/DoublesSketch.java      | 250 ++++++++++++++-
 .../quantiles/DoublesSketchSortedView.java         | 354 ---------------------
 .../datasketches/quantiles/DoublesUnionImpl.java   |   6 +-
 .../quantiles/HeapUpdateDoublesSketch.java         |   2 +-
 .../apache/datasketches/quantiles/ItemsSketch.java | 131 ++++----
 .../datasketches/quantiles/KolmogorovSmirnov.java  |   6 +-
 .../quantilescommon/DoublesSketchSortedView.java   | 118 +++++++
 .../quantiles/CustomQuantilesTest.java             |   3 +-
 .../apache/datasketches/quantiles/UtilTest.java    |   3 +-
 .../quantilescommon/CrossCheckQuantilesTest.java   |  29 +-
 .../quantilescommon/ReflectUtilityTest.java        |  15 +-
 19 files changed, 603 insertions(+), 625 deletions(-)

diff --git a/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java 
b/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java
index 8883734c..ab241f7b 100644
--- a/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/kll/KllDoublesSketch.java
@@ -25,6 +25,7 @@ import static 
org.apache.datasketches.common.ByteArrayUtil.putDoubleLE;
 import static org.apache.datasketches.kll.KllSketch.SketchStructure.UPDATABLE;
 import static org.apache.datasketches.kll.KllSketch.SketchType.DOUBLES_SKETCH;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 import org.apache.datasketches.common.ArrayOfItemsSerDe;
@@ -35,7 +36,7 @@ import 
org.apache.datasketches.memory.DefaultMemoryRequestServer;
 import org.apache.datasketches.memory.Memory;
 import org.apache.datasketches.memory.MemoryRequestServer;
 import org.apache.datasketches.memory.WritableMemory;
-import org.apache.datasketches.quantilescommon.DoublesSortedView;
+import org.apache.datasketches.quantilescommon.DoublesSketchSortedView;
 import org.apache.datasketches.quantilescommon.QuantileSearchCriteria;
 import org.apache.datasketches.quantilescommon.QuantilesDoublesAPI;
 import org.apache.datasketches.quantilescommon.QuantilesDoublesSketchIterator;
@@ -46,7 +47,7 @@ import 
org.apache.datasketches.quantilescommon.QuantilesDoublesSketchIterator;
  * @see org.apache.datasketches.kll.KllSketch
  */
 public abstract class KllDoublesSketch extends KllSketch implements 
QuantilesDoublesAPI {
-  private KllDoublesSketchSortedView kllDoublesSV = null;
+  private DoublesSketchSortedView doublesSV = null;
   final static int ITEM_BYTES = Double.BYTES;
 
   KllDoublesSketch(
@@ -171,21 +172,21 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
   public double[] getCDF(final double[] splitPoints, final 
QuantileSearchCriteria searchCrit) {
     if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
     refreshSortedView();
-    return kllDoublesSV.getCDF(splitPoints, searchCrit);
+    return doublesSV.getCDF(splitPoints, searchCrit);
   }
 
   @Override
   public double[] getPMF(final double[] splitPoints, final 
QuantileSearchCriteria searchCrit) {
     if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
     refreshSortedView();
-    return kllDoublesSV.getPMF(splitPoints, searchCrit);
+    return doublesSV.getPMF(splitPoints, searchCrit);
   }
 
   @Override
   public double getQuantile(final double rank, final QuantileSearchCriteria 
searchCrit) {
     if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
     refreshSortedView();
-    return kllDoublesSV.getQuantile(rank, searchCrit);
+    return doublesSV.getQuantile(rank, searchCrit);
   }
 
   @Override
@@ -195,7 +196,7 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     final int len = ranks.length;
     final double[] quantiles = new double[len];
     for (int i = 0; i < len; i++) {
-      quantiles[i] = kllDoublesSV.getQuantile(ranks[i], searchCrit);
+      quantiles[i] = doublesSV.getQuantile(ranks[i], searchCrit);
     }
     return quantiles;
   }
@@ -224,7 +225,7 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
   public double getRank(final double quantile, final QuantileSearchCriteria 
searchCrit) {
     if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
     refreshSortedView();
-    return kllDoublesSV.getRank(quantile, searchCrit);
+    return doublesSV.getRank(quantile, searchCrit);
   }
 
   /**
@@ -254,17 +255,17 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     final int len = quantiles.length;
     final double[] ranks = new double[len];
     for (int i = 0; i < len; i++) {
-      ranks[i] = kllDoublesSV.getRank(quantiles[i], searchCrit);
+      ranks[i] = doublesSV.getRank(quantiles[i], searchCrit);
     }
     return ranks;
   }
 
   @Override
   @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "OK in this 
case.")
-  public DoublesSortedView getSortedView() {
+  public DoublesSketchSortedView getSortedView() {
     if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
     refreshSortedView();
-    return kllDoublesSV;
+    return doublesSV;
   }
 
   @Override
@@ -278,9 +279,9 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     if (readOnly || sketchStructure != UPDATABLE) { throw new 
SketchesArgumentException(TGT_IS_READ_ONLY_MSG); }
     if (this == other) { throw new SketchesArgumentException(SELF_MERGE_MSG); }
     final KllDoublesSketch othDblSk = (KllDoublesSketch)other;
-    if (othDblSk.isEmpty()) { return; } //then check empty
+    if (othDblSk.isEmpty()) { return; }
     KllDoublesHelper.mergeDoubleImpl(this, othDblSk);
-    kllDoublesSV = null;
+    doublesSV = null;
   }
 
   /**
@@ -299,7 +300,7 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     setMinItem(Double.NaN);
     setMaxItem(Double.NaN);
     setDoubleItemsArray(new double[k]);
-    kllDoublesSV = null;
+    doublesSV = null;
   }
 
   @Override
@@ -323,7 +324,7 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     if (Double.isNaN(item)) { return; } //ignore
     if (readOnly) { throw new SketchesArgumentException(TGT_IS_READ_ONLY_MSG); 
}
     KllDoublesHelper.updateDouble(this, item);
-    kllDoublesSV = null;
+    doublesSV = null;
   }
 
   /**
@@ -337,7 +338,7 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     if (weight < 1L) { throw new SketchesArgumentException("Weight is less 
than one."); }
     if (weight == 1L) { KllDoublesHelper.updateDouble(this, item); }
     else { KllDoublesHelper.updateDouble(this, item, weight); }
-    kllDoublesSV = null;
+    doublesSV = null;
   }
 
   //restricted
@@ -393,11 +394,6 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     return levelsArr[getNumLevels()] * Double.BYTES;
   }
 
-  private final void refreshSortedView() {
-    kllDoublesSV = (kllDoublesSV == null)
-        ? new KllDoublesSketchSortedView(this) : kllDoublesSV;
-  }
-
   abstract void setDoubleItemsArray(double[] doubleItems);
 
   abstract void setDoubleItemsArrayAt(int index, double item);
@@ -416,4 +412,135 @@ public abstract class KllDoublesSketch extends KllSketch 
implements QuantilesDou
     }
   }
 
+  private final DoublesSketchSortedView refreshSortedView() {
+    if (doublesSV == null) {
+      final CreateSortedView csv = new CreateSortedView();
+      doublesSV = csv.getSV();
+    }
+    return doublesSV;
+  }
+
+  private final class CreateSortedView {
+    double[] quantiles;
+    long[] cumWeights;
+
+    DoublesSketchSortedView getSV() {
+      if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
+      if (getN() == 0) { throw new SketchesArgumentException(EMPTY_MSG); }
+      final double[] srcQuantiles = getDoubleItemsArray();
+      final int[] srcLevels = levelsArr;
+      final int srcNumLevels = getNumLevels();
+
+      if (!isLevelZeroSorted()) {
+        Arrays.sort(srcQuantiles, srcLevels[0], srcLevels[1]);
+        if (!hasMemory()) { setLevelZeroSorted(true); }
+      }
+      final int numQuantiles = getNumRetained();
+      quantiles = new double[numQuantiles];
+      cumWeights = new long[numQuantiles];
+      populateFromSketch(srcQuantiles, srcLevels, srcNumLevels, numQuantiles);
+      return new DoublesSketchSortedView(
+          quantiles, cumWeights, getN(), getMaxItem(), getMinItem());
+    }
+
+    private void populateFromSketch(final double[] srcQuantiles, final int[] 
srcLevels,
+      final int srcNumLevels, final int numItems) {
+      final int[] myLevels = new int[srcNumLevels + 1];
+      final int offset = srcLevels[0];
+      System.arraycopy(srcQuantiles, offset, quantiles, 0, numItems);
+      int srcLevel = 0;
+      int dstLevel = 0;
+      long weight = 1;
+      while (srcLevel < srcNumLevels) {
+        final int fromIndex = srcLevels[srcLevel] - offset;
+        final int toIndex = srcLevels[srcLevel + 1] - offset; // exclusive
+        if (fromIndex < toIndex) { // if equal, skip empty level
+          Arrays.fill(cumWeights, fromIndex, toIndex, weight);
+          myLevels[dstLevel] = fromIndex;
+          myLevels[dstLevel + 1] = toIndex;
+          dstLevel++;
+        }
+        srcLevel++;
+        weight *= 2;
+      }
+      final int numLevels = dstLevel;
+      blockyTandemMergeSort(quantiles, cumWeights, myLevels, numLevels); 
//create unit weights
+      KllHelper.convertToCumulative(cumWeights);
+    }
+  } //End of class CreateSortedView
+
+  private static void blockyTandemMergeSort(final double[] quantiles, final 
long[] weights,
+      final int[] levels, final int numLevels) {
+    if (numLevels == 1) { return; }
+
+    // duplicate the input in preparation for the "ping-pong" copy reduction 
strategy.
+    final double[] quantilesTmp = Arrays.copyOf(quantiles, quantiles.length);
+    final long[] weightsTmp = Arrays.copyOf(weights, quantiles.length); // 
don't need the extra one
+
+    blockyTandemMergeSortRecursion(quantilesTmp, weightsTmp, quantiles, 
weights, levels, 0, numLevels);
+  }
+
+  private static void blockyTandemMergeSortRecursion(
+      final double[] quantilesSrc, final long[] weightsSrc,
+      final double[] quantilesDst, final long[] weightsDst,
+      final int[] levels, final int startingLevel, final int numLevels) {
+    if (numLevels == 1) { return; }
+    final int numLevels1 = numLevels / 2;
+    final int numLevels2 = numLevels - numLevels1;
+    assert numLevels1 >= 1;
+    assert numLevels2 >= numLevels1;
+    final int startingLevel1 = startingLevel;
+    final int startingLevel2 = startingLevel + numLevels1;
+    // swap roles of src and dst
+    blockyTandemMergeSortRecursion(
+        quantilesDst, weightsDst,
+        quantilesSrc, weightsSrc,
+        levels, startingLevel1, numLevels1);
+    blockyTandemMergeSortRecursion(
+        quantilesDst, weightsDst,
+        quantilesSrc, weightsSrc,
+        levels, startingLevel2, numLevels2);
+    tandemMerge(
+        quantilesSrc, weightsSrc,
+        quantilesDst, weightsDst,
+        levels,
+        startingLevel1, numLevels1,
+        startingLevel2, numLevels2);
+  }
+
+  private static void tandemMerge(
+      final double[] quantilesSrc, final long[] weightsSrc,
+      final double[] quantilesDst, final long[] weightsDst,
+      final int[] levelStarts,
+      final int startingLevel1, final int numLevels1,
+      final int startingLevel2, final int numLevels2) {
+    final int fromIndex1 = levelStarts[startingLevel1];
+    final int toIndex1 = levelStarts[startingLevel1 + numLevels1]; // exclusive
+    final int fromIndex2 = levelStarts[startingLevel2];
+    final int toIndex2 = levelStarts[startingLevel2 + numLevels2]; // exclusive
+    int iSrc1 = fromIndex1;
+    int iSrc2 = fromIndex2;
+    int iDst = fromIndex1;
+
+    while (iSrc1 < toIndex1 && iSrc2 < toIndex2) {
+      if (quantilesSrc[iSrc1] < quantilesSrc[iSrc2]) {
+        quantilesDst[iDst] = quantilesSrc[iSrc1];
+        weightsDst[iDst] = weightsSrc[iSrc1];
+        iSrc1++;
+      } else {
+        quantilesDst[iDst] = quantilesSrc[iSrc2];
+        weightsDst[iDst] = weightsSrc[iSrc2];
+        iSrc2++;
+      }
+      iDst++;
+    }
+    if (iSrc1 < toIndex1) {
+      System.arraycopy(quantilesSrc, iSrc1, quantilesDst, iDst, toIndex1 - 
iSrc1);
+      System.arraycopy(weightsSrc, iSrc1, weightsDst, iDst, toIndex1 - iSrc1);
+    } else if (iSrc2 < toIndex2) {
+      System.arraycopy(quantilesSrc, iSrc2, quantilesDst, iDst, toIndex2 - 
iSrc2);
+      System.arraycopy(weightsSrc, iSrc2, weightsDst, iDst, toIndex2 - iSrc2);
+    }
+  }
+
 }
diff --git 
a/src/main/java/org/apache/datasketches/kll/KllDoublesSketchSortedView.java 
b/src/main/java/org/apache/datasketches/kll/KllDoublesSketchSortedView.java
index 13f0a9df..a8eaccad 100644
--- a/src/main/java/org/apache/datasketches/kll/KllDoublesSketchSortedView.java
+++ b/src/main/java/org/apache/datasketches/kll/KllDoublesSketchSortedView.java
@@ -23,8 +23,6 @@ import static 
org.apache.datasketches.quantilescommon.QuantileSearchCriteria.INC
 import static org.apache.datasketches.quantilescommon.QuantilesAPI.EMPTY_MSG;
 import static 
org.apache.datasketches.quantilescommon.QuantilesUtil.getNaturalRank;
 
-import java.util.Arrays;
-
 import org.apache.datasketches.common.SketchesArgumentException;
 import org.apache.datasketches.quantilescommon.DoublesSortedView;
 import org.apache.datasketches.quantilescommon.DoublesSortedViewIterator;
@@ -49,6 +47,8 @@ public final class KllDoublesSketchSortedView implements 
DoublesSortedView {
    * @param quantiles sorted array of quantiles
    * @param cumWeights sorted, monotonically increasing cumulative weights.
    * @param totalN the total number of items presented to the sketch.
+   * @param maxItem of type double
+   * @param minItem of type double
    */
   KllDoublesSketchSortedView(final double[] quantiles, final long[] 
cumWeights, final long totalN,
       final double maxItem, final double minItem) {
@@ -59,30 +59,6 @@ public final class KllDoublesSketchSortedView implements 
DoublesSortedView {
     this.minItem = minItem;
   }
 
-  /**
-   * Constructs this Sorted View given the sketch
-   * @param sketch the given KllDoublesSketch.
-   */
-  public KllDoublesSketchSortedView(final KllDoublesSketch sketch) {
-    if (sketch.isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
-    this.totalN = sketch.getN();
-    this.maxItem = sketch.getMaxItem();
-    this.minItem = sketch.getMinItem();
-    final double[] srcQuantiles = sketch.getDoubleItemsArray();
-    final int[] srcLevels = sketch.levelsArr;
-    final int srcNumLevels = sketch.getNumLevels();
-
-    if (!sketch.isLevelZeroSorted()) {
-      Arrays.sort(srcQuantiles, srcLevels[0], srcLevels[1]);
-      if (!sketch.hasMemory()) { sketch.setLevelZeroSorted(true); }
-    }
-
-    final int numQuantiles = srcLevels[srcNumLevels] - srcLevels[0]; //remove 
free space
-    quantiles = new double[numQuantiles];
-    cumWeights = new long[numQuantiles];
-    populateFromSketch(srcQuantiles, srcLevels, srcNumLevels, numQuantiles);
-  }
-
   @Override
   public long[] getCumulativeWeights() {
     return cumWeights.clone();
@@ -144,105 +120,4 @@ public final class KllDoublesSketchSortedView implements 
DoublesSortedView {
     return new DoublesSortedViewIterator(quantiles, cumWeights);
   }
 
-  //restricted methods
-
-  private void populateFromSketch(final double[] srcQuantiles, final int[] 
srcLevels,
-    final int srcNumLevels, final int numItems) {
-    final int[] myLevels = new int[srcNumLevels + 1];
-    final int offset = srcLevels[0];
-    System.arraycopy(srcQuantiles, offset, quantiles, 0, numItems);
-    int srcLevel = 0;
-    int dstLevel = 0;
-    long weight = 1;
-    while (srcLevel < srcNumLevels) {
-      final int fromIndex = srcLevels[srcLevel] - offset;
-      final int toIndex = srcLevels[srcLevel + 1] - offset; // exclusive
-      if (fromIndex < toIndex) { // if equal, skip empty level
-        Arrays.fill(cumWeights, fromIndex, toIndex, weight);
-        myLevels[dstLevel] = fromIndex;
-        myLevels[dstLevel + 1] = toIndex;
-        dstLevel++;
-      }
-      srcLevel++;
-      weight *= 2;
-    }
-    final int numLevels = dstLevel;
-    blockyTandemMergeSort(quantiles, cumWeights, myLevels, numLevels); 
//create unit weights
-    KllHelper.convertToCumulative(cumWeights);
-  }
-
-  private static void blockyTandemMergeSort(final double[] quantiles, final 
long[] weights,
-      final int[] levels, final int numLevels) {
-    if (numLevels == 1) { return; }
-
-    // duplicate the input in preparation for the "ping-pong" copy reduction 
strategy.
-    final double[] quantilesTmp = Arrays.copyOf(quantiles, quantiles.length);
-    final long[] weightsTmp = Arrays.copyOf(weights, quantiles.length); // 
don't need the extra one
-
-    blockyTandemMergeSortRecursion(quantilesTmp, weightsTmp, quantiles, 
weights, levels, 0, numLevels);
-  }
-
-  private static void blockyTandemMergeSortRecursion(
-      final double[] quantilesSrc, final long[] weightsSrc,
-      final double[] quantilesDst, final long[] weightsDst,
-      final int[] levels, final int startingLevel, final int numLevels) {
-    if (numLevels == 1) { return; }
-    final int numLevels1 = numLevels / 2;
-    final int numLevels2 = numLevels - numLevels1;
-    assert numLevels1 >= 1;
-    assert numLevels2 >= numLevels1;
-    final int startingLevel1 = startingLevel;
-    final int startingLevel2 = startingLevel + numLevels1;
-    // swap roles of src and dst
-    blockyTandemMergeSortRecursion(
-        quantilesDst, weightsDst,
-        quantilesSrc, weightsSrc,
-        levels, startingLevel1, numLevels1);
-    blockyTandemMergeSortRecursion(
-        quantilesDst, weightsDst,
-        quantilesSrc, weightsSrc,
-        levels, startingLevel2, numLevels2);
-    tandemMerge(
-        quantilesSrc, weightsSrc,
-        quantilesDst, weightsDst,
-        levels,
-        startingLevel1, numLevels1,
-        startingLevel2, numLevels2);
-  }
-
-  private static void tandemMerge(
-      final double[] quantilesSrc, final long[] weightsSrc,
-      final double[] quantilesDst, final long[] weightsDst,
-      final int[] levelStarts,
-      final int startingLevel1, final int numLevels1,
-      final int startingLevel2, final int numLevels2) {
-    final int fromIndex1 = levelStarts[startingLevel1];
-    final int toIndex1 = levelStarts[startingLevel1 + numLevels1]; // exclusive
-    final int fromIndex2 = levelStarts[startingLevel2];
-    final int toIndex2 = levelStarts[startingLevel2 + numLevels2]; // exclusive
-    int iSrc1 = fromIndex1;
-    int iSrc2 = fromIndex2;
-    int iDst = fromIndex1;
-
-    while (iSrc1 < toIndex1 && iSrc2 < toIndex2) {
-      if (quantilesSrc[iSrc1] < quantilesSrc[iSrc2]) {
-        quantilesDst[iDst] = quantilesSrc[iSrc1];
-        weightsDst[iDst] = weightsSrc[iSrc1];
-        iSrc1++;
-      } else {
-        quantilesDst[iDst] = quantilesSrc[iSrc2];
-        weightsDst[iDst] = weightsSrc[iSrc2];
-        iSrc2++;
-      }
-      iDst++;
-    }
-    if (iSrc1 < toIndex1) {
-      System.arraycopy(quantilesSrc, iSrc1, quantilesDst, iDst, toIndex1 - 
iSrc1);
-      System.arraycopy(weightsSrc, iSrc1, weightsDst, iDst, toIndex1 - iSrc1);
-    } else if (iSrc2 < toIndex2) {
-      System.arraycopy(quantilesSrc, iSrc2, quantilesDst, iDst, toIndex2 - 
iSrc2);
-      System.arraycopy(weightsSrc, iSrc2, weightsDst, iDst, toIndex2 - iSrc2);
-    }
-  }
-
 }
diff --git a/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java 
b/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java
index 273a89bc..9f5a5ae7 100644
--- a/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java
+++ b/src/main/java/org/apache/datasketches/kll/KllItemsSketch.java
@@ -242,7 +242,6 @@ public abstract class KllItemsSketch<T> extends KllSketch 
implements QuantilesGe
   public final ItemsSketchSortedView<T> getSortedView() {
     if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
     return refreshSortedView();
-    //return itemsSV; //SpotBugs EI_EXPOSE_REP, Suppressed by 
FindBugsExcludeFilter
   }
 
   @Override
@@ -454,7 +453,7 @@ public abstract class KllItemsSketch<T> extends KllSketch 
implements QuantilesGe
         blockyTandemMergeSort(quantiles, cumWeights, myLevels, numLevels, 
comparator); //create unit weights
         KllHelper.convertToCumulative(cumWeights);
       }
-  }
+  } //End of class CreateSortedView
 
     private static <T> void blockyTandemMergeSort(final Object[] quantiles, 
final long[] weights,
         final int[] levels, final int numLevels, final Comparator<? super T> 
comp) {
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java 
b/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java
index 81c9e6db..f6df9e87 100644
--- a/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/CompactDoublesSketch.java
@@ -23,7 +23,7 @@ import org.apache.datasketches.common.SketchesStateException;
 import org.apache.datasketches.memory.Memory;
 
 /**
- * Compact sketches are inherently <i>read ony</i>.
+ * Compact sketches are inherently <i>read only</i>.
  * @author Jon Malkin
  */
 public abstract class CompactDoublesSketch extends DoublesSketch {
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/DirectDoublesSketchAccessor.java
 
b/src/main/java/org/apache/datasketches/quantiles/DirectDoublesSketchAccessor.java
index 172ad14b..b95c9f12 100644
--- 
a/src/main/java/org/apache/datasketches/quantiles/DirectDoublesSketchAccessor.java
+++ 
b/src/main/java/org/apache/datasketches/quantiles/DirectDoublesSketchAccessor.java
@@ -27,6 +27,7 @@ import org.apache.datasketches.memory.WritableMemory;
  * @author Jon Malkin
  */
 final class DirectDoublesSketchAccessor extends DoublesSketchAccessor {
+
   DirectDoublesSketchAccessor(final DoublesSketch ds,
                               final boolean forceSize,
                               final int level) {
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
 
b/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
index 384b4266..96c01d93 100644
--- 
a/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
+++ 
b/src/main/java/org/apache/datasketches/quantiles/DirectUpdateDoublesSketch.java
@@ -193,7 +193,7 @@ final class DirectUpdateDoublesSketch extends 
DirectUpdateDoublesSketchR {
       //bit pattern on direct is always derived, no need to save it.
     }
     putN(newN);
-    classicQdsSV = null;
+    doublesSV = null;
   }
 
   @Override
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/DoublesArrayAccessor.java 
b/src/main/java/org/apache/datasketches/quantiles/DoublesArrayAccessor.java
index dd740fb7..7fcf38a2 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesArrayAccessor.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesArrayAccessor.java
@@ -67,8 +67,7 @@ final class DoublesArrayAccessor extends 
DoublesBufferAccessor {
   }
 
   @Override
-  void putArray(final double[] srcArray, final int srcIndex,
-                       final int dstIndex, final int numItems) {
+  void putArray(final double[] srcArray, final int srcIndex, final int 
dstIndex, final int numItems) {
     System.arraycopy(srcArray, srcIndex, buffer_, dstIndex, numItems);
   }
 
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/DoublesBufferAccessor.java 
b/src/main/java/org/apache/datasketches/quantiles/DoublesBufferAccessor.java
index c3b0f9b6..1014a104 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesBufferAccessor.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesBufferAccessor.java
@@ -23,6 +23,7 @@ package org.apache.datasketches.quantiles;
  * @author Jon Malkin
  */
 abstract class DoublesBufferAccessor {
+
   abstract double get(final int index);
 
   abstract double set(final int index, final double quantile);
@@ -31,6 +32,5 @@ abstract class DoublesBufferAccessor {
 
   abstract double[] getArray(int fromIdx, int numItems);
 
-  abstract void putArray(double[] srcArray, int srcIndex,
-                         int dstIndex, int numItems);
+  abstract void putArray(double[] srcArray, int srcIndex, int dstIndex, int 
numItems);
 }
diff --git a/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java 
b/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
index 93858c38..11dcc425 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesSketch.java
@@ -21,6 +21,7 @@ package org.apache.datasketches.quantiles;
 
 import static java.lang.Math.max;
 import static java.lang.Math.min;
+import static java.lang.System.arraycopy;
 import static org.apache.datasketches.common.Util.ceilingPowerOf2;
 import static org.apache.datasketches.quantiles.ClassicUtil.MAX_PRELONGS;
 import static org.apache.datasketches.quantiles.ClassicUtil.MIN_K;
@@ -28,13 +29,16 @@ import static 
org.apache.datasketches.quantiles.ClassicUtil.checkIsCompactMemory
 import static org.apache.datasketches.quantiles.ClassicUtil.checkK;
 import static 
org.apache.datasketches.quantiles.ClassicUtil.computeNumLevelsNeeded;
 import static 
org.apache.datasketches.quantiles.ClassicUtil.computeRetainedItems;
+import static 
org.apache.datasketches.quantiles.DoublesSketchAccessor.BB_LVL_IDX;
 
+import java.util.Arrays;
 import java.util.Random;
 
 import org.apache.datasketches.common.SketchesArgumentException;
+import org.apache.datasketches.common.SketchesStateException;
 import org.apache.datasketches.memory.Memory;
 import org.apache.datasketches.memory.WritableMemory;
-import org.apache.datasketches.quantilescommon.DoublesSortedView;
+import org.apache.datasketches.quantilescommon.DoublesSketchSortedView;
 import org.apache.datasketches.quantilescommon.QuantileSearchCriteria;
 import org.apache.datasketches.quantilescommon.QuantilesAPI;
 import org.apache.datasketches.quantilescommon.QuantilesDoublesAPI;
@@ -108,7 +112,7 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
    */
   final int k_;
 
-  DoublesSketchSortedView classicQdsSV = null;
+  DoublesSketchSortedView doublesSV = null;
 
   DoublesSketch(final int k) {
     checkK(k);
@@ -160,7 +164,7 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
   public double[] getCDF(final double[] splitPoints, final 
QuantileSearchCriteria searchCrit) {
   if (isEmpty()) { throw new IllegalArgumentException(QuantilesAPI.EMPTY_MSG); 
}
     refreshSortedView();
-    return classicQdsSV.getCDF(splitPoints, searchCrit);
+    return doublesSV.getCDF(splitPoints, searchCrit);
   }
 
   @Override
@@ -173,14 +177,14 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
   public double[] getPMF(final double[] splitPoints, final 
QuantileSearchCriteria searchCrit) {
   if (isEmpty()) { throw new IllegalArgumentException(QuantilesAPI.EMPTY_MSG); 
}
     refreshSortedView();
-    return classicQdsSV.getPMF(splitPoints, searchCrit);
+    return doublesSV.getPMF(splitPoints, searchCrit);
   }
 
   @Override
   public double getQuantile(final double rank, final QuantileSearchCriteria 
searchCrit) {
   if (isEmpty()) { throw new IllegalArgumentException(QuantilesAPI.EMPTY_MSG); 
}
     refreshSortedView();
-    return classicQdsSV.getQuantile(rank, searchCrit);
+    return doublesSV.getQuantile(rank, searchCrit);
   }
 
   @Override
@@ -190,7 +194,7 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
     final int len = ranks.length;
     final double[] quantiles = new double[len];
     for (int i = 0; i < len; i++) {
-      quantiles[i] = classicQdsSV.getQuantile(ranks[i], searchCrit);
+      quantiles[i] = doublesSV.getQuantile(ranks[i], searchCrit);
     }
     return quantiles;
   }
@@ -219,7 +223,7 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
   public double getRank(final double quantile, final QuantileSearchCriteria 
searchCrit) {
     if (isEmpty()) { throw new 
IllegalArgumentException(QuantilesAPI.EMPTY_MSG); }
     refreshSortedView();
-    return classicQdsSV.getRank(quantile, searchCrit);
+    return doublesSV.getRank(quantile, searchCrit);
   }
 
   /**
@@ -249,7 +253,7 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
     final int len = quantiles.length;
     final double[] ranks = new double[len];
     for (int i = 0; i < len; i++) {
-      ranks[i] = classicQdsSV.getRank(quantiles[i], searchCrit);
+      ranks[i] = doublesSV.getRank(quantiles[i], searchCrit);
     }
     return ranks;
   }
@@ -508,11 +512,6 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
     return new DoublesSketchIterator(this, getBitPattern());
   }
 
-  @Override
-  public DoublesSortedView getSortedView() {
-    return new DoublesSketchSortedView(this);
-  }
-
   /**
    * {@inheritDoc}
    * <p>The parameter <i>k</i> will not change.</p>
@@ -538,10 +537,6 @@ public abstract class DoublesSketch implements 
QuantilesDoublesAPI {
     return newSketch;
   }
 
-private final void refreshSortedView() {
-  classicQdsSV = (classicQdsSV == null) ? new DoublesSketchSortedView(this) : 
classicQdsSV;
-}
-
   //Restricted abstract
 
   /**
@@ -579,4 +574,225 @@ private final void refreshSortedView() {
    * @return the Memory if it exists, otherwise returns null.
    */
   abstract WritableMemory getMemory();
+
+  //************SORTED VIEW****************************
+
+  @Override
+  public DoublesSketchSortedView getSortedView() {
+    return refreshSortedView();
+  }
+
+  private final DoublesSketchSortedView refreshSortedView() {
+    return (doublesSV == null) ? (doublesSV = getSV()) : doublesSV;
+  }
+
+  private DoublesSketchSortedView getSV() {
+    final long totalN = getN();
+    if (isEmpty() || (totalN == 0)) { throw new 
SketchesArgumentException(EMPTY_MSG); }
+    final int numQuantiles = getNumRetained();
+    final double[] svQuantiles = new double[numQuantiles];
+    final long[] svCumWeights = new long[numQuantiles];
+    final DoublesSketchAccessor sketchAccessor = 
DoublesSketchAccessor.wrap(this);
+
+    // Populate from DoublesSketch:
+    //  copy over the "levels" and then the base buffer, all with appropriate 
weights
+    populateFromDoublesSketch(getK(), totalN, getBitPattern(), sketchAccessor, 
svQuantiles, svCumWeights);
+
+    // Sort the first "numSamples" slots of the two arrays in tandem,
+    // taking advantage of the already sorted blocks of length k
+    blockyTandemMergeSort(svQuantiles, svCumWeights, numQuantiles, getK());
+
+    if (convertToCumulative(svCumWeights) != totalN) {
+      throw new SketchesStateException("Sorted View is misconfigured. TotalN 
does not match cumWeights.");
+    }
+    return new DoublesSketchSortedView(svQuantiles, svCumWeights, totalN, 
getMaxItem(), getMinItem());
+  }
+
+  private final static void populateFromDoublesSketch(
+      final int k, final long totalN, final long bitPattern,
+      final DoublesSketchAccessor sketchAccessor,
+      final double[] svQuantiles, final long[] svCumWeights) {
+    long weight = 1;
+    int index = 0;
+    long bits = bitPattern;
+    assert bits == (totalN / (2L * k)); // internal consistency check
+    for (int lvl = 0; bits != 0L; lvl++, bits >>>= 1) {
+      weight <<= 1; // X2
+      if ((bits & 1L) > 0L) {
+        sketchAccessor.setLevel(lvl);
+        for (int i = 0; i < sketchAccessor.numItems(); i++) {
+          svQuantiles[index] = sketchAccessor.get(i);
+          svCumWeights[index] = weight;
+          index++;
+        }
+      }
+    }
+
+    weight = 1; //NOT a mistake! We just copied the highest level; now we need 
to copy the base buffer
+    final int startOfBaseBufferBlock = index;
+
+    // Copy BaseBuffer over, along with weight = 1
+    sketchAccessor.setLevel(BB_LVL_IDX);
+    for (int i = 0; i < sketchAccessor.numItems(); i++) {
+      svQuantiles[index] = sketchAccessor.get(i);
+      svCumWeights[index] = weight;
+      index++;
+    }
+    assert index == svQuantiles.length;
+
+    // Must sort the items that came from the base buffer.
+    // Don't need to sort the corresponding weights because they are all the 
same.
+    final int numSamples = index;
+    Arrays.sort(svQuantiles, startOfBaseBufferBlock, numSamples);
+  }
+
+  /**
+   * blockyTandemMergeSort() is an implementation of top-down merge sort 
specialized
+   * for the case where the input contains successive equal-length blocks
+   * that have already been sorted, so that only the top part of the
+   * merge tree remains to be executed. Also, two arrays are sorted in tandem,
+   * as discussed below.
+   * @param svQuantiles array of quantiles for sorted view
+   * @param svCumWts array of cumulative weights for sorted view
+   * @param arrLen length of quantiles array and cumWts array
+   * @param blkSize size of internal sorted blocks, equal to k
+   */
+  //used by this and UtilTest
+  static void blockyTandemMergeSort(final double[] svQuantiles, final long[] 
svCumWts, final int arrLen,
+      final int blkSize) {
+    assert blkSize >= 1;
+    if (arrLen <= blkSize) { return; }
+    int numblks = arrLen / blkSize;
+    if ((numblks * blkSize) < arrLen) { numblks += 1; }
+    assert ((numblks * blkSize) >= arrLen);
+
+    // duplication of the input arrays is preparation for the "ping-pong" copy 
reduction strategy.
+    final double[] qSrc = Arrays.copyOf(svQuantiles, arrLen);
+    final long[] cwSrc   = Arrays.copyOf(svCumWts, arrLen);
+
+    blockyTandemMergeSortRecursion(qSrc, cwSrc,
+                                   svQuantiles, svCumWts,
+                                   0, numblks,
+                                   blkSize, arrLen);
+  }
+
+  /**
+   *  blockyTandemMergeSortRecursion() is called by blockyTandemMergeSort().
+   *  In addition to performing the algorithm's top down recursion,
+   *  it manages the buffer swapping that eliminates most copying.
+   *  It also maps the input's pre-sorted blocks into the subarrays
+   *  that are processed by tandemMerge().
+   * @param qSrc source array of quantiles
+   * @param cwSrc source weights array
+   * @param qDst destination quantiles array
+   * @param cwDst destination weights array
+   * @param grpStart group start, refers to pre-sorted blocks such as block 0, 
block 1, etc.
+   * @param grpLen group length, refers to pre-sorted blocks such as block 0, 
block 1, etc.
+   * @param blkSize block size
+   * @param arrLim array limit
+   */
+  private static void blockyTandemMergeSortRecursion(final double[] qSrc, 
final long[] cwSrc,
+      final double[] qDst, final long[] cwDst, final int grpStart, final int 
grpLen,
+      /* indices of blocks */ final int blkSize, final int arrLim) {
+    // Important note: grpStart and grpLen do NOT refer to positions in the 
underlying array.
+    // Instead, they refer to the pre-sorted blocks, such as block 0, block 1, 
etc.
+
+    assert (grpLen > 0);
+    if (grpLen == 1) { return; }
+    final int grpLen1 = grpLen / 2;
+    final int grpLen2 = grpLen - grpLen1;
+    assert (grpLen1 >= 1);
+    assert (grpLen2 >= grpLen1);
+
+    final int grpStart1 = grpStart;
+    final int grpStart2 = grpStart + grpLen1;
+
+    //swap roles of src and dst
+    blockyTandemMergeSortRecursion(qDst, cwDst,
+                           qSrc, cwSrc,
+                           grpStart1, grpLen1, blkSize, arrLim);
+
+    //swap roles of src and dst
+    blockyTandemMergeSortRecursion(qDst, cwDst,
+                           qSrc, cwSrc,
+                           grpStart2, grpLen2, blkSize, arrLim);
+
+    // here we convert indices of blocks into positions in the underlying 
array.
+    final int arrStart1 = grpStart1 * blkSize;
+    final int arrStart2 = grpStart2 * blkSize;
+    final int arrLen1   = grpLen1   * blkSize;
+    int arrLen2         = grpLen2   * blkSize;
+
+    // special case for the final block which might be shorter than blkSize.
+    if ((arrStart2 + arrLen2) > arrLim) { arrLen2 = arrLim - arrStart2; }
+
+    tandemMerge(qSrc, cwSrc,
+                arrStart1, arrLen1,
+                arrStart2, arrLen2,
+                qDst, cwDst,
+                arrStart1); // which will be arrStart3
+  }
+
+  /**
+   *  Performs two merges in tandem. One of them provides the sort keys
+   *  while the other one passively undergoes the same data motion.
+   * @param qSrc quantiles source
+   * @param cwSrc cumulative weights source
+   * @param arrStart1 Array 1 start offset
+   * @param arrLen1 Array 1 length
+   * @param arrStart2 Array 2 start offset
+   * @param arrLen2 Array 2 length
+   * @param qDst quantiles destination
+   * @param cwDst cumulative weights destination
+   * @param arrStart3 Array 3 start offset
+   */
+  private static void tandemMerge(final double[] qSrc, final long[] cwSrc,
+                                  final int arrStart1, final int arrLen1,
+                                  final int arrStart2, final int arrLen2,
+                                  final double[] qDst, final long[] cwDst,
+                                  final int arrStart3) {
+    final int arrStop1 = arrStart1 + arrLen1;
+    final int arrStop2 = arrStart2 + arrLen2;
+
+    int i1 = arrStart1;
+    int i2 = arrStart2;
+    int i3 = arrStart3;
+    while ((i1 < arrStop1) && (i2 < arrStop2)) {
+      if (qSrc[i2] < qSrc[i1]) {
+        qDst[i3] = qSrc[i2];
+        cwDst[i3] = cwSrc[i2];
+        i2++;
+      } else {
+        qDst[i3] = qSrc[i1];
+        cwDst[i3] = cwSrc[i1];
+        i1++;
+      }
+      i3++;
+    }
+
+    if (i1 < arrStop1) {
+      arraycopy(qSrc, i1, qDst, i3, arrStop1 - i1);
+      arraycopy(cwSrc, i1, cwDst, i3, arrStop1 - i1);
+    } else {
+      assert i2 < arrStop2;
+      arraycopy(qSrc, i2, qDst, i3, arrStop2 - i2);
+      arraycopy(cwSrc, i2, cwDst, i3, arrStop2 - i2);
+    }
+  }
+
+  /**
+   * Convert the individual weights into cumulative weights.
+   * An array of {1,1,1,1} becomes {1,2,3,4}
+   * @param array of actual weights from the sketch, none of the weights may 
be zero
+   * @return total weight
+   */
+  private static long convertToCumulative(final long[] array) {
+    long subtotal = 0;
+    for (int i = 0; i < array.length; i++) {
+      final long newSubtotal = subtotal + array[i];
+      subtotal = array[i] = newSubtotal;
+    }
+    return subtotal;
+  }
+
 }
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/DoublesSketchSortedView.java 
b/src/main/java/org/apache/datasketches/quantiles/DoublesSketchSortedView.java
deleted file mode 100644
index bb68061a..00000000
--- 
a/src/main/java/org/apache/datasketches/quantiles/DoublesSketchSortedView.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * 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.datasketches.quantiles;
-
-import static java.lang.System.arraycopy;
-import static 
org.apache.datasketches.quantiles.DoublesSketchAccessor.BB_LVL_IDX;
-import static 
org.apache.datasketches.quantilescommon.QuantileSearchCriteria.INCLUSIVE;
-import static org.apache.datasketches.quantilescommon.QuantilesAPI.EMPTY_MSG;
-import static 
org.apache.datasketches.quantilescommon.QuantilesUtil.getNaturalRank;
-
-import java.util.Arrays;
-
-import org.apache.datasketches.common.SketchesArgumentException;
-import org.apache.datasketches.common.SketchesStateException;
-import org.apache.datasketches.quantilescommon.DoublesSortedView;
-import org.apache.datasketches.quantilescommon.DoublesSortedViewIterator;
-import org.apache.datasketches.quantilescommon.InequalitySearch;
-import org.apache.datasketches.quantilescommon.QuantileSearchCriteria;
-import org.apache.datasketches.quantilescommon.QuantilesUtil;
-
-/**
- * The SortedView of the Classic Quantiles DoublesSketch.
- * @author Alexander Saydakov
- * @author Lee Rhodes
- */
-public final class DoublesSketchSortedView implements DoublesSortedView {
-  private final double[] quantiles;
-  private final long[] cumWeights; //comes in as individual weights, converted 
to cumulative natural weights
-  private final long totalN;
-  private final double maxItem;
-  private final double minItem;
-
-  /**
-   * Construct from elements, also used in testing.
-   * @param quantiles sorted array of quantiles
-   * @param cumWeights sorted, monotonically increasing cumulative weights.
-   * @param totalN the total number of items presented to the sketch.
-   * @param maxItem of type double
-   * @param minItem of type double
-   */
-  DoublesSketchSortedView(final double[] quantiles, final long[] cumWeights, 
final long totalN,
-      final double maxItem, final double minItem) {
-    this.quantiles = quantiles;
-    this.cumWeights  = cumWeights;
-    this.totalN = totalN;
-    this.maxItem = maxItem;
-    this.minItem = minItem;
-  }
-
-  /**
-   * Constructs this Sorted View given the sketch
-   * @param sketch the given Classic Quantiles DoublesSketch
-   */
-  public DoublesSketchSortedView(final DoublesSketch sketch) {
-    if (sketch.isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
-    this.totalN = sketch.getN();
-    this.maxItem = sketch.getMaxItem();
-    this.minItem = sketch.getMinItem();
-    final int k = sketch.getK();
-    final int numQuantiles = sketch.getNumRetained();
-    quantiles = new double[numQuantiles];
-    cumWeights = new long[numQuantiles];
-    final DoublesSketchAccessor sketchAccessor = 
DoublesSketchAccessor.wrap(sketch);
-
-    // Populate from DoublesSketch:
-    //  copy over the "levels" and then the base buffer, all with appropriate 
weights
-    populateFromDoublesSketch(k, totalN, sketch.getBitPattern(), 
sketchAccessor, quantiles, cumWeights);
-
-    // Sort the first "numSamples" slots of the two arrays in tandem,
-    //  taking advantage of the already sorted blocks of length k
-    blockyTandemMergeSort(quantiles, cumWeights, numQuantiles, k);
-   if (convertToCumulative(cumWeights) != totalN) {
-     throw new SketchesStateException("Sorted View is misconfigured. TotalN 
does not match cumWeights.");
-   }
-  }
-
-  @Override
-  public long[] getCumulativeWeights() {
-    return cumWeights.clone();
-  }
-
-  @Override
-  public double getMaxItem() {
-    return maxItem;
-  }
-
-  @Override
-  public double getMinItem() {
-    return minItem;
-  }
-
-  @Override
-  public long getN() {
-    return totalN;
-  }
-
-  @Override
-  public double getQuantile(final double rank, final QuantileSearchCriteria 
searchCrit) {
-    if (isEmpty()) { throw new IllegalArgumentException(EMPTY_MSG); }
-    QuantilesUtil.checkNormalizedRankBounds(rank);
-    final int len = cumWeights.length;
-    final double naturalRank = getNaturalRank(rank, totalN, searchCrit);
-    final InequalitySearch crit = (searchCrit == INCLUSIVE) ? 
InequalitySearch.GE : InequalitySearch.GT;
-    final int index = InequalitySearch.find(cumWeights, 0, len - 1, 
naturalRank, crit);
-    if (index == -1) {
-      return quantiles[len - 1]; //EXCLUSIVE (GT) case: normRank == 1.0;
-    }
-    return quantiles[index];
-  }
-
-  @Override
-  public double getRank(final double quantile, final QuantileSearchCriteria 
searchCrit) {
-    if (isEmpty()) { throw new IllegalArgumentException(EMPTY_MSG); }
-    final int len = quantiles.length;
-    final InequalitySearch crit = (searchCrit == INCLUSIVE) ? 
InequalitySearch.LE : InequalitySearch.LT;
-    final int index = InequalitySearch.find(quantiles,  0, len - 1, quantile, 
crit);
-    if (index == -1) {
-      return 0; //EXCLUSIVE (LT) case: quantile <= minQuantile; INCLUSIVE (LE) 
case: quantile < minQuantile
-    }
-    return (double)cumWeights[index] / totalN;
-  }
-
-  @Override
-  public double[] getQuantiles() {
-    return quantiles.clone();
-  }
-
-  @Override
-  public boolean isEmpty() {
-    return totalN == 0;
-  }
-
-  @Override
-  public DoublesSortedViewIterator iterator() {
-    return new DoublesSortedViewIterator(quantiles, cumWeights);
-  }
-
-  //restricted methods
-
-  /**
-   * Populate the arrays and registers from a DoublesSketch
-   * @param k K parameter of the sketch
-   * @param n The current size of the stream
-   * @param bitPattern the bit pattern for valid log levels
-   * @param sketchAccessor A DoublesSketchAccessor around the sketch
-   * @param quantilesArr the consolidated array of all items from the sketch
-   * @param cumWtsArr populates this array with the raw individual weights 
from the sketch,
-   * it will be cumulative later.
-   */
-  private final static void populateFromDoublesSketch(
-          final int k, final long n, final long bitPattern,
-          final DoublesSketchAccessor sketchAccessor,
-          final double[] quantilesArr, final long[] cumWtsArr) {
-    long weight = 1;
-    int nxt = 0;
-    long bits = bitPattern;
-    assert bits == (n / (2L * k)); // internal consistency check
-    for (int lvl = 0; bits != 0L; lvl++, bits >>>= 1) {
-      weight *= 2;
-      if ((bits & 1L) > 0L) {
-        sketchAccessor.setLevel(lvl);
-        for (int i = 0; i < sketchAccessor.numItems(); i++) {
-          quantilesArr[nxt] = sketchAccessor.get(i);
-          cumWtsArr[nxt] = weight;
-          nxt++;
-        }
-      }
-    }
-
-    weight = 1; //NOT a mistake! We just copied the highest level; now we need 
to copy the base buffer
-    final int startOfBaseBufferBlock = nxt;
-
-    // Copy BaseBuffer over, along with weight = 1
-    sketchAccessor.setLevel(BB_LVL_IDX);
-    for (int i = 0; i < sketchAccessor.numItems(); i++) {
-      quantilesArr[nxt] = sketchAccessor.get(i);
-      cumWtsArr[nxt] = weight;
-      nxt++;
-    }
-    assert nxt == quantilesArr.length;
-
-    // Must sort the items that came from the base buffer.
-    // Don't need to sort the corresponding weights because they are all the 
same.
-    final int numSamples = nxt;
-    Arrays.sort(quantilesArr, startOfBaseBufferBlock, numSamples);
-  }
-
-  /**
-   * blockyTandemMergeSort() is an implementation of top-down merge sort 
specialized
-   * for the case where the input contains successive equal-length blocks
-   * that have already been sorted, so that only the top part of the
-   * merge tree remains to be executed. Also, two arrays are sorted in tandem,
-   * as discussed below.
-   * @param quantiles array of quantiles
-   * @param cumWts array of cum weights
-   * @param arrLen length of quantiles array and cumWts array
-   * @param blkSize size of internal sorted blocks
-   */
-  //used by this and UtilTest
-  static void blockyTandemMergeSort(final double[] quantiles, final long[] 
cumWts, final int arrLen,
-      final int blkSize) {
-    assert blkSize >= 1;
-    if (arrLen <= blkSize) { return; }
-    int numblks = arrLen / blkSize;
-    if ((numblks * blkSize) < arrLen) { numblks += 1; }
-    assert ((numblks * blkSize) >= arrLen);
-
-    // duplication of the input arrays is preparation for the "ping-pong" copy 
reduction strategy.
-    final double[] qSrc = Arrays.copyOf(quantiles, arrLen);
-    final long[] cwSrc   = Arrays.copyOf(cumWts, arrLen);
-
-    blockyTandemMergeSortRecursion(qSrc, cwSrc,
-                                   quantiles, cumWts,
-                                   0, numblks,
-                                   blkSize, arrLen);
-  }
-
-  /**
-   *  blockyTandemMergeSortRecursion() is called by blockyTandemMergeSort().
-   *  In addition to performing the algorithm's top down recursion,
-   *  it manages the buffer swapping that eliminates most copying.
-   *  It also maps the input's pre-sorted blocks into the subarrays
-   *  that are processed by tandemMerge().
-   * @param qSrc source array of quantiles
-   * @param cwSrc source weights array
-   * @param qDst destination quantiles array
-   * @param cwDst destination weights array
-   * @param grpStart group start, refers to pre-sorted blocks such as block 0, 
block 1, etc.
-   * @param grpLen group length, refers to pre-sorted blocks such as block 0, 
block 1, etc.
-   * @param blkSize block size
-   * @param arrLim array limit
-   */
-  private static void blockyTandemMergeSortRecursion(final double[] qSrc, 
final long[] cwSrc,
-      final double[] qDst, final long[] cwDst, final int grpStart, final int 
grpLen,
-      /* indices of blocks */ final int blkSize, final int arrLim) {
-    // Important note: grpStart and grpLen do NOT refer to positions in the 
underlying array.
-    // Instead, they refer to the pre-sorted blocks, such as block 0, block 1, 
etc.
-
-    assert (grpLen > 0);
-    if (grpLen == 1) { return; }
-    final int grpLen1 = grpLen / 2;
-    final int grpLen2 = grpLen - grpLen1;
-    assert (grpLen1 >= 1);
-    assert (grpLen2 >= grpLen1);
-
-    final int grpStart1 = grpStart;
-    final int grpStart2 = grpStart + grpLen1;
-
-    //swap roles of src and dst
-    blockyTandemMergeSortRecursion(qDst, cwDst,
-                           qSrc, cwSrc,
-                           grpStart1, grpLen1, blkSize, arrLim);
-
-    //swap roles of src and dst
-    blockyTandemMergeSortRecursion(qDst, cwDst,
-                           qSrc, cwSrc,
-                           grpStart2, grpLen2, blkSize, arrLim);
-
-    // here we convert indices of blocks into positions in the underlying 
array.
-    final int arrStart1 = grpStart1 * blkSize;
-    final int arrStart2 = grpStart2 * blkSize;
-    final int arrLen1   = grpLen1   * blkSize;
-    int arrLen2         = grpLen2   * blkSize;
-
-    // special case for the final block which might be shorter than blkSize.
-    if ((arrStart2 + arrLen2) > arrLim) { arrLen2 = arrLim - arrStart2; }
-
-    tandemMerge(qSrc, cwSrc,
-                arrStart1, arrLen1,
-                arrStart2, arrLen2,
-                qDst, cwDst,
-                arrStart1); // which will be arrStart3
-  }
-
-  /**
-   *  Performs two merges in tandem. One of them provides the sort keys
-   *  while the other one passively undergoes the same data motion.
-   * @param qSrc quantiles source
-   * @param cwSrc cumulative weights source
-   * @param arrStart1 Array 1 start offset
-   * @param arrLen1 Array 1 length
-   * @param arrStart2 Array 2 start offset
-   * @param arrLen2 Array 2 length
-   * @param qDst quantiles destination
-   * @param cwDst cumulative weights destination
-   * @param arrStart3 Array 3 start offset
-   */
-  private static void tandemMerge(final double[] qSrc, final long[] cwSrc,
-                                  final int arrStart1, final int arrLen1,
-                                  final int arrStart2, final int arrLen2,
-                                  final double[] qDst, final long[] cwDst,
-                                  final int arrStart3) {
-    final int arrStop1 = arrStart1 + arrLen1;
-    final int arrStop2 = arrStart2 + arrLen2;
-
-    int i1 = arrStart1;
-    int i2 = arrStart2;
-    int i3 = arrStart3;
-    while ((i1 < arrStop1) && (i2 < arrStop2)) {
-      if (qSrc[i2] < qSrc[i1]) {
-        qDst[i3] = qSrc[i2];
-        cwDst[i3] = cwSrc[i2];
-        i2++;
-      } else {
-        qDst[i3] = qSrc[i1];
-        cwDst[i3] = cwSrc[i1];
-        i1++;
-      }
-      i3++;
-    }
-
-    if (i1 < arrStop1) {
-      arraycopy(qSrc, i1, qDst, i3, arrStop1 - i1);
-      arraycopy(cwSrc, i1, cwDst, i3, arrStop1 - i1);
-    } else {
-      assert i2 < arrStop2;
-      arraycopy(qSrc, i2, qDst, i3, arrStop2 - i2);
-      arraycopy(cwSrc, i2, cwDst, i3, arrStop2 - i2);
-    }
-  }
-
-  /**
-   * Convert the individual weights into cumulative weights.
-   * An array of {1,1,1,1} becomes {1,2,3,4}
-   * @param array of actual weights from the sketch, none of the weights may 
be zero
-   * @return total weight
-   */
-  private static long convertToCumulative(final long[] array) {
-    long subtotal = 0;
-    for (int i = 0; i < array.length; i++) {
-      final long newSubtotal = subtotal + array[i];
-      subtotal = array[i] = newSubtotal;
-    }
-    return subtotal;
-  }
-
-}
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/DoublesUnionImpl.java 
b/src/main/java/org/apache/datasketches/quantiles/DoublesUnionImpl.java
index b55f0b53..38854d3f 100644
--- a/src/main/java/org/apache/datasketches/quantiles/DoublesUnionImpl.java
+++ b/src/main/java/org/apache/datasketches/quantiles/DoublesUnionImpl.java
@@ -123,14 +123,14 @@ final class DoublesUnionImpl extends DoublesUnionImplR {
   public void union(final DoublesSketch sketchIn) {
     Objects.requireNonNull(sketchIn);
     gadget_ = updateLogic(maxK_, gadget_, sketchIn);
-    gadget_.classicQdsSV = null;
+    gadget_.doublesSV = null;
   }
 
   @Override
   public void union(final Memory mem) {
     Objects.requireNonNull(mem);
     gadget_ = updateLogic(maxK_, gadget_, DoublesSketch.wrap(mem));
-    gadget_.classicQdsSV = null;
+    gadget_.doublesSV = null;
   }
 
   @Override
@@ -139,7 +139,7 @@ final class DoublesUnionImpl extends DoublesUnionImplR {
       gadget_ = HeapUpdateDoublesSketch.newInstance(maxK_);
     }
     gadget_.update(quantile);
-    gadget_.classicQdsSV = null;
+    gadget_.doublesSV = null;
   }
 
   @Override
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/HeapUpdateDoublesSketch.java 
b/src/main/java/org/apache/datasketches/quantiles/HeapUpdateDoublesSketch.java
index 8282f00c..2197d8b8 100644
--- 
a/src/main/java/org/apache/datasketches/quantiles/HeapUpdateDoublesSketch.java
+++ 
b/src/main/java/org/apache/datasketches/quantiles/HeapUpdateDoublesSketch.java
@@ -270,7 +270,7 @@ final class HeapUpdateDoublesSketch extends 
UpdateDoublesSketch {
       baseBufferCount_ = newBBCount;
     }
     n_ = newN;
-    classicQdsSV = null;
+    doublesSV = null;
   }
 
   /**
diff --git a/src/main/java/org/apache/datasketches/quantiles/ItemsSketch.java 
b/src/main/java/org/apache/datasketches/quantiles/ItemsSketch.java
index 54795d7a..13aee81e 100644
--- a/src/main/java/org/apache/datasketches/quantiles/ItemsSketch.java
+++ b/src/main/java/org/apache/datasketches/quantiles/ItemsSketch.java
@@ -530,12 +530,6 @@ public final class ItemsSketch<T> implements 
QuantilesGenericAPI<T> {
     dstMem.putByteArray(0, byteArr, 0, byteArr.length);
   }
 
-  @Override
-  public ItemsSketchSortedView<T> getSortedView() {
-    if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
-    return refreshSortedView();
-  }
-
   @Override
   public void update(final T item) {
     // this method only uses the base buffer part of the combined buffer
@@ -631,69 +625,84 @@ public final class ItemsSketch<T> implements 
QuantilesGenericAPI<T> {
     sketch.combinedBuffer_ = Arrays.copyOf(baseBuffer, newSize);
   }
 
+  //************SORTED VIEW****************************
+
+  @Override
+  public ItemsSketchSortedView<T> getSortedView() {
+    return refreshSortedView();
+  }
+
   private final ItemsSketchSortedView<T> refreshSortedView() {
-    if (classicQisSV == null) {
-      final CreateSortedView csv = new CreateSortedView();
-      classicQisSV = csv.getSV();
-    }
-    return classicQisSV;
-  }
-
-  @SuppressWarnings({"rawtypes","unchecked"})
-  private final class CreateSortedView {
-    final long n = getN();
-    final int numQuantiles = getNumRetained();
-    final T[] quantiles = (T[]) Array.newInstance(clazz, numQuantiles);
-    long[] cumWeights = new long[numQuantiles];
-    final int k = getK();
-
-    final T[] combinedBuffer = (T[]) getCombinedBuffer();
-    final int baseBufferCount = getBaseBufferCount();
-    final Comparator<? super T> comparator = ItemsSketch.this.comparator_;
-
-    ItemsSketchSortedView<T> getSV() {
-      long weight = 1;
-      int index = 0;
-      long bits = getBitPattern();
-      assert bits == (n / (2L * k)); // internal consistency check
-      for (int lvl = 0; bits != 0L; lvl++, bits >>>= 1) {
-        weight *= 2;
-        if ((bits & 1L) > 0L) {
-          final int offset = (2 + lvl) * k;
-          for (int i = 0; i < k; i++) {
-            quantiles[index] = combinedBuffer[i + offset];
-            cumWeights[index] = weight;
-            index++;
-          }
-        }
-      }
+    return (classicQisSV == null) ? (classicQisSV = getSV(this)) : 
classicQisSV;
+  }
 
-      weight = 1; //NOT a mistake! We just copied the highest level; now we 
need to copy the base buffer
-      final int startOfBaseBufferBlock = index;
+  @SuppressWarnings({"unchecked"})
+  private static <T> ItemsSketchSortedView<T> getSV(final ItemsSketch<T> sk) {
+    final long totalN = sk.getN();
+    if (sk.isEmpty() || (totalN == 0)) { throw new 
SketchesArgumentException(EMPTY_MSG); }
+    final int k = sk.getK();
+    final int numQuantiles = sk.getNumRetained();
+    final T[] svQuantiles = (T[]) Array.newInstance(sk.clazz, numQuantiles);
+    final long[] svCumWeights = new long[numQuantiles];
+    final Comparator<? super T> comparator = sk.comparator_;
 
-      // Copy BaseBuffer over, along with weight = 1
-      for (int i = 0; i < baseBufferCount; i++) {
-        quantiles[index] = combinedBuffer[i];
-        cumWeights[index] = weight;
-        index++;
-      }
-      assert index == numQuantiles;
+    final T[] combinedBuffer = (T[]) sk.getCombinedBuffer();
+    final int baseBufferCount = sk.getBaseBufferCount();
+
+    // Populate from ItemsSketch:
+    // copy over the "levels" and then the base buffer, all with appropriate 
weights
+    populateFromItemsSketch(k, totalN, sk.getBitPattern(), combinedBuffer, 
baseBufferCount,
+        numQuantiles, svQuantiles, svCumWeights, sk.getComparator());
+
+    // Sort the first "numSamples" slots of the two arrays in tandem,
+    // taking advantage of the already sorted blocks of length k
+    ItemsMergeImpl.blockyTandemMergeSort(svQuantiles, svCumWeights, 
numQuantiles, k, comparator);
+
+    if (convertToCumulative(svCumWeights) != totalN) {
+      throw new SketchesStateException("Sorted View is misconfigured. TotalN 
does not match cumWeights.");
+    }
+
+    final double normRankErr = getNormalizedRankError(sk.getK(), true);
+    return new ItemsSketchSortedView<>(
+        svQuantiles, svCumWeights, sk.getN(), comparator, sk.getMaxItem(), 
sk.getMinItem(), normRankErr);
 
-      // Must sort the items that came from the base buffer.
-      // Don't need to sort the corresponding weights because they are all the 
same.
-      Arrays.sort(quantiles, startOfBaseBufferBlock, numQuantiles, comparator);
+  }
 
-      // Sort the first "numSamples" slots of the two arrays in tandem,
-      // taking advantage of the already sorted blocks of length k
-      ItemsMergeImpl.blockyTandemMergeSort(quantiles, cumWeights, 
numQuantiles, k, comparator);
+  private final static <T> void populateFromItemsSketch(
+      final int k, final long totalN, final long bitPattern, final T[] 
combinedBuffer,
+      final int baseBufferCount, final int numQuantiles, final T[] 
svQuantiles, final long[] svCumWeights,
+      final Comparator<? super T> comparator) {
 
-      if (convertToCumulative(cumWeights) != n) {
-        throw new SketchesStateException("Sorted View is misconfigured. TotalN 
does not match cumWeights.");
+    long weight = 1;
+    int index = 0;
+    long bits = bitPattern;
+    assert bits == (totalN / (2L * k)); // internal consistency check
+    for (int lvl = 0; bits != 0L; lvl++, bits >>>= 1) {
+      weight <<= 1; // X2
+      if ((bits & 1L) > 0L) {
+        final int offset = (2 + lvl) * k;
+        for (int i = 0; i < k; i++) {
+          svQuantiles[index] = combinedBuffer[i + offset];
+          svCumWeights[index] = weight;
+          index++;
+        }
       }
-      final double normRankErr = getNormalizedRankError(getK(), true);
-      return new ItemsSketchSortedView(
-          quantiles, cumWeights, getN(), comparator, getMaxItem(), 
getMinItem(), normRankErr);
     }
+
+    weight = 1; //NOT a mistake! We just copied the highest level; now we need 
to copy the base buffer
+    final int startOfBaseBufferBlock = index;
+
+    // Copy BaseBuffer over, along with weight = 1
+    for (int i = 0; i < baseBufferCount; i++) {
+      svQuantiles[index] = combinedBuffer[i];
+      svCumWeights[index] = weight;
+      index++;
+    }
+    assert index == numQuantiles;
+
+    // Must sort the items that came from the base buffer.
+    // Don't need to sort the corresponding weights because they are all the 
same.
+    Arrays.sort(svQuantiles, startOfBaseBufferBlock, numQuantiles, comparator);
   }
 
   /**
diff --git 
a/src/main/java/org/apache/datasketches/quantiles/KolmogorovSmirnov.java 
b/src/main/java/org/apache/datasketches/quantiles/KolmogorovSmirnov.java
index c290b059..6b8079ea 100644
--- a/src/main/java/org/apache/datasketches/quantiles/KolmogorovSmirnov.java
+++ b/src/main/java/org/apache/datasketches/quantiles/KolmogorovSmirnov.java
@@ -19,6 +19,8 @@
 
 package org.apache.datasketches.quantiles;
 
+import org.apache.datasketches.quantilescommon.DoublesSketchSortedView;
+
 /**
  * Kolmogorov-Smirnov Test
  * See <a 
href="https://en.wikipedia.org/wiki/Kolmogorov-Smirnov_test";>Kolmogorov–Smirnov 
Test</a>
@@ -36,8 +38,8 @@ final class KolmogorovSmirnov {
    * @return the raw delta area between two quantile sketches
    */
   public static double computeKSDelta(final DoublesSketch sketch1, final 
DoublesSketch sketch2) {
-    final DoublesSketchSortedView p = new DoublesSketchSortedView(sketch1);
-    final DoublesSketchSortedView q = new DoublesSketchSortedView(sketch2);
+    final DoublesSketchSortedView p = sketch1.getSortedView();
+    final DoublesSketchSortedView q = sketch2.getSortedView();
 
     final double[] pSamplesArr = p.getQuantiles();
     final double[] qSamplesArr = q.getQuantiles();
diff --git 
a/src/main/java/org/apache/datasketches/quantilescommon/DoublesSketchSortedView.java
 
b/src/main/java/org/apache/datasketches/quantilescommon/DoublesSketchSortedView.java
new file mode 100644
index 00000000..b0332369
--- /dev/null
+++ 
b/src/main/java/org/apache/datasketches/quantilescommon/DoublesSketchSortedView.java
@@ -0,0 +1,118 @@
+/*
+ * 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.datasketches.quantilescommon;
+
+import static 
org.apache.datasketches.quantilescommon.QuantileSearchCriteria.INCLUSIVE;
+import static org.apache.datasketches.quantilescommon.QuantilesAPI.EMPTY_MSG;
+import static 
org.apache.datasketches.quantilescommon.QuantilesUtil.getNaturalRank;
+
+import org.apache.datasketches.common.SketchesArgumentException;
+
+/**
+ * The SortedView of the Quantiles Classic DoublesSketch and the 
KllDoublesSketch.
+ * @author Alexander Saydakov
+ * @author Lee Rhodes
+ */
+public final class DoublesSketchSortedView implements DoublesSortedView {
+  private final double[] quantiles;
+  private final long[] cumWeights; //comes in as individual weights, converted 
to cumulative natural weights
+  private final long totalN;
+  private final double maxItem;
+  private final double minItem;
+
+  /**
+   * Construct from elements, also used in testing.
+   * @param quantiles sorted array of quantiles
+   * @param cumWeights sorted, monotonically increasing cumulative weights.
+   * @param totalN the total number of items presented to the sketch.
+   * @param maxItem of type double
+   * @param minItem of type double
+   */
+  public DoublesSketchSortedView(final double[] quantiles, final long[] 
cumWeights, final long totalN,
+      final double maxItem, final double minItem) {
+    this.quantiles = quantiles;
+    this.cumWeights  = cumWeights;
+    this.totalN = totalN;
+    this.maxItem = maxItem;
+    this.minItem = minItem;
+  }
+
+  @Override
+  public long[] getCumulativeWeights() {
+    return cumWeights.clone();
+  }
+
+  @Override
+  public double getMaxItem() {
+    return maxItem;
+  }
+
+  @Override
+  public double getMinItem() {
+    return minItem;
+  }
+
+  @Override
+  public long getN() {
+    return totalN;
+  }
+
+  @Override
+  public double getQuantile(final double rank, final QuantileSearchCriteria 
searchCrit) {
+    if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
+    QuantilesUtil.checkNormalizedRankBounds(rank);
+    final int len = cumWeights.length;
+    final double naturalRank = getNaturalRank(rank, totalN, searchCrit);
+    final InequalitySearch crit = (searchCrit == INCLUSIVE) ? 
InequalitySearch.GE : InequalitySearch.GT;
+    final int index = InequalitySearch.find(cumWeights, 0, len - 1, 
naturalRank, crit);
+    if (index == -1) {
+      return quantiles[len - 1]; //EXCLUSIVE (GT) case: normRank == 1.0;
+    }
+    return quantiles[index];
+  }
+
+  @Override
+  public double[] getQuantiles() {
+    return quantiles.clone();
+  }
+
+  @Override
+  public double getRank(final double quantile, final QuantileSearchCriteria 
searchCrit) {
+    if (isEmpty()) { throw new SketchesArgumentException(EMPTY_MSG); }
+    final int len = quantiles.length;
+    final InequalitySearch crit = (searchCrit == INCLUSIVE) ? 
InequalitySearch.LE : InequalitySearch.LT;
+    final int index = InequalitySearch.find(quantiles,  0, len - 1, quantile, 
crit);
+    if (index == -1) {
+      return 0; //EXCLUSIVE (LT) case: quantile <= minQuantile; INCLUSIVE (LE) 
case: quantile < minQuantile
+    }
+    return (double)cumWeights[index] / totalN;
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return totalN == 0;
+  }
+
+  @Override
+  public DoublesSortedViewIterator iterator() {
+    return new DoublesSortedViewIterator(quantiles, cumWeights);
+  }
+
+}
diff --git 
a/src/test/java/org/apache/datasketches/quantiles/CustomQuantilesTest.java 
b/src/test/java/org/apache/datasketches/quantiles/CustomQuantilesTest.java
index d3193883..101c26cd 100644
--- a/src/test/java/org/apache/datasketches/quantiles/CustomQuantilesTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/CustomQuantilesTest.java
@@ -26,6 +26,7 @@ import static 
org.apache.datasketches.quantilescommon.QuantileSearchCriteria.INC
 import static 
org.apache.datasketches.quantilescommon.QuantilesUtil.getNaturalRank;
 import static org.testng.Assert.assertEquals;
 
+import org.apache.datasketches.quantilescommon.DoublesSketchSortedView;
 import org.testng.annotations.Test;
 
 public class CustomQuantilesTest {
@@ -55,7 +56,7 @@ public class CustomQuantilesTest {
       }
     }
     long N = sk.getN();
-    DoublesSketchSortedView sv = new DoublesSketchSortedView(sk);
+    DoublesSketchSortedView sv = sk.getSortedView();
     double[] quantilesArr = sv.getQuantiles();
     long[] cumWtsArr = sv.getCumulativeWeights();
     int lenQ = quantilesArr.length;
diff --git a/src/test/java/org/apache/datasketches/quantiles/UtilTest.java 
b/src/test/java/org/apache/datasketches/quantiles/UtilTest.java
index 0ca3ea42..49546df5 100644
--- a/src/test/java/org/apache/datasketches/quantiles/UtilTest.java
+++ b/src/test/java/org/apache/datasketches/quantiles/UtilTest.java
@@ -165,7 +165,6 @@ public class UtilTest {
  }
 
  /**
-  *
   * @param numTries number of tries
   * @param maxArrLen maximum length of array size
   */
@@ -178,7 +177,7 @@ public class UtilTest {
          arr = makeMergeTestInput(arrLen, blkSize);
          long [] brr = makeTheTandemArray(arr);
          assertMergeTestPrecondition(arr, brr, arrLen, blkSize);
-         DoublesSketchSortedView.blockyTandemMergeSort(arr, brr, arrLen, 
blkSize);
+         DoublesSketch.blockyTandemMergeSort(arr, brr, arrLen, blkSize);
          /* verify sorted order */
          for (int i = 0; i < (arrLen-1); i++) {
            assert arr[i] <= arr[i+1];
diff --git 
a/src/test/java/org/apache/datasketches/quantilescommon/CrossCheckQuantilesTest.java
 
b/src/test/java/org/apache/datasketches/quantilescommon/CrossCheckQuantilesTest.java
index dbbbb656..6049f2f3 100644
--- 
a/src/test/java/org/apache/datasketches/quantilescommon/CrossCheckQuantilesTest.java
+++ 
b/src/test/java/org/apache/datasketches/quantilescommon/CrossCheckQuantilesTest.java
@@ -29,8 +29,7 @@ import static 
org.apache.datasketches.quantilescommon.LinearRanksAndQuantiles.ge
 import static 
org.apache.datasketches.quantilescommon.LinearRanksAndQuantiles.getTrueItemRank;
 import static 
org.apache.datasketches.quantilescommon.QuantileSearchCriteria.EXCLUSIVE;
 import static 
org.apache.datasketches.quantilescommon.QuantileSearchCriteria.INCLUSIVE;
-import static 
org.apache.datasketches.quantilescommon.ReflectUtilityTest.CLASSIC_DOUBLES_SV_CTOR;
-import static 
org.apache.datasketches.quantilescommon.ReflectUtilityTest.KLL_DOUBLES_SV_CTOR;
+import static 
org.apache.datasketches.quantilescommon.ReflectUtilityTest.DOUBLES_SV_CTOR;
 import static 
org.apache.datasketches.quantilescommon.ReflectUtilityTest.KLL_FLOATS_SV_CTOR;
 import static 
org.apache.datasketches.quantilescommon.ReflectUtilityTest.REQ_SV_CTOR;
 import static org.testng.Assert.assertEquals;
@@ -40,13 +39,11 @@ import java.util.Comparator;
 import org.apache.datasketches.common.ArrayOfStringsSerDe;
 import org.apache.datasketches.common.SketchesArgumentException;
 import org.apache.datasketches.kll.KllDoublesSketch;
-import org.apache.datasketches.kll.KllDoublesSketchSortedView;
 import org.apache.datasketches.kll.KllFloatsSketch;
 import org.apache.datasketches.kll.KllFloatsSketchSortedView;
 import org.apache.datasketches.kll.KllItemsSketch;
 import org.apache.datasketches.kll.KllSketch;
 import org.apache.datasketches.quantiles.DoublesSketch;
-import org.apache.datasketches.quantiles.DoublesSketchSortedView;
 import org.apache.datasketches.quantiles.ItemsSketch;
 import org.apache.datasketches.quantiles.UpdateDoublesSketch;
 import org.apache.datasketches.req.ReqSketch;
@@ -146,10 +143,10 @@ public class CrossCheckQuantilesTest {
 
   ReqSketchSortedView reqFloatsSV = null;
   KllFloatsSketchSortedView kllFloatsSV = null;
-  KllDoublesSketchSortedView kllDoublesSV = null;
+  DoublesSketchSortedView kllDoublesSV = null;
   DoublesSketchSortedView classicDoublesSV = null;
   ItemsSketchSortedView<String> kllItemsSV = null;
-  ItemsSketchSortedView<String> itemsSV = null;
+  ItemsSketchSortedView<String> classicItemsSV = null;
 
   public CrossCheckQuantilesTest() {}
 
@@ -221,7 +218,7 @@ public class CrossCheckQuantilesTest {
       testRank = kllItemsSk.getRank(s, crit);
       assertEquals(testRank, trueRank);
 
-      testRank = itemsSV.getRank(s, crit);
+      testRank = classicItemsSV.getRank(s, crit);
       assertEquals(testRank, trueRank);
       testRank = itemsSk.getRank(s, crit);
       assertEquals(testRank, trueRank);
@@ -286,7 +283,7 @@ public class CrossCheckQuantilesTest {
       testIQ = kllItemsSk.getQuantile(normRank, crit);
       assertEquals(testIQ, trueIQ);
 
-      testIQ = itemsSV.getQuantile(normRank, crit);
+      testIQ = classicItemsSV.getQuantile(normRank, crit);
       assertEquals(testIQ, trueIQ);
       testIQ = itemsSk.getQuantile(normRank, crit);
       assertEquals(testIQ, trueIQ);
@@ -339,9 +336,9 @@ public class CrossCheckQuantilesTest {
         svMaxFValues[set], svMinFValues[set]);
     kllFloatsSV = getRawKllFloatsSV(svFValues[set], svCumWeights[set], 
totalN[set],
         svMaxFValues[set], svMinFValues[set]);
-    kllDoublesSV = getRawKllDoublesSV(svDValues[set], svCumWeights[set], 
totalN[set],
+    kllDoublesSV = getRawDoublesSV(svDValues[set], svCumWeights[set], 
totalN[set],
         svMaxDValues[set], svMinDValues[set]);
-    classicDoublesSV = getRawClassicDoublesSV(svDValues[set], 
svCumWeights[set], totalN[set],
+    classicDoublesSV = getRawDoublesSV(svDValues[set], svCumWeights[set], 
totalN[set],
         svMaxDValues[set], svMinDValues[set]);
     String svImax = svIValues[set][svIValues[set].length - 1];
     String svImin = svIValues[set][0];
@@ -349,7 +346,7 @@ public class CrossCheckQuantilesTest {
     kllItemsSV = new ItemsSketchSortedView<>(svIValues[set], 
svCumWeights[set], totalN[set],
         comparator, svImax, svImin, normRankErr);
     normRankErr = ItemsSketch.getNormalizedRankError(k, true);
-    itemsSV = new ItemsSketchSortedView<>(svIValues[set], svCumWeights[set], 
totalN[set],
+    classicItemsSV = new ItemsSketchSortedView<>(svIValues[set], 
svCumWeights[set], totalN[set],
         comparator, svImax, svImin, normRankErr);
   }
 
@@ -365,16 +362,10 @@ public class CrossCheckQuantilesTest {
     return (KllFloatsSketchSortedView) KLL_FLOATS_SV_CTOR.newInstance(values, 
cumWeights, totalN, maxItem, minItem);
   }
 
-  private final static KllDoublesSketchSortedView getRawKllDoublesSV(
+  private final static DoublesSketchSortedView getRawDoublesSV(
       final double[] values, final long[] cumWeights, final long totalN, final 
double maxItem, final double minItem)
           throws Exception {
-    return (KllDoublesSketchSortedView) 
KLL_DOUBLES_SV_CTOR.newInstance(values, cumWeights, totalN, maxItem, minItem);
-  }
-
-  private final static DoublesSketchSortedView getRawClassicDoublesSV(
-      final double[] values, final long[] cumWeights, final long totalN, final 
double maxItem, final double minItem)
-          throws Exception {
-    return (DoublesSketchSortedView) 
CLASSIC_DOUBLES_SV_CTOR.newInstance(values, cumWeights, totalN, maxItem, 
minItem);
+    return (DoublesSketchSortedView) DOUBLES_SV_CTOR.newInstance(values, 
cumWeights, totalN, maxItem, minItem);
   }
 
   /********BUILD DATA SETS**********/
diff --git 
a/src/test/java/org/apache/datasketches/quantilescommon/ReflectUtilityTest.java 
b/src/test/java/org/apache/datasketches/quantilescommon/ReflectUtilityTest.java
index 191629fb..6dbcac2d 100644
--- 
a/src/test/java/org/apache/datasketches/quantilescommon/ReflectUtilityTest.java
+++ 
b/src/test/java/org/apache/datasketches/quantilescommon/ReflectUtilityTest.java
@@ -36,28 +36,23 @@ public final class ReflectUtilityTest {
 
   static final Class<?> REQ_SV;
   static final Class<?> KLL_FLOATS_SV;
-  static final Class<?> KLL_DOUBLES_SV;
-  static final Class<?> CLASSIC_DOUBLES_SV;
+  static final Class<?> DOUBLES_SV;
 
   static final Constructor<?> REQ_SV_CTOR;
   static final Constructor<?> KLL_FLOATS_SV_CTOR;
-  static final Constructor<?> KLL_DOUBLES_SV_CTOR;
-  static final Constructor<?> CLASSIC_DOUBLES_SV_CTOR;
+  static final Constructor<?> DOUBLES_SV_CTOR;
 
   static {
     REQ_SV = getClass("org.apache.datasketches.req.ReqSketchSortedView");
     KLL_FLOATS_SV = 
getClass("org.apache.datasketches.kll.KllFloatsSketchSortedView");
-    KLL_DOUBLES_SV = 
getClass("org.apache.datasketches.kll.KllDoublesSketchSortedView");
-    CLASSIC_DOUBLES_SV = 
getClass("org.apache.datasketches.quantiles.DoublesSketchSortedView");
+    DOUBLES_SV = 
getClass("org.apache.datasketches.quantilescommon.DoublesSketchSortedView");
 
     REQ_SV_CTOR =
         getConstructor(REQ_SV, float[].class, long[].class, long.class, 
float.class, float.class);
     KLL_FLOATS_SV_CTOR =
         getConstructor(KLL_FLOATS_SV, float[].class, long[].class, long.class, 
float.class, float.class);
-    KLL_DOUBLES_SV_CTOR =
-        getConstructor(KLL_DOUBLES_SV, double[].class, long[].class, 
long.class, double.class, double.class);
-    CLASSIC_DOUBLES_SV_CTOR =
-        getConstructor(CLASSIC_DOUBLES_SV, double[].class, long[].class, 
long.class, double.class, double.class);
+    DOUBLES_SV_CTOR =
+        getConstructor(DOUBLES_SV, double[].class, long[].class, long.class, 
double.class, double.class);
   }
 
   @Test //Example


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to