• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / datasketches-java / #306

30 Apr 2024 10:01PM UTC coverage: 97.645% (-0.5%) from 98.139%
#306

push

web-flow
Merge pull request #555 from apache/fix_pom_xml_header

Fix pom xml header

26865 of 27513 relevant lines covered (97.64%)

0.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.04
/src/main/java/org/apache/datasketches/quantiles/DoublesUnionImpl.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19

20
package org.apache.datasketches.quantiles;
21

22
import static org.apache.datasketches.quantiles.DoublesUtil.copyToHeap;
23

24
import java.util.Objects;
25

26
import org.apache.datasketches.memory.Memory;
27
import org.apache.datasketches.memory.WritableMemory;
28

29
/**
30
 * Union operation for on-heap.
31
 *
32
 * @author Lee Rhodes
33
 * @author Kevin Lang
34
 */
35
final class DoublesUnionImpl extends DoublesUnionImplR {
1✔
36

37
  private DoublesUnionImpl(final int maxK) {
38
    super(maxK);
1✔
39
  }
1✔
40

41
  /**
42
   * Returns a empty Heap DoublesUnion object.
43
   * @param maxK determines the accuracy and size of the union and is a maximum.
44
   * The effective <i>k</i> can be smaller due to unions with smaller <i>k</i> sketches.
45
   * It is recommended that <i>maxK</i> be a power of 2 to enable unioning of sketches with
46
   * different <i>k</i>.
47
   * @return a new DoublesUnionImpl on the Java heap
48
   */
49
  static DoublesUnionImpl heapInstance(final int maxK) {
50
    return new DoublesUnionImpl(maxK);
1✔
51
  }
52

53
  /**
54
   * Returns a empty DoublesUnion object that refers to the given direct, off-heap Memory,
55
   * which will be initialized to the empty state.
56
   *
57
   * @param maxK determines the accuracy and size of the union and is a maximum.
58
   * The effective <i>k</i> can be smaller due to unions with smaller <i>k</i> sketches.
59
   * It is recommended that <i>maxK</i> be a power of 2 to enable unioning of sketches with
60
   * different <i>k</i>.
61
   * @param dstMem the Memory to be used by the sketch
62
   * @return a DoublesUnion object
63
   */
64
  static DoublesUnionImpl directInstance(final int maxK, final WritableMemory dstMem) {
65
    Objects.requireNonNull(dstMem);
1✔
66
    final DirectUpdateDoublesSketch sketch = DirectUpdateDoublesSketch.newInstance(maxK, dstMem);
1✔
67
    final DoublesUnionImpl union = new DoublesUnionImpl(maxK);
1✔
68
    union.maxK_ = maxK;
1✔
69
    union.gadget_ = sketch;
1✔
70
    return union;
1✔
71
  }
72

73
  /**
74
   * Returns a Heap DoublesUnion object that has been initialized with the data from the given
75
   * sketch.
76
   *
77
   * @param sketch A DoublesSketch to be used as a source of data only and will not be modified.
78
   * @return a DoublesUnion object
79
   */
80
  static DoublesUnionImpl heapifyInstance(final DoublesSketch sketch) {
81
    Objects.requireNonNull(sketch);
1✔
82
    final int k = sketch.getK();
1✔
83
    final DoublesUnionImpl union = new DoublesUnionImpl(k);
1✔
84
    union.maxK_ = k;
1✔
85
    union.gadget_ = copyToHeap(sketch);
1✔
86
    return union;
1✔
87
  }
88

89
  /**
90
   * Returns a Heap DoublesUnion object that has been initialized with the data from the given
91
   * Memory image of a DoublesSketch. The srcMem object will not be modified and a reference to
92
   * it is not retained. The <i>maxK</i> of the resulting union will be that obtained from
93
   * the sketch Memory image.
94
   *
95
   * @param srcMem a Memory image of a quantiles DoublesSketch
96
   * @return a DoublesUnion object
97
   */
98
  static DoublesUnionImpl heapifyInstance(final Memory srcMem) {
99
    Objects.requireNonNull(srcMem);
1✔
100
    final HeapUpdateDoublesSketch sketch = HeapUpdateDoublesSketch.heapifyInstance(srcMem);
1✔
101
    final DoublesUnionImpl union = new DoublesUnionImpl(sketch.getK());
1✔
102
    union.gadget_ = sketch;
1✔
103
    return union;
1✔
104
  }
105

106
  /**
107
   * Returns an updatable Union object that wraps off-heap data structure of the given memory
108
   * image of a non-compact DoublesSketch. The data structures of the Union remain off-heap.
109
   *
110
   * @param mem A memory image of a non-compact DoublesSketch to be used as the data
111
   * structure for the union and will be modified.
112
   * @return a Union object
113
   */
114
  static DoublesUnionImpl wrapInstance(final WritableMemory mem) {
115
    Objects.requireNonNull(mem);
1✔
116
    final DirectUpdateDoublesSketch sketch = DirectUpdateDoublesSketch.wrapInstance(mem);
1✔
117
    final DoublesUnionImpl union = new DoublesUnionImpl(sketch.getK());
1✔
118
    union.gadget_ = sketch;
1✔
119
    return union;
1✔
120
  }
121

122
  @Override
123
  public void union(final DoublesSketch sketchIn) {
124
    Objects.requireNonNull(sketchIn);
1✔
125
    gadget_ = updateLogic(maxK_, gadget_, sketchIn);
1✔
126
    gadget_.doublesSV = null;
1✔
127
  }
1✔
128

129
  @Override
130
  public void union(final Memory mem) {
131
    Objects.requireNonNull(mem);
1✔
132
    gadget_ = updateLogic(maxK_, gadget_, DoublesSketch.wrap(mem));
1✔
133
    gadget_.doublesSV = null;
1✔
134
  }
1✔
135

136
  @Override
137
  public void update(final double quantile) {
138
    if (gadget_ == null) {
1✔
139
      gadget_ = HeapUpdateDoublesSketch.newInstance(maxK_);
1✔
140
    }
141
    gadget_.update(quantile);
1✔
142
    gadget_.doublesSV = null;
1✔
143
  }
1✔
144

145
  @Override
146
  public UpdateDoublesSketch getResultAndReset() {
147
    if (gadget_ == null) { return null; } //Intentionally return null here for speed.
1✔
148
    final UpdateDoublesSketch ds = gadget_;
1✔
149
    gadget_ = null;
1✔
150
    return ds;
1✔
151
  }
152

153
  @Override
154
  public void reset() {
155
    gadget_ = null;
1✔
156
  }
1✔
157

158
  //@formatter:off
159
  static UpdateDoublesSketch updateLogic(final int myMaxK, final UpdateDoublesSketch myQS,
160
                                         final DoublesSketch other) {
161
    int sw1 = ((myQS  == null) ? 0 :  myQS.isEmpty() ? 4 : 8);
1✔
162
    sw1 |=    ((other == null) ? 0 : other.isEmpty() ? 1 : 2);
1✔
163
    int outCase = 0; //0=null, 1=NOOP, 2=copy, 3=merge
1✔
164

165
    switch (sw1) {
1✔
166
      case 0:  outCase = 0; break; //myQS = null,  other = null ; return null
×
167
      case 1:  outCase = 4; break; //myQS = null,  other = empty; create empty-heap(myMaxK)
1✔
168
      case 2:  outCase = 2; break; //myQS = null,  other = valid; stream or downsample to myMaxK
1✔
169
      case 4:  outCase = 1; break; //myQS = empty, other = null ; no-op
1✔
170
      case 5:  outCase = 1; break; //myQS = empty, other = empty; no-op
1✔
171
      case 6:  outCase = 3; break; //myQS = empty, other = valid; merge
1✔
172
      case 8:  outCase = 1; break; //myQS = valid, other = null ; no-op
1✔
173
      case 9:  outCase = 1; break; //myQS = valid, other = empty: no-op
1✔
174
      case 10: outCase = 3; break; //myQS = valid, other = valid; merge
1✔
175
      default: break; //This cannot happen
176
    }
177
    UpdateDoublesSketch ret = null;
1✔
178

179
    switch (outCase) {
1✔
180
      case 0: break; //return null
×
181
      case 1: ret = myQS; break; //no-op
1✔
182
      case 2: { //myQS = null,  other = valid; stream or downsample to myMaxK
183
        assert other != null;
1✔
184
        if (!other.isEstimationMode()) { //other is exact, stream items in
1✔
185
          ret = HeapUpdateDoublesSketch.newInstance(myMaxK);
1✔
186
          // exact mode, only need copy base buffer
187
          final DoublesSketchAccessor otherAccessor = DoublesSketchAccessor.wrap(other);
1✔
188
          for (int i = 0; i < otherAccessor.numItems(); ++i) {
1✔
189
            ret.update(otherAccessor.get(i));
1✔
190
          }
191
        }
1✔
192
        else { //myQS = null, other is est mode
193
          ret = (myMaxK < other.getK())
1✔
194
              ? other.downSampleInternal(other, myMaxK, null) //null mem
1✔
195
              : DoublesUtil.copyToHeap(other); //copy required because caller has handle
1✔
196
        }
197
        break;
1✔
198
      }
199
      case 3: { //myQS = empty/valid, other = valid; merge
200
        assert other != null;
1✔
201
        assert myQS != null;
1✔
202
        if (!other.isEstimationMode()) { //other is exact, stream items in
1✔
203
          ret = myQS;
1✔
204
          // exact mode, only need copy base buffer
205
          final DoublesSketchAccessor otherAccessor = DoublesSketchAccessor.wrap(other);
1✔
206
          for (int i = 0; i < otherAccessor.numItems(); ++i) {
1✔
207
            ret.update(otherAccessor.get(i));
1✔
208
          }
209
        }
1✔
210
        else { //myQS = empty/valid, other = valid and in est mode
211
          if (myQS.getK() <= other.getK()) { //I am smaller or equal, thus the target
1✔
212
            DoublesMergeImpl.mergeInto(other, myQS);
1✔
213
            ret = myQS;
1✔
214
          }
215
          else { //Bigger: myQS.getK() > other.getK(), must effectively downsize me or swap
216
            if (myQS.isEmpty()) {
1✔
217
              if (myQS.hasMemory()) {
1✔
218
                final WritableMemory mem = myQS.getMemory(); //myQS is empty, ok to reconfigure
1✔
219
                other.putMemory(mem, false); // not compact, but BB ordered
1✔
220
                ret = DirectUpdateDoublesSketch.wrapInstance(mem);
1✔
221
              } else { //myQS is empty and on heap
1✔
222
                ret = DoublesUtil.copyToHeap(other);
1✔
223
              }
224
            }
225
            else { //Not Empty: myQS has data, downsample to tmp
226
              final UpdateDoublesSketch tmp = DoublesSketch.builder().setK(other.getK()).build();
1✔
227

228
              DoublesMergeImpl.downSamplingMergeInto(myQS, tmp); //myData -> tmp
1✔
229
              ret = (myQS.hasMemory())
1✔
230
                  ? DoublesSketch.builder().setK(other.getK()).build(myQS.getMemory())
1✔
231
                  : DoublesSketch.builder().setK(other.getK()).build();
1✔
232

233
              DoublesMergeImpl.mergeInto(tmp, ret);
1✔
234
              DoublesMergeImpl.mergeInto(other, ret);
1✔
235
            }
236
          }
237
        }
238
        break;
1✔
239
      }
240
      case 4: { //myQS = null,  other = empty; create empty-heap(myMaxK)
241
        ret = HeapUpdateDoublesSketch.newInstance(myMaxK);
1✔
242
        break;
1✔
243
      }
244
      default: break; //This cannot happen
245
    }
246
    return ret;
1✔
247
  }
248
  //@formatter:on
249

250
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc