• 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

99.44
/src/main/java/org/apache/datasketches/cpc/PreambleUtil.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.cpc;
21

22
import static org.apache.datasketches.common.Util.LS;
23
import static org.apache.datasketches.common.Util.checkBounds;
24
import static org.apache.datasketches.common.Util.zeroPad;
25
import static org.apache.datasketches.cpc.RuntimeAsserts.rtAssert;
26
import static org.apache.datasketches.cpc.RuntimeAsserts.rtAssertEquals;
27

28
import java.nio.ByteOrder;
29
import java.util.Objects;
30

31
import org.apache.datasketches.common.Family;
32
import org.apache.datasketches.common.SketchesArgumentException;
33
import org.apache.datasketches.common.SketchesStateException;
34
import org.apache.datasketches.memory.Memory;
35
import org.apache.datasketches.memory.WritableMemory;
36

37
//@formatter:off
38
/**
39
 * All formats are illustrated as Big-Endian, LSB on the right.
40
 *
41
 * <pre>
42
 * Format = EMPTY_MERGED/EMPTY_HIP: NoWindow, NoSV, HIP or NoHIP = 00X.
43
 * The first 8 bytes are common for all Formats.
44
 * PI = 2, FIcol = 0
45
 * Long adr ||
46
 *          ||    7   |    6   |    5   |    4   |    3   |    2   |    1   |    0   |
47
 *      0   ||---SEED HASH-----|-Flags--|-FIcol--|---lgK--|-FamID--|-SerVer-|---PI---|
48
 *
49
 *
50
 * Format = SPARSE_HYBRID_MERGED: {NoWindow, SV, NoHIP} = 2 = 010.
51
 * PI = 4, FIcol = 0
52
 * Long adr ||
53
 *          ||   15   |   14   |   13   |   12   |   11   |   10   |    9   |    8   |
54
 *      1   ||-------------SV Length Ints--------|--------numCoupons = numSV---------|
55
 *
56
 *          ||   23   |   22   |   21   |   20   |   19   |   18   |   17   |   16   |
57
 *      2   ||                                   |----------Start SV bit stream------|
58
 *
59
 *
60
 * Format = SPARSE_HYBRID_HIP: {NoWindow, SV, HIP} = 3 = 011
61
 * PI = 8, FIcol = 0
62
 * Long adr ||
63
 *          ||   15   |   14   |   13   |   12   |   11   |   10   |    9   |    8   |
64
 *      1   ||-------------SV Length Ints--------|--------numCoupons = numSV---------|
65
 *
66
 *          ||   23   |   22   |   21   |   20   |   19   |   18   |   17   |   16   |
67
 *      2   ||----------------------------------KxP----------------------------------|
68
 *
69
 *          ||   31   |   30   |   29   |   28   |   27   |   26   |   25   |   24   |
70
 *      3   ||-------------------------------HIP Accum-------------------------------|
71
 *
72
 *          ||   39   |   38   |   37   |   36   |   35   |   34   |   33   |   32   |
73
 *      4   ||                                   |----------Start of SV stream-------|
74
 *
75
 *
76
 * Format = PINNED_SLIDING_MERGED_NOSV: {Window, No SV, NoHIP} = 4 = 100
77
 * PI = 4, FIcol = valid
78
 * Long adr ||
79
 *          ||   15   |   14   |   13   |   12   |   11   |   10   |    9   |    8   |
80
 *      1   ||----------Window Length Ints-------|------------numCoupons-------------|
81
 *
82
 *          ||   23   |   22   |   21   |   20   |   19   |   18   |   17   |   16   |
83
 *      2   ||                                   |--------Start of Window stream-----|
84
 *
85
 *
86
 * Format = PINNED_SLIDING_HIP_NOSV: {Window, No SV, HIP} = 5 = 101
87
 * PI = 8, FIcol = valid
88
 * Long adr ||
89
 *          ||   15   |   14   |   13   |   12   |   11   |   10   |    9   |    8   |
90
 *      1   ||----------Window Length Ints-------|------------numCoupons-------------|
91
 *
92
 *          ||   23   |   22   |   21   |   20   |   19   |   18   |   17   |   16   |
93
 *      2   ||----------------------------------KxP----------------------------------|
94
 *
95
 *          ||   31   |   30   |   29   |   28   |   27   |   26   |   25   |   24   |
96
 *      3   ||-------------------------------HIP Accum-------------------------------|
97
 *
98
 *          ||   39   |   38   |   37   |   36   |   35   |   34   |   33   |   32   |
99
 *      4   ||                                   |--------Start of Window stream-----|
100
 *
101
 *
102
 * Format = PINNED_SLIDING_MERGED: {Window, SV, NoHIP} = 6 = 110
103
 * PI = 6, FIcol = valid
104
 * Long adr ||
105
 *          ||   15   |   14   |   13   |   12   |   11   |   10   |    9   |    8   |
106
 *      1   ||---------------numSV---------------|------------numCoupons-------------|
107
 *
108
 *          ||   23   |   22   |   21   |   20   |   19   |   18   |   17   |   16   |
109
 *      2   ||----------Window Length Ints-------|-------------SV Length Ints--------|
110
 *
111
 *          ||   XX   |   XX   |   XX   |   XX   |   27   |   26   |   25   |   24   |
112
 *      3   ||--------Start of SV stream---------|--------Start of Window stream-----|
113
 *
114
 *
115
 * Format = PINNED_SLIDING_HIP: {Window, SV, HIP} = 7 = 111
116
 * PI = 10, FIcol = valid
117
 * Long adr ||
118
 *          ||   15   |   14   |   13   |   12   |   11   |   10   |    9   |    8   |
119
 *      1   ||---------------numSV---------------|------------numCoupons-------------|
120
 *
121
 *          ||   23   |   22   |   21   |   20   |   19   |   18   |   17   |   16   |
122
 *      2   ||----------------------------------KxP----------------------------------|
123
 *
124
 *          ||   31   |   30   |   29   |   28   |   27   |   26   |   25   |   24   |
125
 *      3   ||-------------------------------HIP Accum-------------------------------|
126
 *
127
 *          ||   39   |   38   |   37   |   36   |   35   |   34   |   33   |   32   |
128
 *      4   ||----------Window Length Ints-------|-------------SV Length Ints--------|
129
 *
130
 *          ||   XX   |   XX   |   XX   |   XX   |   43   |   42   |   41   |   40   |
131
 *      5   ||--------Start of SV stream---------|--------Start of Window stream-----|
132
 * </pre>
133
 *
134
 * @author Lee Rhodes
135
 * @author Kevin Lang
136
 */
137
final class PreambleUtil {
138

139
  private PreambleUtil() {}
140

141
  static {
142
    if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
1✔
143
      throw new SketchesStateException("This sketch will not work on Big Endian CPUs.");
×
144
    }
145
  }
146

147
  private static final String fmt = "%10d%10x";
148

149
  /**
150
   *  The serialization version for the set of serialization formats defined in this class
151
   */
152
  static final byte SER_VER = 1;
153

154
  //Flag bit masks, Byte 5
155
  static final int BIG_ENDIAN_FLAG_MASK     = 1; //Reserved.
156
  static final int COMPRESSED_FLAG_MASK     = 2;
157
  static final int HIP_FLAG_MASK            = 4;
158
  static final int SUP_VAL_FLAG_MASK        = 8; //num Suprising Values > 0
159
  static final int WINDOW_FLAG_MASK         = 16;//window length > 0
160

161
  //PREAMBLE SIZE
162

163
  /**
164
   * This defines the preamble space required by each of the formats in units of 4-byte integers.
165
   */
166
  private static final byte[] preIntDefs = { 2, 2, 4, 8, 4, 8, 6, 10 };
1✔
167

168
  /**
169
   * Returns the defined size of the preamble in units of integers (4 bytes) given the
170
   * <i>Format</i>.
171
   * @param format the given <i>Format</i>.
172
   * @return the defined size of the preamble in units of integers (4 bytes) given the <i>Format</i>.
173
   */
174
  static byte getDefinedPreInts(final Format format) {
175
    return preIntDefs[format.ordinal()];
1✔
176
  }
177

178
  //PREAMBLE LO_FIELD DEFINITIONS, OFFSETS, AND GETS
179

180
  /**
181
   * This defines the seven fields of the first eight bytes of the preamble.
182
   * The ordinal of these values defines the byte offset.
183
   * Do not change the order.
184
   */
185
  enum LoField { PRE_INTS, SER_VERSION, FAMILY, LG_K, FI_COL, FLAGS, SEED_HASH }
1✔
186

187
  /**
188
   * Returns the defined byte offset from the start of the preamble given a <i>LoField</i>.
189
   * This only applies to the first 8 bytes of the preamble.
190
   * @param loField the given <i>LoField</i>.
191
   * @return the defined byte offset from the start of the preamble given a <i>LoField</i>.
192
   */
193
  static int getLoFieldOffset(final LoField loField) {
194
    return loField.ordinal();
1✔
195
  }
196

197
  static int getPreInts(final Memory mem) {
198
    return mem.getByte(getLoFieldOffset(LoField.PRE_INTS)) & 0XFF;
1✔
199
  }
200

201
  static int getSerVer(final Memory mem) {
202
    return mem.getByte(getLoFieldOffset(LoField.SER_VERSION)) & 0XFF;
1✔
203
  }
204

205
  static Family getFamily(final Memory mem) {
206
    final int fam = mem.getByte(getLoFieldOffset(LoField.FAMILY)) & 0XFF;
1✔
207
    return Family.idToFamily(fam);
1✔
208
  }
209

210
  static int getLgK(final Memory mem) {
211
    return mem.getByte(getLoFieldOffset(LoField.LG_K)) & 0XFF;
1✔
212
  }
213

214
  static int getFiCol(final Memory mem) {
215
    return mem.getByte(getLoFieldOffset(LoField.FI_COL)) & 0XFF;
1✔
216
  }
217

218
  static int getFlags(final Memory mem) {
219
    return mem.getByte(getLoFieldOffset(LoField.FLAGS)) & 0XFF;
1✔
220
  }
221

222
  static short getSeedHash(final Memory mem) {
223
    return mem.getShort(getLoFieldOffset(LoField.SEED_HASH));
1✔
224
  }
225

226
  static int getFormatOrdinal(final Memory mem) {
227
    final int flags = getFlags(mem);
1✔
228
    return (flags >>> 2) & 0x7;
1✔
229
  }
230

231
  static Format getFormat(final Memory mem) {
232
    final int ordinal = getFormatOrdinal(mem);
1✔
233
    return Format.ordinalToFormat(ordinal);
1✔
234
  }
235

236
  static boolean hasHip(final Memory mem) {
237
    return (getFlags(mem) & HIP_FLAG_MASK) > 0;
1✔
238
  }
239

240
  static final boolean hasSv(final Memory mem) {
241
    return (getFlags(mem) & SUP_VAL_FLAG_MASK) > 0;
1✔
242
  }
243

244
  static final boolean hasWindow(final Memory mem) {
245
    return (getFlags(mem) & WINDOW_FLAG_MASK) > 0;
1✔
246
  }
247

248
  static final boolean isCompressed(final Memory mem) {
249
    return (getFlags(mem) & COMPRESSED_FLAG_MASK) > 0;
1✔
250
  }
251

252
  //PREAMBLE HI_FIELD DEFINITIONS
253

254
  /**
255
   * This defines the eight additional preamble fields located after the <i>LoField</i>.
256
   * Do not change the order.
257
   *
258
   * <p>Note: NUM_SV has dual meanings: In sparse and hybrid flavors it is equivalent to
259
   * numCoupons so it isn't stored separately. In pinned and sliding flavors is is the
260
   * numSV of the PairTable, which stores only surprising values.</p>
261
   */
262
  enum HiField { NUM_COUPONS, NUM_SV, KXP, HIP_ACCUM, SV_LENGTH_INTS, W_LENGTH_INTS, SV_STREAM,
1✔
263
    W_STREAM }
1✔
264

265
  //PREAMBLE HI_FIELD OFFSETS
266

267
  /**
268
   * This defines the byte offset for eac of the 8 <i>HiFields</i>
269
   * given the Format ordinal (1st dimension) and the HiField ordinal (2nd dimension).
270
   */
271
  private static final byte[][] hiFieldOffset = //[Format][HiField]
1✔
272
    { {0,  0,  0,  0,  0,  0,  0,  0},
273
      {0,  0,  0,  0,  0,  0,  0,  0},
274
      {8,  0,  0,  0, 12,  0, 16,  0},
275
      {8,  0, 16, 24, 12,  0, 32,  0},
276
      {8,  0,  0,  0,  0, 12,  0, 16},
277
      {8,  0, 16, 24,  0, 12,  0, 32},
278
      {8, 12,  0,  0, 16, 20, 24, 24}, //the 2nd 24 is not used.
279
      {8, 12, 16, 24, 32, 36, 40, 40}  //the 2nd 40 is not used.
280
    };
281

282
  /**
283
   * Returns the defined byte offset from the start of the preamble given the <i>HiField</i>
284
   * and the <i>Format</i>.
285
   * Note this can not be used to obtain the stream offsets.
286
   * @param format the desired <i>Format</i>
287
   * @param hiField the desired preamble <i>HiField</i> after the first eight bytes.
288
   * @return the defined byte offset from the start of the preamble for the given <i>HiField</i>
289
   * and the <i>Format</i>.
290
   */
291
  static long getHiFieldOffset(final Format format, final HiField hiField) {
292
    final int formatIdx = format.ordinal();
1✔
293
    final int hiFieldIdx = hiField.ordinal();
1✔
294
    final long fieldOffset = hiFieldOffset[formatIdx][hiFieldIdx] & 0xFF; //initially a byte
1✔
295
    if (fieldOffset == 0) {
1✔
296
      throw new SketchesStateException("Undefined preamble field given the Format: "
1✔
297
          + "Format: " + format.toString() + ", HiField: " + hiField.toString());
1✔
298
    }
299
    return fieldOffset;
1✔
300
  }
301

302
  //PREAMBLE HI_FIELD GETS
303

304
  static int getNumCoupons(final Memory mem) {
305
    final Format format = getFormat(mem);
1✔
306
    final HiField hiField = HiField.NUM_COUPONS;
1✔
307
    final long offset = getHiFieldOffset(format, hiField);
1✔
308
    return mem.getInt(offset);
1✔
309
  }
310

311
  static int getNumSv(final Memory mem) {
312
    final Format format = getFormat(mem);
1✔
313
    final HiField hiField = HiField.NUM_SV;
1✔
314
    final long offset = getHiFieldOffset(format, hiField);
1✔
315
    return mem.getInt(offset);
1✔
316
  }
317

318
  static int getSvLengthInts(final Memory mem) {
319
    final Format format = getFormat(mem);
1✔
320
    final HiField hiField = HiField.SV_LENGTH_INTS;
1✔
321
    final long offset = getHiFieldOffset(format, hiField);
1✔
322
    return mem.getInt(offset);
1✔
323
  }
324

325
  static int getWLengthInts(final Memory mem) {
326
    final Format format = getFormat(mem);
1✔
327
    final HiField hiField = HiField.W_LENGTH_INTS;
1✔
328
    final long offset = getHiFieldOffset(format, hiField);
1✔
329
    return mem.getInt(offset);
1✔
330
  }
331

332
  static double getKxP(final Memory mem) {
333
    final Format format = getFormat(mem);
1✔
334
    final HiField hiField = HiField.KXP;
1✔
335
    final long offset = getHiFieldOffset(format, hiField);
1✔
336
    return mem.getDouble(offset);
1✔
337
  }
338

339
  static double getHipAccum(final Memory mem) {
340
    final Format format = getFormat(mem);
1✔
341
    final HiField hiField = HiField.HIP_ACCUM;
1✔
342
    final long offset = getHiFieldOffset(format, hiField);
1✔
343
    return mem.getDouble(offset);
1✔
344
  }
345

346
  static long getSvStreamOffset(final Memory mem) {
347
    final Format format = getFormat(mem);
1✔
348
    final HiField svLenField = HiField.SV_LENGTH_INTS;
1✔
349
    if (!hasSv(mem)) {
1✔
350
      fieldError(format, svLenField);
×
351
    } else {
352
      final long svLengthInts = mem.getInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS)) & 0XFFFF_FFFFL;
1✔
353
      if (svLengthInts == 0) {
1✔
354
        throw new SketchesStateException("svLengthInts cannot be zero");
1✔
355
      }
356
    }
357
    long wLengthInts = 0;
1✔
358
    if (hasWindow(mem)) {
1✔
359
      wLengthInts = mem.getInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS)) & 0XFFFF_FFFFL;
1✔
360
      if (wLengthInts == 0) {
1✔
361
        throw new SketchesStateException("wLengthInts cannot be zero");
1✔
362
      }
363
    }
364
    return (getPreInts(mem) + wLengthInts) << 2;
1✔
365
  }
366

367
  static long getWStreamOffset(final Memory mem) {
368
    final Format format = getFormat(mem);
1✔
369
    final HiField wLenField = HiField.W_LENGTH_INTS;
1✔
370
    if (!hasWindow(mem))  { fieldError(format, wLenField); }
1✔
371
    final long wLengthInts = mem.getInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS)) & 0XFFFF_FFFFL;
1✔
372
      if (wLengthInts == 0) {
1✔
373
        throw new SketchesStateException("wLengthInts cannot be zero");
1✔
374
      }
375
    return getPreInts(mem) << 2;
1✔
376
  }
377

378
  static int[] getSvStream(final Memory mem) {
379
    final long offset = getSvStreamOffset(mem);
1✔
380
    final int svLengthInts = getSvLengthInts(mem);
1✔
381
    final int[] svStream = new int[svLengthInts];
1✔
382
    mem.getIntArray(offset, svStream, 0, svLengthInts);
1✔
383
    return svStream;
1✔
384
  }
385

386
  static int[] getWStream(final Memory mem) {
387
    final long offset = getWStreamOffset(mem);
1✔
388
    final int wLength = getWLengthInts(mem);
1✔
389
    final int[] wStream = new int[wLength];
1✔
390
    mem.getIntArray(offset, wStream, 0, wLength);
1✔
391
    return wStream;
1✔
392
  }
393

394
  // PUT INTO MEMORY
395

396
  static void putEmptyMerged(final WritableMemory wmem,
397
      final int lgK,
398
      final short seedHash) {
399
    final Format format = Format.EMPTY_MERGED;
1✔
400
    final byte preInts = getDefinedPreInts(format);
1✔
401
    final byte fiCol = (byte) 0;
1✔
402
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
403
    checkCapacity(wmem.getCapacity(), 8);
1✔
404
    putFirst8(wmem, preInts, (byte) lgK, fiCol, flags, seedHash);
1✔
405
  }
1✔
406

407
  static void putEmptyHip(final WritableMemory wmem,
408
      final int lgK,
409
      final short seedHash) {
410
    final Format format = Format.EMPTY_HIP;
1✔
411
    final byte preInts = getDefinedPreInts(format);
1✔
412
    final byte fiCol = (byte) 0;
1✔
413
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
414
    checkCapacity(wmem.getCapacity(), 8);
1✔
415
    putFirst8(wmem, preInts, (byte) lgK, fiCol, flags, seedHash);
1✔
416
  }
1✔
417

418
  static void putSparseHybridMerged(final WritableMemory wmem,
419
      final int lgK,
420
      final int numCoupons, //unsigned
421
      final int svLengthInts,
422
      final short seedHash,
423
      final int[] svStream) {
424
    final Format format = Format.SPARSE_HYBRID_MERGED;
1✔
425
    final byte preInts = getDefinedPreInts(format);
1✔
426
    final byte fiCol = (byte) 0;
1✔
427
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
428
    checkCapacity(wmem.getCapacity(), 4L * (preInts + svLengthInts));
1✔
429
    putFirst8(wmem, preInts, (byte) lgK, fiCol, flags, seedHash);
1✔
430

431
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_COUPONS), numCoupons);
1✔
432
    wmem.putInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS), svLengthInts);
1✔
433
    wmem.putIntArray(getSvStreamOffset(wmem), svStream, 0, svLengthInts);
1✔
434
  }
1✔
435

436
  static void putSparseHybridHip(final WritableMemory wmem,
437
      final int lgK,
438
      final int numCoupons, //unsigned
439
      final int svLengthInts,
440
      final double kxp,
441
      final double hipAccum,
442
      final short seedHash,
443
      final int[] svStream) {
444
    final Format format = Format.SPARSE_HYBRID_HIP;
1✔
445
    final byte preInts = getDefinedPreInts(format);
1✔
446
    final byte fiCol = (byte) 0;
1✔
447
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
448
    checkCapacity(wmem.getCapacity(), 4L * (preInts + svLengthInts));
1✔
449
    putFirst8(wmem, preInts, (byte) lgK, fiCol, flags, seedHash);
1✔
450

451
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_COUPONS), numCoupons);
1✔
452
    wmem.putInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS), svLengthInts);
1✔
453
    wmem.putDouble(getHiFieldOffset(format, HiField.KXP), kxp);
1✔
454
    wmem.putDouble(getHiFieldOffset(format, HiField.HIP_ACCUM), hipAccum);
1✔
455
    wmem.putIntArray(getSvStreamOffset(wmem), svStream, 0, svLengthInts);
1✔
456
  }
1✔
457

458
  static void putPinnedSlidingMergedNoSv(final WritableMemory wmem,
459
      final int lgK,
460
      final int fiCol,
461
      final int numCoupons, //unsigned
462
      final int wLengthInts,
463
      final short seedHash,
464
      final int[] wStream) {
465
    final Format format = Format.PINNED_SLIDING_MERGED_NOSV;
1✔
466
    final byte preInts = getDefinedPreInts(format);
1✔
467
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
468
    checkCapacity(wmem.getCapacity(), 4L * (preInts + wLengthInts));
1✔
469
    putFirst8(wmem, preInts, (byte) lgK, (byte) fiCol, flags, seedHash);
1✔
470

471
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_COUPONS), numCoupons);
1✔
472
    wmem.putInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS), wLengthInts);
1✔
473
    wmem.putIntArray(getWStreamOffset(wmem), wStream, 0, wLengthInts);
1✔
474
  }
1✔
475

476
  static void putPinnedSlidingHipNoSv(final WritableMemory wmem,
477
      final int lgK,
478
      final int fiCol,
479
      final int numCoupons, //unsigned
480
      final int wLengthInts,
481
      final double kxp,
482
      final double hipAccum,
483
      final short seedHash,
484
      final int[] wStream) {
485
    final Format format = Format.PINNED_SLIDING_HIP_NOSV;
1✔
486
    final byte preInts = getDefinedPreInts(format);
1✔
487
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
488
    checkCapacity(wmem.getCapacity(), 4L * (preInts + wLengthInts));
1✔
489
    putFirst8(wmem, preInts, (byte) lgK, (byte) fiCol, flags, seedHash);
1✔
490

491
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_COUPONS), numCoupons);
1✔
492
    wmem.putInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS), wLengthInts);
1✔
493
    wmem.putDouble(getHiFieldOffset(format, HiField.KXP), kxp);
1✔
494
    wmem.putDouble(getHiFieldOffset(format, HiField.HIP_ACCUM), hipAccum);
1✔
495
    wmem.putIntArray(getWStreamOffset(wmem), wStream, 0, wLengthInts);
1✔
496
  }
1✔
497

498
  static void putPinnedSlidingMerged(final WritableMemory wmem,
499
      final int lgK,
500
      final int fiCol,
501
      final int numCoupons, //unsigned
502
      final int numSv,
503
      final int svLengthInts,
504
      final int wLengthInts,
505
      final short seedHash,
506
      final int[] svStream,
507
      final int[] wStream) {
508
    final Format format = Format.PINNED_SLIDING_MERGED;
1✔
509
    final byte preInts = getDefinedPreInts(format);
1✔
510
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
511
    checkCapacity(wmem.getCapacity(), 4L * (preInts + svLengthInts + wLengthInts));
1✔
512
    putFirst8(wmem, preInts, (byte) lgK, (byte) fiCol, flags, seedHash);
1✔
513

514
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_COUPONS), numCoupons);
1✔
515
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_SV), numSv);
1✔
516
    wmem.putInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS), svLengthInts);
1✔
517
    wmem.putInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS), wLengthInts);
1✔
518
    wmem.putIntArray(getSvStreamOffset(wmem), svStream, 0, svLengthInts);
1✔
519
    wmem.putIntArray(getWStreamOffset(wmem), wStream, 0, wLengthInts);
1✔
520
  }
1✔
521

522
  static void putPinnedSlidingHip(final WritableMemory wmem,
523
      final int lgK,
524
      final int fiCol,
525
      final int numCoupons, //unsigned
526
      final int numSv,
527
      final double kxp,
528
      final double hipAccum,
529
      final int svLengthInts,
530
      final int wLengthInts,
531
      final short seedHash,
532
      final int[] svStream,
533
      final int[] wStream) {
534
    final Format format = Format.PINNED_SLIDING_HIP;
1✔
535
    final byte preInts = getDefinedPreInts(format);
1✔
536
    final byte flags = (byte) ((format.ordinal() << 2) | COMPRESSED_FLAG_MASK);
1✔
537
    checkCapacity(wmem.getCapacity(), 4L * (preInts + svLengthInts + wLengthInts));
1✔
538
    putFirst8(wmem, preInts, (byte) lgK, (byte) fiCol, flags, seedHash);
1✔
539

540
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_COUPONS), numCoupons);
1✔
541
    wmem.putInt(getHiFieldOffset(format, HiField.NUM_SV), numSv);
1✔
542
    wmem.putDouble(getHiFieldOffset(format, HiField.KXP), kxp);
1✔
543
    wmem.putDouble(getHiFieldOffset(format, HiField.HIP_ACCUM), hipAccum);
1✔
544
    wmem.putInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS), svLengthInts);
1✔
545
    wmem.putInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS), wLengthInts);
1✔
546
    wmem.putIntArray(getSvStreamOffset(wmem), svStream, 0, svLengthInts);
1✔
547
    wmem.putIntArray(getWStreamOffset(wmem), wStream, 0, wLengthInts);
1✔
548
  }
1✔
549

550
  private static void putFirst8(final WritableMemory wmem, final byte preInts, final byte lgK,
551
      final byte fiCol, final byte flags, final short seedHash) {
552
    wmem.clear(0L, 4L * preInts);
1✔
553
    wmem.putByte(getLoFieldOffset(LoField.PRE_INTS), preInts);
1✔
554
    wmem.putByte(getLoFieldOffset(LoField.SER_VERSION), SER_VER);
1✔
555
    wmem.putByte(getLoFieldOffset(LoField.FAMILY), (byte) Family.CPC.getID());
1✔
556
    wmem.putByte(getLoFieldOffset(LoField.LG_K), lgK);
1✔
557
    wmem.putByte(getLoFieldOffset(LoField.FI_COL), fiCol);
1✔
558
    wmem.putByte(getLoFieldOffset(LoField.FLAGS), flags);
1✔
559
    wmem.putShort(getLoFieldOffset(LoField.SEED_HASH), seedHash);
1✔
560
  }
1✔
561

562
  //TO STRING
563

564
  static String toString(final byte[] byteArr, final boolean detail) {
565
    final Memory mem = Memory.wrap(byteArr);
1✔
566
    return toString(mem, detail);
1✔
567
  }
568

569
  static String toString(final Memory mem, final boolean detail) {
570
    final long capBytes = mem.getCapacity();
1✔
571
    //Lo Fields Preamble, first 7 fields, first 8 bytes
572
    final int preInts = mem.getByte(getLoFieldOffset(LoField.PRE_INTS)) & 0xFF;
1✔
573
    final int serVer = mem.getByte(getLoFieldOffset(LoField.SER_VERSION)) & 0xFF;
1✔
574
    final Family family = Family.idToFamily(mem.getByte(getLoFieldOffset(LoField.FAMILY)) & 0xFF);
1✔
575
    final int lgK = mem.getByte(getLoFieldOffset(LoField.LG_K)) & 0xFF;
1✔
576
    final int fiCol = mem.getByte(getLoFieldOffset(LoField.FI_COL)) & 0xFF;
1✔
577
    final int flags = mem.getByte(getLoFieldOffset(LoField.FLAGS)) & 0XFF;
1✔
578
    final int seedHash = mem.getShort(getLoFieldOffset(LoField.SEED_HASH)) & 0XFFFF;
1✔
579
    final String seedHashStr = Integer.toHexString(seedHash);
1✔
580

581
    //Flags of the Flags byte
582
    final String flagsStr = zeroPad(Integer.toBinaryString(flags), 8) + ", " + (flags);
1✔
583
    final boolean bigEndian = (flags & BIG_ENDIAN_FLAG_MASK) > 0;
1✔
584
    final boolean compressed = (flags & COMPRESSED_FLAG_MASK) > 0;
1✔
585
    final boolean hasHip = (flags & HIP_FLAG_MASK) > 0;
1✔
586
    final boolean hasSV = (flags & SUP_VAL_FLAG_MASK) > 0;
1✔
587
    final boolean hasWindow = (flags & WINDOW_FLAG_MASK) > 0;
1✔
588

589
    final int formatOrdinal = (flags >>> 2) & 0x7;
1✔
590
    final Format format = Format.ordinalToFormat(formatOrdinal);
1✔
591

592
    final String nativeOrderStr = ByteOrder.nativeOrder().toString();
1✔
593

594
    long numCoupons = 0;
1✔
595
    long numSv = 0;
1✔
596
    long winOffset = 0;
1✔
597
    long svLengthInts = 0;
1✔
598
    long wLengthInts = 0;
1✔
599
    double kxp = 0;
1✔
600
    double hipAccum = 0;
1✔
601
    long svStreamStart = 0;
1✔
602
    long wStreamStart = 0;
1✔
603
    long reqBytes = 0;
1✔
604

605
    final StringBuilder sb = new StringBuilder();
1✔
606
    sb.append(LS);
1✔
607
    sb.append("### CPC SKETCH IMAGE - PREAMBLE:").append(LS);
1✔
608
    sb.append("Format                          : ").append(format.name()).append(LS);
1✔
609
    sb.append("Byte 0: Preamble Ints           : ").append(preInts).append(LS);
1✔
610
    sb.append("Byte 1: SerVer                  : ").append(serVer).append(LS);
1✔
611
    sb.append("Byte 2: Family                  : ").append(family).append(LS);
1✔
612
    sb.append("Byte 3: lgK                     : ").append(lgK).append(LS);
1✔
613
    sb.append("Byte 4: First Interesting Col   : ").append(fiCol).append(LS);
1✔
614
    sb.append("Byte 5: Flags                   : ").append(flagsStr).append(LS);
1✔
615
    sb.append("  BIG_ENDIAN_STORAGE            : ").append(bigEndian).append(LS);
1✔
616
    sb.append("  (Native Byte Order)           : ").append(nativeOrderStr).append(LS);
1✔
617
    sb.append("  Compressed                    : ").append(compressed).append(LS);
1✔
618
    sb.append("  Has HIP                       : ").append(hasHip).append(LS);
1✔
619
    sb.append("  Has Surprising Values         : ").append(hasSV).append(LS);
1✔
620
    sb.append("  Has Window Values             : ").append(hasWindow).append(LS);
1✔
621
    sb.append("Byte 6, 7: Seed Hash            : ").append(seedHashStr).append(LS);
1✔
622

623
    final Flavor flavor;
624

625
    switch (format) {
1✔
626
      case EMPTY_MERGED :
627
      case EMPTY_HIP : {
628
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
629
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
630
        break;
1✔
631
      }
632
      case SPARSE_HYBRID_MERGED : {
633
        numCoupons = mem.getInt(getHiFieldOffset(format, HiField.NUM_COUPONS)) & 0xFFFF_FFFFL;
1✔
634

635
        numSv = numCoupons;
1✔
636
        svLengthInts = mem.getInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
637
        svStreamStart = getSvStreamOffset(mem);
1✔
638
        reqBytes = svStreamStart + (svLengthInts << 2);
1✔
639
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
640
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
641
        sb.append("Num Coupons                     : ").append(numCoupons).append(LS);
1✔
642

643
        sb.append("Num SV                          : ").append(numSv).append(LS);
1✔
644
        sb.append("SV Length Ints                  : ").append(svLengthInts).append(LS);
1✔
645
        sb.append("SV Stream Start                 : ").append(svStreamStart).append(LS);
1✔
646
        break;
1✔
647
      }
648
      case SPARSE_HYBRID_HIP : {
649
        numCoupons = mem.getInt(getHiFieldOffset(format, HiField.NUM_COUPONS)) & 0xFFFF_FFFFL;
1✔
650

651
        numSv = numCoupons;
1✔
652
        svLengthInts = mem.getInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
653
        svStreamStart = getSvStreamOffset(mem);
1✔
654

655
        kxp = mem.getDouble(getHiFieldOffset(format, HiField.KXP));
1✔
656
        hipAccum = mem.getDouble(getHiFieldOffset(format, HiField.HIP_ACCUM));
1✔
657
        reqBytes = svStreamStart + (svLengthInts << 2);
1✔
658

659
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
660
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
661
        sb.append("Num Coupons                     : ").append(numCoupons).append(LS);
1✔
662

663
        sb.append("Num SV                          : ").append(numSv).append(LS);
1✔
664
        sb.append("SV Length Ints                  : ").append(svLengthInts).append(LS);
1✔
665
        sb.append("SV Stream Start                 : ").append(svStreamStart).append(LS);
1✔
666

667
        sb.append("KxP                             : ").append(kxp).append(LS);
1✔
668
        sb.append("HipAccum                        : ").append(hipAccum).append(LS);
1✔
669
        break;
1✔
670
      }
671
      case PINNED_SLIDING_MERGED_NOSV : {
672
        numCoupons = mem.getInt(getHiFieldOffset(format, HiField.NUM_COUPONS)) & 0xFFFF_FFFFL;
1✔
673

674
        winOffset = CpcUtil.determineCorrectOffset(lgK, numCoupons);
1✔
675
        wLengthInts = mem.getInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
676
        wStreamStart = getWStreamOffset(mem);
1✔
677
        reqBytes = wStreamStart + (wLengthInts << 2);
1✔
678

679
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
680
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
681
        sb.append("Num Coupons                     : ").append(numCoupons).append(LS);
1✔
682

683
        sb.append("Window Offset                   : ").append(winOffset).append(LS);
1✔
684
        sb.append("Window Length Ints              : ").append(wLengthInts).append(LS);
1✔
685
        sb.append("Window Stream Start             : ").append(wStreamStart).append(LS);
1✔
686
        break;
1✔
687
      }
688
      case PINNED_SLIDING_HIP_NOSV : {
689
        numCoupons = mem.getInt(getHiFieldOffset(format, HiField.NUM_COUPONS)) & 0xFFFF_FFFFL;
1✔
690

691
        winOffset = CpcUtil.determineCorrectOffset(lgK, numCoupons);
1✔
692
        wLengthInts = mem.getInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
693
        wStreamStart = getWStreamOffset(mem);
1✔
694

695
        kxp = mem.getDouble(getHiFieldOffset(format, HiField.KXP));
1✔
696
        hipAccum = mem.getDouble(getHiFieldOffset(format, HiField.HIP_ACCUM));
1✔
697
        reqBytes = wStreamStart + (wLengthInts << 2);
1✔
698

699
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
700
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
701
        sb.append("Num Coupons                     : ").append(numCoupons).append(LS);
1✔
702

703
        sb.append("Window Offset                   : ").append(winOffset).append(LS);
1✔
704
        sb.append("Window Length Ints              : ").append(wLengthInts).append(LS);
1✔
705
        sb.append("Window Stream Start             : ").append(wStreamStart).append(LS);
1✔
706

707
        sb.append("KxP                             : ").append(kxp).append(LS);
1✔
708
        sb.append("HipAccum                        : ").append(hipAccum).append(LS);
1✔
709
        break;
1✔
710
      }
711
      case PINNED_SLIDING_MERGED : {
712
        numCoupons = mem.getInt(getHiFieldOffset(format, HiField.NUM_COUPONS) & 0xFFFF_FFFFL);
1✔
713

714
        winOffset = CpcUtil.determineCorrectOffset(lgK, numCoupons);
1✔
715
        wLengthInts = mem.getInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
716

717
        numSv = mem.getInt(getHiFieldOffset(format, HiField.NUM_SV)) & 0xFFFF_FFFFL;
1✔
718
        svLengthInts = mem.getInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
719

720
        wStreamStart = getWStreamOffset(mem);
1✔
721
        svStreamStart = getSvStreamOffset(mem);
1✔
722
        reqBytes = svStreamStart + (svLengthInts << 2);
1✔
723

724
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
725
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
726
        sb.append("Num Coupons                     : ").append(numCoupons).append(LS);
1✔
727

728
        sb.append("Num SV                          : ").append(numSv).append(LS);
1✔
729
        sb.append("SV Length Ints                  : ").append(svLengthInts).append(LS);
1✔
730
        sb.append("SV Stream Start                 : ").append(svStreamStart).append(LS);
1✔
731

732
        sb.append("Window Offset                   : ").append(winOffset).append(LS);
1✔
733
        sb.append("Window Length Ints              : ").append(wLengthInts).append(LS);
1✔
734
        sb.append("Window Stream Start             : ").append(wStreamStart).append(LS);
1✔
735
        break;
1✔
736
      }
737
      case PINNED_SLIDING_HIP : {
738
        numCoupons = mem.getInt(getHiFieldOffset(format, HiField.NUM_COUPONS) & 0xFFFF_FFFFL);
1✔
739

740
        winOffset = CpcUtil.determineCorrectOffset(lgK, numCoupons);
1✔
741
        wLengthInts = mem.getInt(getHiFieldOffset(format, HiField.W_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
742

743
        numSv = mem.getInt(getHiFieldOffset(format, HiField.NUM_SV)) & 0xFFFF_FFFFL;
1✔
744
        svLengthInts = mem.getInt(getHiFieldOffset(format, HiField.SV_LENGTH_INTS)) & 0xFFFF_FFFFL;
1✔
745
        wStreamStart = getWStreamOffset(mem);
1✔
746
        svStreamStart = getSvStreamOffset(mem);
1✔
747

748
        kxp = mem.getDouble(getHiFieldOffset(format, HiField.KXP));
1✔
749
        hipAccum = mem.getDouble(getHiFieldOffset(format, HiField.HIP_ACCUM));
1✔
750
        reqBytes = svStreamStart + (svLengthInts << 2);
1✔
751

752
        flavor = CpcUtil.determineFlavor(lgK, numCoupons);
1✔
753
        sb.append("Flavor                          : ").append(flavor).append(LS);
1✔
754
        sb.append("Num Coupons                     : ").append(numCoupons).append(LS);
1✔
755

756
        sb.append("Num SV                          : ").append(numSv).append(LS);
1✔
757
        sb.append("SV Length Ints                  : ").append(svLengthInts).append(LS);
1✔
758
        sb.append("SV Stream Start                 : ").append(svStreamStart).append(LS);
1✔
759

760
        sb.append("Window Offset                   : ").append(winOffset).append(LS);
1✔
761
        sb.append("Window Length Ints              : ").append(wLengthInts).append(LS);
1✔
762
        sb.append("Window Stream Start             : ").append(wStreamStart).append(LS);
1✔
763

764
        sb.append("KxP                             : ").append(kxp).append(LS);
1✔
765
        sb.append("HipAccum                        : ").append(hipAccum).append(LS);
1✔
766
        break;
767
      }
768
    }
769

770
    sb.append("Actual Bytes                    : ").append(capBytes).append(LS);
1✔
771
    sb.append("Required Bytes                  : ").append(reqBytes).append(LS);
1✔
772

773
    if (detail) {
1✔
774
      sb.append(LS).append("### CPC SKETCH IMAGE - DATA").append(LS);
1✔
775
      if (wLengthInts > 0) {
1✔
776
        sb.append(LS).append("Window Stream:").append(LS);
1✔
777
        listData(mem, wStreamStart, wLengthInts, sb);
1✔
778
      }
779
      if (svLengthInts > 0) {
1✔
780
        sb.append(LS).append("SV Stream:").append(LS);
1✔
781
        listData(mem, svStreamStart, svLengthInts, sb);
1✔
782
      }
783
    }
784
    sb.append("### END CPC SKETCH IMAGE").append(LS);
1✔
785
    return sb.toString();
1✔
786
  } //end toString(mem)
787

788
  private static void listData(final Memory mem, final long offsetBytes, final long lengthInts,
789
      final StringBuilder sb) {
790
    final long memCap = mem.getCapacity();
1✔
791
    final long expectedCap = offsetBytes + (4L * lengthInts);
1✔
792
    checkCapacity(memCap, expectedCap);
1✔
793
    for (long i = 0; i < lengthInts; i++) {
1✔
794
      sb.append(String.format(fmt, i, mem.getInt(offsetBytes + (4L * i)))).append(LS);
1✔
795
    }
796
  }
1✔
797

798
  static void fieldError(final Format format, final HiField hiField) {
799
    throw new SketchesArgumentException(
1✔
800
        "Operation is illegal: Format = " + format.name() + ", HiField = " + hiField);
1✔
801
  }
802

803
  static void checkCapacity(final long memCap, final long expectedCap) {
804
    if (memCap < expectedCap) {
1✔
805
      throw new SketchesArgumentException(
1✔
806
          "Insufficient Image Bytes = " + memCap + ", Expected = " + expectedCap);
807
    }
808
  }
1✔
809

810
  //basic checks of SerVer, Format, preInts, Family, fiCol, lgK.
811
  static void checkLoPreamble(final Memory mem) {
812
    Objects.requireNonNull(mem, "Source Memory must not be null");
1✔
813
    checkBounds(0, 8, mem.getCapacity()); //need min 8 bytes
1✔
814
    rtAssertEquals(getSerVer(mem), SER_VER & 0XFF);
1✔
815
    final Format fmat = getFormat(mem);
1✔
816
    final int preIntsDef = getDefinedPreInts(fmat) & 0XFF;
1✔
817
    rtAssertEquals(getPreInts(mem), preIntsDef);
1✔
818
    final Family fam = getFamily(mem);
1✔
819
    rtAssert(fam == Family.CPC);
1✔
820
    final int lgK = getLgK(mem);
1✔
821
    rtAssert((lgK >= 4) && (lgK <= 26));
1✔
822
    final int fiCol = getFiCol(mem);
1✔
823
    rtAssert((fiCol <= 63) && (fiCol >= 0));
1✔
824
  }
1✔
825

826
}
827
//@formatter:on
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