• 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

82.63
/src/main/java/org/apache/datasketches/quantilescommon/InequalitySearch.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.quantilescommon;
21

22
import java.util.Objects;
23

24
import org.apache.datasketches.common.SketchesArgumentException;
25

26
/**
27
 * This provides efficient, unique and unambiguous binary searching for inequality comparison criteria
28
 * for ordered arrays of values that may include duplicate values. The inequality criteria include
29
 * <, ≤, ==, ≥, >. All the inequality criteria use the same search algorithm.
30
 * (Although == is not an inequality, it is included for convenience.)
31
 *
32
 * <p>In order to make the searching unique and unambiguous, we modified the traditional binary
33
 * search algorithm to search for adjacent pairs of values <i>{A, B}</i> in the values array
34
 * instead of just a single value, where <i>a</i> and <i>b</i> are the array indices of two
35
 * adjacent values in the array. For all the search criteria, when the algorithm has narrowed the
36
 * search down to a single value or adjacent pair of values, the <i>resolve()</i> method provides the
37
 * final result of the search. If there is no valid value in the array that satisfies the search
38
 * criterion, the algorithm will return -1 to the caller.</p>
39
 *
40
 * <p>Given a sorted array of values <i>arr[]</i> and a search key value <i>v</i>, the algorithms for
41
 * the searching criteria are given with each enum criterion.</p>
42
 *
43
 * @see <a href="https://datasketches.apache.org/docs/Quantiles/SketchingQuantilesAndRanksTutorial.html">
44
 * Sketching Quantiles and Ranks Tutorial</a>
45
 * @author Lee Rhodes
46
 */
47
public enum InequalitySearch {
1✔
48

49
  /**
50
   * Given a sorted array of increasing values <i>arr[]</i> and a key value <i>v</i>,
51
   * this criterion instructs the binary search algorithm to find the highest adjacent pair of
52
   * values <i>{A,B}</i> such that <i>A &lt; v &le; B</i>.<br>
53
   * Let <i>low</i> = index of the lowest value in the range.<br>
54
   * Let <i>high</i> = index of the highest value in the range.
55
   *
56
   * <p>If <i>v</i> &gt; arr[high], return arr[high].<br>
57
   * If <i>v</i> &le; arr[low], return -1.<br>
58
   * Else return index of A.</p>
59
   */
60
  LT { //arr[A] < V <= arr[B], return A
1✔
61
    @Override
62
    int compare(final double[] arr, final int a, final int b, final double v) {
63
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
64
    }
65

66
    @Override
67
    int compare(final float[] arr, final int a, final int b, final float v) {
68
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
69
    }
70

71
    @Override
72
    int compare(final long[] arr, final int a, final int b, final long v) {
73
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
74
    }
75

76
    @Override
77
    int compare(final long[] arr, final int a, final int b, final double v) {
78
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
×
79
    }
80

81
    @Override
82
    int getIndex(final double[] arr, final int a, final int b, final double v) {
83
      return a;
1✔
84
    }
85

86
    @Override
87
    int getIndex(final float[] arr, final int a, final int b, final float v) {
88
      return a;
1✔
89
    }
90

91
    @Override
92
    int getIndex(final long[] arr, final int a, final int b, final long v) {
93
      return a;
1✔
94
    }
95

96
    @Override
97
    int getIndex(final long[] arr, final int a, final int b, final double v) {
98
      return a;
×
99
    }
100

101
    @Override
102
    int resolve(final double[] arr, final int lo, final int hi, final double v) {
103
      return (lo == hi)
1✔
104
          ? (v > arr[lo] ? lo : -1)
105
          : v > arr[hi] ? hi : (v > arr[lo] ? lo : -1);
106
    }
107

108
    @Override
109
    int resolve(final float[] arr, final int lo, final int hi, final float v) {
110
      return (lo == hi)
1✔
111
          ? (v > arr[lo] ? lo : -1)
112
          : v > arr[hi] ? hi : (v > arr[lo] ? lo : -1);
113
    }
114

115
    @Override
116
    int resolve(final long[] arr, final int lo, final int hi, final long v) {
117
      return (lo == hi)
1✔
118
          ? (v > arr[lo] ? lo : -1)
119
          : v > arr[hi] ? hi : (v > arr[lo] ? lo : -1);
120
    }
121

122
    @Override
123
    int resolve(final long[] arr, final int lo, final int hi, final double v) {
124
      return (lo == hi)
×
125
          ? (v > arr[lo] ? lo : -1)
126
          : v > arr[hi] ? hi : (v > arr[lo] ? lo : -1);
127
    }
128

129
    @Override
130
    public String desc(final double[] arr, final int low, final int high, final double v, final int idx) {
131
      if (idx == -1) {
1✔
132
        return "LT: " + v + " <= arr[" + low + "]=" + arr[low] + "; return -1";
1✔
133
      }
134
      if (idx == high) {
1✔
135
        return "LT: " + v + " > arr[" + high + "]=" + arr[high]
1✔
136
            + "; return arr[" + high + "]=" + arr[high];
137
      } //idx < high
138
      return "LT: " + v
1✔
139
      + ": arr[" + idx + "]=" + arr[idx] + " < " + v + " <= arr[" + (idx + 1) + "]=" + arr[idx + 1]
140
      + "; return arr[" + idx + "]=" + arr[idx];
141
    }
142

143
    @Override
144
    public String desc(final float[] arr, final int low, final int high, final float v, final int idx) {
145
      if (idx == -1) {
1✔
146
        return "LT: " + v + " <= arr[" + low + "]=" + arr[low] + "; return -1";
1✔
147
      }
148
      if (idx == high) {
1✔
149
        return "LT: " + v + " > arr[" + high + "]=" + arr[high]
1✔
150
            + "; return arr[" + high + "]=" + arr[high];
151
      } //idx < high
152
      return "LT: " + v
1✔
153
      + ": arr[" + idx + "]=" + arr[idx] + " < " + v + " <= arr[" + (idx + 1) + "]=" + arr[idx + 1]
154
      + "; return arr[" + idx + "]=" + arr[idx];
155
    }
156

157
    @Override
158
    public String desc(final long[] arr, final int low, final int high, final long v, final int idx) {
159
      if (idx == -1) {
1✔
160
        return "LT: " + v + " <= arr[" + low + "]=" + arr[low] + "; return -1";
1✔
161
      }
162
      if (idx == high) {
1✔
163
        return "LT: " + v + " > arr[" + high + "]=" + arr[high]
1✔
164
            + "; return arr[" + high + "]=" + arr[high];
165
      } //idx < high
166
      return "LT: " + v
1✔
167
      + ": arr[" + idx + "]=" + arr[idx] + " < " + v + " <= arr[" + (idx + 1) + "]=" + arr[idx + 1]
168
      + "; return arr[" + idx + "]=" + arr[idx];
169
    }
170

171
    @Override
172
    public String desc(final long[] arr, final int low, final int high, final double v, final int idx) {
173
      if (idx == -1) {
×
174
        return "LT: " + v + " <= arr[" + low + "]=" + arr[low] + "; return -1";
×
175
      }
176
      if (idx == high) {
×
177
        return "LT: " + v + " > arr[" + high + "]=" + arr[high]
×
178
            + "; return arr[" + high + "]=" + arr[high];
179
      } //idx < high
180
      return "LT: " + v
×
181
      + ": arr[" + idx + "]=" + arr[idx] + " < " + v + " <= arr[" + (idx + 1) + "]=" + arr[idx + 1]
182
      + "; return arr[" + idx + "]=" + arr[idx];
183
    }
184
  },
185

186
  /**
187
   * Given a sorted array of increasing values <i>arr[]</i> and a key value <i>V</i>,
188
   * this criterion instructs the binary search algorithm to find the highest adjacent pair of
189
   * values <i>{A,B}</i> such that <i>A &le; V &lt; B</i>.<br>
190
   * Let <i>low</i> = index of the lowest value in the range.<br>
191
   * Let <i>high</i> = index of the highest value in the range.
192
   *
193
   * <p>If <i>v</i> &ge; arr[high], return arr[high].<br>
194
   * If <i>v</i> &lt; arr[low], return -1.<br>
195
   * Else return index of A.</p>
196
   */
197
  LE { //arr[A] <= V < arr[B], return A
1✔
198
    @Override
199
    int compare(final double[] arr, final int a, final int b, final double v) {
200
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
201
    }
202

203
    @Override
204
    int compare(final float[] arr, final int a, final int b, final float v) {
205
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
206
    }
207

208
    @Override
209
    int compare(final long[] arr, final int a, final int b, final long v) {
210
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
211
    }
212

213
    @Override
214
    int compare(final long[] arr, final int a, final int b, final double v) {
215
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
×
216
    }
217

218
    @Override
219
    int getIndex(final double[] arr, final int a, final int b, final double v) {
220
      return a;
1✔
221
    }
222

223
    @Override
224
    int getIndex(final float[] arr, final int a, final int b, final float v) {
225
      return a;
1✔
226
    }
227

228
    @Override
229
    int getIndex(final long[] arr, final int a, final int b, final long v) {
230
      return a;
1✔
231
    }
232

233
    @Override
234
    int getIndex(final long[] arr, final int a, final int b, final double v) {
235
      return a;
×
236
    }
237

238
    @Override
239
    int resolve(final double[] arr, final int lo, final int hi, final double v) {
240
      return (lo == hi)
1✔
241
          ? (v >= arr[lo] ? lo : -1)
242
          : v >= arr[hi] ? hi : (v >= arr[lo] ? lo : -1);
243
    }
244

245
    @Override
246
    int resolve(final float[] arr, final int lo, final int hi, final float v) {
247
      return (lo == hi)
1✔
248
          ? (v >= arr[lo] ? lo : -1)
249
          : v >= arr[hi] ? hi : (v >= arr[lo] ? lo : -1);
250
    }
251

252
    @Override
253
    int resolve(final long[] arr, final int lo, final int hi, final long v) {
254
      return (lo == hi)
1✔
255
          ? (v >= arr[lo] ? lo : -1)
256
          : v >= arr[hi] ? hi : (v >= arr[lo] ? lo : -1);
257
    }
258

259
    @Override
260
    int resolve(final long[] arr, final int lo, final int hi, final double v) {
261
      return (lo == hi)
×
262
          ? (v >= arr[lo] ? lo : -1)
263
          : v >= arr[hi] ? hi : (v >= arr[lo] ? lo : -1);
264
    }
265

266
    @Override
267
    public String desc(final double[] arr, final int low, final int high, final double v, final int idx) {
268
      if (idx == -1) {
1✔
269
        return "LE: " + v + " < arr[" + low + "]=" + arr[low] + "; return -1";
1✔
270
      }
271
      if (idx == high) {
1✔
272
        return "LE: " + v + " >= arr[" + high + "]=" + arr[high]
1✔
273
            + "; return arr[" + high + "]=" + arr[high];
274
      }
275
      return "LE: " + v
1✔
276
      + ": arr[" + idx + "]=" + arr[idx] + " <= " + v + " < arr[" + (idx + 1) + "]=" + arr[idx + 1]
277
          + "; return arr[" + idx + "]=" + arr[idx];
278
    }
279

280
    @Override
281
    public String desc(final float[] arr, final int low, final int high, final float v, final int idx) {
282
      if (idx == -1) {
1✔
283
        return "LE: " + v + " < arr[" + low + "]=" + arr[low] + "; return -1";
1✔
284
      }
285
      if (idx == high) {
1✔
286
        return "LE: " + v + " >= arr[" + high + "]=" + arr[high]
1✔
287
            + "; return arr[" + high + "]=" + arr[high];
288
      }
289
      return "LE: " + v
1✔
290
      + ": arr[" + idx + "]=" + arr[idx] + " <= " + v + " < arr[" + (idx + 1) + "]=" + arr[idx + 1]
291
          + "; return arr[" + idx + "]=" + arr[idx];
292
    }
293

294
    @Override
295
    public String desc(final long[] arr, final int low, final int high, final long v, final int idx) {
296
      if (idx == -1) {
1✔
297
        return "LE: " + v + " < arr[" + low + "]=" + arr[low] + "; return -1";
1✔
298
      }
299
      if (idx == high) {
1✔
300
        return "LE: " + v + " >= arr[" + high + "]=" + arr[high]
1✔
301
            + "; return arr[" + high + "]=" + arr[high];
302
      }
303
      return "LE: " + v
1✔
304
      + ": arr[" + idx + "]=" + arr[idx] + " <= " + v + " < arr[" + (idx + 1) + "]=" + arr[idx + 1]
305
          + "; return arr[" + idx + "]=" + arr[idx];
306
    }
307

308
    @Override
309
    public String desc(final long[] arr, final int low, final int high, final double v, final int idx) {
310
      if (idx == -1) {
×
311
        return "LE: " + v + " < arr[" + low + "]=" + arr[low] + "; return -1";
×
312
      }
313
      if (idx == high) {
×
314
        return "LE: " + v + " >= arr[" + high + "]=" + arr[high]
×
315
            + "; return arr[" + high + "]=" + arr[high];
316
      }
317
      return "LE: " + v
×
318
      + ": arr[" + idx + "]=" + arr[idx] + " <= " + v + " < arr[" + (idx + 1) + "]=" + arr[idx + 1]
319
          + "; return arr[" + idx + "]=" + arr[idx];
320
    }
321
  },
322

323
  /**
324
   * Given a sorted array of increasing values <i>arr[]</i> and a key value <i>V</i>,
325
   * this criterion instructs the binary search algorithm to find the adjacent pair of
326
   * values <i>{A,B}</i> such that <i>A &le; V &le; B</i>.
327
   * The returned value from the binary search algorithm will be the index of <i>A</i> or <i>B</i>,
328
   * if one of them is equal to <i>V</i>, or -1 if V is not equal to either one.
329
   */
330
  EQ { //arr[A] <= V <= arr[B], return A or B
1✔
331
    @Override
332
    int compare(final double[] arr, final int a, final int b, final double v) {
333
      return v < arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
334
    }
335

336
    @Override
337
    int compare(final float[] arr, final int a, final int b, final float v) {
338
      return v < arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
339
    }
340

341
    @Override
342
    int compare(final long[] arr, final int a, final int b, final long v) {
343
      return v < arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
344
    }
345

346
    @Override
347
    int compare(final long[] arr, final int a, final int b, final double v) {
348
      return v < arr[a] ? -1 : arr[b] < v ? 1 : 0;
×
349
    }
350

351
    @Override
352
    int getIndex(final double[] arr, final int a, final int b, final double v) {
353
      return v == arr[a] ? a : v == arr[b] ? b : -1;
1✔
354
    }
355

356
    @Override
357
    int getIndex(final float[] arr, final int a, final int b, final float v) {
358
      return v == arr[a] ? a : v == arr[b] ? b : -1;
1✔
359
    }
360

361
    @Override
362
    int getIndex(final long[] arr, final int a, final int b, final long v) {
363
      return v == arr[a] ? a : v == arr[b] ? b : -1;
1✔
364
    }
365

366
    @Override
367
    int getIndex(final long[] arr, final int a, final int b, final double v) {
368
      return v == arr[a] ? a : v == arr[b] ? b : -1;
×
369
    }
370

371
    @Override
372
    int resolve(final double[] arr, final int lo, final int hi, final double v) {
373
      return (lo == hi)
1✔
374
          ? (v == arr[lo] ? lo : -1)
375
          : v == arr[lo] ? lo : (v == arr[hi] ? hi : -1);
376
    }
377

378
    @Override
379
    int resolve(final float[] arr, final int lo, final int hi, final float v) {
380
      return (lo == hi)
1✔
381
          ? (v == arr[lo] ? lo : -1)
382
          : v == arr[lo] ? lo : (v == arr[hi] ? hi : -1);
383
    }
384

385
    @Override
386
    int resolve(final long[] arr, final int lo, final int hi, final long v) {
387
      return (lo == hi)
1✔
388
          ? (v == arr[lo] ? lo : -1)
389
          : v == arr[lo] ? lo : (v == arr[hi] ? hi : -1);
390
    }
391

392
    @Override
393
    int resolve(final long[] arr, final int lo, final int hi, final double v) {
394
      return (lo == hi)
×
395
          ? (v == arr[lo] ? lo : -1)
396
          : v == arr[lo] ? lo : (v == arr[hi] ? hi : -1);
397
    }
398

399
    @Override
400
    public String desc(final double[] arr, final int low, final int high, final double v, final int idx) {
401
      if (idx == -1) {
1✔
402
        if (v > arr[high]) {
1✔
403
          return "EQ: " + v + " > arr[" + high + "]; return -1";
1✔
404
        }
405
        if (v < arr[low]) {
1✔
406
          return "EQ: " + v + " < arr[" + low + "]; return -1";
1✔
407
        }
408
        return "EQ: " + v + " Cannot be found within arr[" + low + "], arr[" + high + "]; return -1";
1✔
409
      }
410
      return "EQ: " + v + " == arr[" + idx + "]; return arr[" + idx + "]=" + arr[idx];
1✔
411
    }
412

413
    @Override
414
    public String desc(final float[] arr, final int low, final int high, final float v, final int idx) {
415
      if (idx == -1) {
1✔
416
        if (v > arr[high]) {
1✔
417
          return "EQ: " + v + " > arr[" + high + "]; return -1";
1✔
418
        }
419
        if (v < arr[low]) {
1✔
420
          return "EQ: " + v + " < arr[" + low + "]; return -1";
1✔
421
        }
422
        return "EQ: " + v + " Cannot be found within arr[" + low + "], arr[" + high + "]; return -1";
1✔
423
      }
424
      return "EQ: " + v + " == arr[" + idx + "]; return arr[" + idx + "]=" + arr[idx];
1✔
425
    }
426

427
    @Override
428
    public String desc(final long[] arr, final int low, final int high, final long v, final int idx) {
429
      if (idx == -1) {
1✔
430
        if (v > arr[high]) {
1✔
431
          return "EQ: " + v + " > arr[" + high + "]; return -1";
1✔
432
        }
433
        if (v < arr[low]) {
1✔
434
          return "EQ: " + v + " < arr[" + low + "]; return -1";
1✔
435
        }
436
        return "EQ: " + v + " Cannot be found within arr[" + low + "], arr[" + high + "]; return -1";
×
437
      }
438
      return "EQ: " + v + " == arr[" + idx + "]; return arr[" + idx + "]=" + arr[idx];
1✔
439
    }
440

441
    @Override
442
    public String desc(final long[] arr, final int low, final int high, final double v, final int idx) {
443
      if (idx == -1) {
×
444
        if (v > arr[high]) {
×
445
          return "EQ: " + v + " > arr[" + high + "]; return -1";
×
446
        }
447
        if (v < arr[low]) {
×
448
          return "EQ: " + v + " < arr[" + low + "]; return -1";
×
449
        }
450
        return "EQ: " + v + " Cannot be found within arr[" + low + "], arr[" + high + "]; return -1";
×
451
      }
452
      return "EQ: " + v + " == arr[" + idx + "]; return arr[" + idx + "]=" + arr[idx];
×
453
    }
454
  },
455

456
  /**
457
   * Given a sorted array of increasing values <i>arr[]</i> and a key value <i>V</i>,
458
   * this criterion instructs the binary search algorithm to find the lowest adjacent pair of
459
   * values <i>{A,B}</i> such that <i>A &lt; V &le; B</i>.<br>
460
   * Let <i>low</i> = index of the lowest value in the range.<br>
461
   * Let <i>high</i> = index of the highest value in the range.
462
   *
463
   * <p>If <i>v</i> &le; arr[low], return arr[low].<br>
464
   * If <i>v</i> &gt; arr[high], return -1.<br>
465
   * Else return index of B.</p>
466
   */
467
  GE { //arr[A] < V <= arr[B], return B
1✔
468
    @Override
469
    int compare(final double[] arr, final int a, final int b, final double v) {
470
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
471
    }
472

473
    @Override
474
    int compare(final float[] arr, final int a, final int b, final float v) {
475
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
476
    }
477

478
    @Override
479
    int compare(final long[] arr, final int a, final int b, final long v) {
480
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
481
    }
482

483
    @Override
484
    int compare(final long[] arr, final int a, final int b, final double v) {
485
      return v <= arr[a] ? -1 : arr[b] < v ? 1 : 0;
1✔
486
    }
487

488
    @Override
489
    int getIndex(final double[] arr, final int a, final int b, final double v) {
490
      return b;
1✔
491
    }
492

493
    @Override
494
    int getIndex(final float[] arr, final int a, final int b, final float v) {
495
      return b;
1✔
496
    }
497

498
    @Override
499
    int getIndex(final long[] arr, final int a, final int b, final long v) {
500
      return b;
1✔
501
    }
502

503
    @Override
504
    int getIndex(final long[] arr, final int a, final int b, final double v) {
505
      return b;
1✔
506
    }
507

508
    @Override
509
    int resolve(final double[] arr, final int lo, final int hi, final double v) {
510
      return (lo == hi)
1✔
511
          ? (v <= arr[lo] ? lo : -1)
512
          : v <= arr[lo] ? lo : (v <= arr[hi] ? hi : -1);
513
    }
514

515
    @Override
516
    int resolve(final float[] arr, final int lo, final int hi, final float v) {
517
      return (lo == hi)
1✔
518
          ? (v <= arr[lo] ? lo : -1)
519
          : v <= arr[lo] ? lo : (v <= arr[hi] ? hi : -1);
520
    }
521

522
    @Override
523
    int resolve(final long[] arr, final int lo, final int hi, final long v) {
524
      return (lo == hi)
1✔
525
          ? (v <= arr[lo] ? lo : -1)
526
          : v <= arr[lo] ? lo : (v <= arr[hi] ? hi : -1);
527
    }
528

529
    @Override
530
    int resolve(final long[] arr, final int lo, final int hi, final double v) {
531
      return (lo == hi)
1✔
532
          ? (v <= arr[lo] ? lo : -1)
533
          : v <= arr[lo] ? lo : (v <= arr[hi] ? hi : -1);
534
    }
535

536
    @Override
537
    public String desc(final double[] arr, final int low, final int high, final double v, final int idx) {
538
      if (idx == -1) {
1✔
539
        return "GE: " + v + " > arr[" + high + "]=" + arr[high] + "; return -1";
1✔
540
      }
541
      if (idx == low) {
1✔
542
        return "GE: " + v + " <= arr[" + low + "]=" + arr[low]
1✔
543
            + "; return arr[" + low + "]=" + arr[low];
544
      } //idx > low
545
      return "GE: " + v
1✔
546
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " < " + v + " <= arr[" + idx + "]=" + arr[idx]
547
          + "; return arr[" + idx + "]=" + arr[idx];
548
    }
549

550
    @Override
551
    public String desc(final float[] arr, final int low, final int high, final float v, final int idx) {
552
      if (idx == -1) {
1✔
553
        return "GE: " + v + " > arr[" + high + "]=" + arr[high] + "; return -1";
1✔
554
      }
555
      if (idx == low) {
1✔
556
        return "GE: " + v + " <= arr[" + low + "]=" + arr[low]
1✔
557
            + "; return arr[" + low + "]=" + arr[low];
558
      } //idx > low
559
      return "GE: " + v
1✔
560
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " < " + v + " <= arr[" + idx + "]=" + arr[idx]
561
          + "; return arr[" + idx + "]=" + arr[idx];
562
    }
563

564
    @Override
565
    public String desc(final long[] arr, final int low, final int high, final long v, final int idx) {
566
      if (idx == -1) {
1✔
567
        return "GE: " + v + " > arr[" + high + "]=" + arr[high] + "; return -1";
1✔
568
      }
569
      if (idx == low) {
1✔
570
        return "GE: " + v + " <= arr[" + low + "]=" + arr[low]
1✔
571
            + "; return arr[" + low + "]=" + arr[low];
572
      } //idx > low
573
      return "GE: " + v
1✔
574
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " < " + v + " <= arr[" + idx + "]=" + arr[idx]
575
          + "; return arr[" + idx + "]=" + arr[idx];
576
    }
577

578
    @Override
579
    public String desc(final long[] arr, final int low, final int high, final double v, final int idx) {
580
      if (idx == -1) {
×
581
        return "GE: " + v + " > arr[" + high + "]=" + arr[high] + "; return -1";
×
582
      }
583
      if (idx == low) {
×
584
        return "GE: " + v + " <= arr[" + low + "]=" + arr[low]
×
585
            + "; return arr[" + low + "]=" + arr[low];
586
      } //idx > low
587
      return "GE: " + v
×
588
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " < " + v + " <= arr[" + idx + "]=" + arr[idx]
589
          + "; return arr[" + idx + "]=" + arr[idx];
590
    }
591
  },
592

593
  /**
594
   * Given a sorted array of increasing values <i>arr[]</i> and a key value <i>V</i>,
595
   * this criterion instructs the binary search algorithm to find the lowest adjacent pair of
596
   * values <i>{A,B}</i> such that <i>A &le; V &lt; B</i>.<br>
597
   * Let <i>low</i> = index of the lowest value in the range.<br>
598
   * Let <i>high</i> = index of the highest value in the range.
599
   *
600
   * <p>If <i>v</i> &lt; arr[low], return arr[low].<br>
601
   * If <i>v</i> &ge; arr[high], return -1.<br>
602
   * Else return index of B.</p>
603
   */
604
  GT { //arr[A] <= V < arr[B], return B
1✔
605
    @Override
606
    int compare(final double[] arr, final int a, final int b, final double v) {
607
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
608
    }
609

610
    @Override
611
    int compare(final float[] arr, final int a, final int b, final float v) {
612
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
613
    }
614

615
    @Override
616
    int compare(final long[] arr, final int a, final int b, final long v) {
617
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
618
    }
619

620
    @Override
621
    int compare(final long[] arr, final int a, final int b, final double v) {
622
      return v < arr[a] ? -1 : arr[b] <= v ? 1 : 0;
1✔
623
    }
624

625
    @Override
626
    int getIndex(final double[] arr, final int a, final int b, final double v) {
627
      return b;
1✔
628
    }
629

630
    @Override
631
    int getIndex(final float[] arr, final int a, final int b, final float v) {
632
      return b;
1✔
633
    }
634

635
    @Override
636
    int getIndex(final long[] arr, final int a, final int b, final long v) {
637
      return b;
1✔
638
    }
639

640
    @Override
641
    int getIndex(final long[] arr, final int a, final int b, final double v) {
642
      return b;
1✔
643
    }
644

645
    @Override
646
    int resolve(final double[] arr, final int lo, final int hi, final double v) {
647
      return (lo == hi)
1✔
648
          ? (v < arr[lo] ? lo : -1)
649
          : v < arr[lo] ? lo : (v < arr[hi] ? hi : -1);
650
    }
651

652
    @Override
653
    int resolve(final float[] arr, final int lo, final int hi, final float v) {
654
      return (lo == hi)
1✔
655
          ? (v < arr[lo] ? lo : -1)
656
          : v < arr[lo] ? lo : (v < arr[hi] ? hi : -1);
657
    }
658

659
    @Override
660
    int resolve(final long[] arr, final int lo, final int hi, final long v) {
661
      return (lo == hi)
1✔
662
          ? (v < arr[lo] ? lo : -1)
663
          : v < arr[lo] ? lo : (v < arr[hi] ? hi : -1);
664
    }
665

666
    @Override
667
    int resolve(final long[] arr, final int lo, final int hi, final double v) {
668
      return (lo == hi)
1✔
669
          ? (v < arr[lo] ? lo : -1)
670
          : v < arr[lo] ? lo : (v < arr[hi] ? hi : -1);
671
    }
672

673
    @Override
674
    public String desc(final double[] arr, final int low, final int high, final double v, final int idx) {
675
      if (idx == -1) {
1✔
676
        return "GT: " + v + " >= arr[" + high + "]=" + arr[high] + "; return -1";
1✔
677
      }
678
      if (idx == low) {
1✔
679
        return "GT: " + v + " < arr[" + low + "]=" + arr[low]
1✔
680
            + "; return arr[" + low + "]=" + arr[low];
681
      } //idx > low
682
      return "GT: " + v
1✔
683
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " <= " + v + " < arr[" + idx + "]=" + arr[idx]
684
          + "; return arr[" + idx + "]=" + arr[idx];
685
    }
686

687
    @Override
688
    public String desc(final float[] arr, final int low, final int high, final float v, final int idx) {
689
      if (idx == -1) {
1✔
690
        return "GT: " + v + " >= arr[" + high + "]=" + arr[high] + "; return -1";
1✔
691
      }
692
      if (idx == low) {
1✔
693
        return "GT: " + v + " < arr[" + low + "]=" + arr[low]
1✔
694
            + "; return arr[" + low + "]=" + arr[low];
695
      } //idx > low
696
      return "GT: " + v
1✔
697
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " <= " + v + " < arr[" + idx + "]=" + arr[idx]
698
          + "; return arr[" + idx + "]=" + arr[idx];
699
    }
700

701
    @Override
702
    public String desc(final long[] arr, final int low, final int high, final long v, final int idx) {
703
      if (idx == -1) {
1✔
704
        return "GT: " + v + " >= arr[" + high + "]=" + arr[high] + "; return -1";
1✔
705
      }
706
      if (idx == low) {
1✔
707
        return "GT: " + v + " < arr[" + low + "]=" + arr[low]
1✔
708
            + "; return arr[" + low + "]=" + arr[low];
709
      } //idx > low
710
      return "GT: " + v
1✔
711
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " <= " + v + " < arr[" + idx + "]=" + arr[idx]
712
          + "; return arr[" + idx + "]=" + arr[idx];
713
    }
714

715
    @Override
716
    public String desc(final long[] arr, final int low, final int high, final double v, final int idx) {
717
      if (idx == -1) {
×
718
        return "GT: " + v + " >= arr[" + high + "]=" + arr[high] + "; return -1";
×
719
      }
720
      if (idx == low) {
×
721
        return "GT: " + v + " < arr[" + low + "]=" + arr[low]
×
722
            + "; return arr[" + low + "]=" + arr[low];
723
      } //idx > low
724
      return "GT: " + v
×
725
      + ": arr[" + (idx - 1) + "]=" + arr[idx - 1] + " <= " + v + " < arr[" + idx + "]=" + arr[idx]
726
          + "; return arr[" + idx + "]=" + arr[idx];
727
    }
728
  };
729

730
  /**
731
   * The call to compare index a and index b with the value v.
732
   * @param arr The underlying sorted array of values
733
   * @param a the lower index of the current pair
734
   * @param b the higher index of the current pair
735
   * @param v the value to search for
736
   * @return +1, which means we must search higher in the array, or -1, which means we must
737
   * search lower in the array, or 0, which means we have found the correct bounding pair.
738
   */
739
  abstract int compare(double[] arr, int a, int b, double v);
740

741
  /**
742
   * The call to compare index a and index b with the value v.
743
   * @param arr The underlying sorted array of values
744
   * @param a the lower index of the current pair
745
   * @param b the higher index of the current pair
746
   * @param v the value to search for
747
   * @return +1, which means we must search higher in the array, or -1, which means we must
748
   * search lower in the array, or 0, which means we have found the correct bounding pair.
749
   */
750
  abstract int compare(float[] arr, int a, int b, float v);
751

752
  /**
753
   * The call to compare index a and index b with the value v.
754
   * @param arr The underlying sorted array of values
755
   * @param a the lower index of the current pair
756
   * @param b the higher index of the current pair
757
   * @param v the value to search for
758
   * @return +1, which means we must search higher in the array, or -1, which means we must
759
   * search lower in the array, or 0, which means we have found the correct bounding pair.
760
   */
761
  abstract int compare(long[] arr, int a, int b, long v);
762

763
  /**
764
   * The call to compare index a and index b with the value v.
765
   * @param arr The underlying sorted array of values
766
   * @param a the lower index of the current pair
767
   * @param b the higher index of the current pair
768
   * @param v the value to search for
769
   * @return +1, which means we must search higher in the array, or -1, which means we must
770
   * search lower in the array, or 0, which means we have found the correct bounding pair.
771
   */
772
  abstract int compare(long[] arr, int a, int b, double v);
773

774
  /**
775
   * If the compare operation returns 0, which means "found", this returns the index of the
776
   * found value that satisfies the selected criteria.
777
   * @param arr the array being searched
778
   * @param a the lower index of the current pair
779
   * @param b the higher index of the current pair
780
   * @param v the value being searched for.
781
   * @return the index of the found value that satisfies the selected criteria.
782
   */
783
  abstract int getIndex(double[] arr, int a, int b, double v);
784

785
  /**
786
   * If the compare operation returns 0, which means "found", this returns the index of the
787
   * found value that satisfies the selected criteria.
788
   * @param arr the array being searched
789
   * @param a the lower index of the current pair
790
   * @param b the higher index of the current pair
791
   * @param v the value being searched for.
792
   * @return the index of the found value that satisfies the selected criteria.
793
   */
794
  abstract int getIndex(float[] arr, int a, int b, float v);
795

796
  /**
797
   * If the compare operation returns 0, which means "found", this returns the index of the
798
   * found value that satisfies the selected criteria.
799
   * @param arr the array being searched
800
   * @param a the lower index of the current pair
801
   * @param b the higher index of the current pair
802
   * @param v the value being searched for.
803
   * @return the index of the found value that satisfies the selected criteria.
804
   */
805
  abstract int getIndex(long[] arr, int a, int b, long v);
806

807
  /**
808
   * If the compare operation returns 0, which means "found", this returns the index of the
809
   * found value that satisfies the selected criteria.
810
   * @param arr the array being searched
811
   * @param a the lower index of the current pair
812
   * @param b the higher index of the current pair
813
   * @param v the value being searched for.
814
   * @return the index of the found value that satisfies the selected criteria.
815
   */
816
  abstract int getIndex(long[] arr, int a, int b, double v);
817

818
  /**
819
   * Called to resolve the search when the hi and lo pointers are equal or adjacent.
820
   * @param arr the array being searched
821
   * @param lo the current lo value
822
   * @param hi the current hi value
823
   * @param v the value being searched for
824
   * @return the index of the resolution or -1, if it cannot be resolved.
825
   */
826
  abstract int resolve(double[] arr, int lo, int hi, double v);
827

828
  /**
829
   * Called to resolve the search when the hi and lo pointers are equal or adjacent.
830
   * @param arr the array being searched
831
   * @param lo the current lo value
832
   * @param hi the current hi value
833
   * @param v the value being searched for
834
   * @return the index of the resolution or -1, if it cannot be resolved.
835
   */
836
  abstract int resolve(float[] arr, int lo, int hi, float v);
837

838
  /**
839
   * Called to resolve the search when the hi and lo pointers are equal or adjacent.
840
   * @param arr the array being searched
841
   * @param lo the current lo value
842
   * @param hi the current hi value
843
   * @param v the value being searched for
844
   * @return the index of the resolution or -1, if it cannot be resolved.
845
   */
846
  abstract int resolve(long[] arr, int lo, int hi, long v);
847

848
  /**
849
   * Called to resolve the search when the hi and lo pointers are equal or adjacent.
850
   * @param arr the array being searched
851
   * @param lo the current lo value
852
   * @param hi the current hi value
853
   * @param v the value being searched for
854
   * @return the index of the resolution or -1, if it cannot be resolved.
855
   */
856
  abstract int resolve(long[] arr, int lo, int hi, double v);
857

858
  /**
859
   * Optional call that describes the details of the results of the search.
860
   * Used primarily for debugging.
861
   * @param arr The underlying sorted array of values
862
   * @param low the low index of the range
863
   * @param high the high index of the range
864
   * @param v the value to search for
865
   * @param idx the resolved index from the search
866
   * @return the descriptive string.
867
   */
868
  public abstract String desc(double[] arr, int low, int high, double v, int idx);
869

870
  /**
871
   * Optional call that describes the details of the results of the search.
872
   * Used primarily for debugging.
873
   * @param arr The underlying sorted array of values
874
   * @param low the low index of the range
875
   * @param high the high index of the range
876
   * @param v the value to search for
877
   * @param idx the resolved index from the search
878
   * @return the descriptive string.
879
   */
880
  public abstract String desc(float[] arr, int low, int high, float v, int idx);
881

882
  /**
883
   * Optional call that describes the details of the results of the search.
884
   * Used primarily for debugging.
885
   * @param arr The underlying sorted array of values
886
   * @param low the low index of the range
887
   * @param high the high index of the range
888
   * @param v the value to search for
889
   * @param idx the resolved index from the search
890
   * @return the descriptive string.
891
   */
892
  public abstract String desc(long[] arr, int low, int high, long v, int idx);
893

894
  /**
895
   * Optional call that describes the details of the results of the search.
896
   * Used primarily for debugging.
897
   * @param arr The underlying sorted array of values
898
   * @param low the low index of the range
899
   * @param high the high index of the range
900
   * @param v the value to search for
901
   * @param idx the resolved index from the search
902
   * @return the descriptive string.
903
   */
904
  public abstract String desc(long[] arr, int low, int high, double v, int idx);
905

906
  /**
907
   * Binary Search for the index of the double value in the given search range that satisfies
908
   * the given InequalitySearch criterion.
909
   * If -1 is returned there are no values in the search range that satisfy the criterion.
910
   *
911
   * @param arr the given array of comparable values that must be sorted with increasing values.
912
   * The array must not be null and the values of the array must not be NaN in the range [low, high].
913
   * @param low the lowest index of the lowest value in the search range, inclusive.
914
   * @param high the highest index of the highest value in the search range, inclusive.
915
   * @param v the value to search for. It must not be NaN.
916
   * @param crit one of the InequalitySearch criteria: LT, LE, EQ, GT, GE. It must not be null.
917
   * @return the index of the value in the given search range that satisfies the InequalitySearch criterion
918
   */
919
  public static int find(final double[] arr, final int low, final int high,
920
      final double v, final InequalitySearch crit) {
921
    Objects.requireNonNull(arr, "Input arr must not be null");
1✔
922
    Objects.requireNonNull(crit, "Input crit must not be null");
1✔
923
    if (arr.length == 0) { throw new SketchesArgumentException("Input array must not be empty."); }
1✔
924
    if (Double.isNaN(v)) { throw new SketchesArgumentException("Input v must not be NaN."); }
1✔
925
    int lo = low;
1✔
926
    int hi = high;
1✔
927
    while (lo <= hi) {
1✔
928
      if (hi - lo <= 1) {
1✔
929
        return crit.resolve(arr, lo, hi, v);
1✔
930
      }
931
      final int mid = lo + (hi - lo) / 2;
1✔
932
      final int ret = crit.compare(arr, mid, mid + 1, v);
1✔
933
      if (ret == -1 ) { hi = mid; }
1✔
934
      else if (ret == 1) { lo = mid + 1; }
1✔
935
      else  { return crit.getIndex(arr, mid, mid + 1, v); }
1✔
936
    }
1✔
937
    return -1; //should never return here
×
938
  }
939

940
  /**
941
   * Binary Search for the index of the float value in the given search range that satisfies
942
   * the given InequalitySearch criterion.
943
   * If -1 is returned there are no values in the search range that satisfy the criterion.
944
   *
945
   * @param arr the given array that must be sorted.
946
   * It must not be null and must not contain any NaN values in the range {low, high} inclusive.
947
   * @param low the lowest index of the lowest value in the search range, inclusive.
948
   * @param high the highest index of the highest value in the search range, inclusive.
949
   * @param v the value to search for. It must not be NaN.
950
   * @param crit one of LT, LE, EQ, GT, GE
951
   * @return the index of the value in the given search range that satisfies the criterion
952
   */
953
  public static int find(final float[] arr, final int low, final int high,
954
      final float v, final InequalitySearch crit) {
955
    Objects.requireNonNull(arr, "Input arr must not be null");
1✔
956
    Objects.requireNonNull(crit, "Input crit must not be null");
1✔
957
    if (arr.length == 0) { throw new SketchesArgumentException("Input array must not be empty."); }
1✔
958
    if (Float.isNaN(v)) { throw new SketchesArgumentException("Input v must not be NaN."); }
1✔
959
    int lo = low;
1✔
960
    int hi = high;
1✔
961
    while (lo <= hi) {
1✔
962
      if (hi - lo <= 1) {
1✔
963
        return crit.resolve(arr, lo, hi, v);
1✔
964
      }
965
      final int mid = lo + (hi - lo) / 2;
1✔
966
      final int ret = crit.compare(arr, mid, mid + 1, v);
1✔
967
      if (ret == -1 ) { hi = mid; }
1✔
968
      else if (ret == 1) { lo = mid + 1; }
1✔
969
      else  { return crit.getIndex(arr, mid, mid + 1, v); }
1✔
970
    }
1✔
971
    return -1; //should never return here
×
972
  }
973

974
  /**
975
   * Binary Search for the index of the long value in the given search range that satisfies
976
   * the given InequalitySearch criterion.
977
   * If -1 is returned there are no values in the search range that satisfy the criterion.
978
   *
979
   * @param arr the given array that must be sorted.
980
   * @param low the lowest index of the lowest value in the search range, inclusive.
981
   * @param high the highest index of the highest value in the search range, inclusive.
982
   * @param v the value to search for.
983
   * @param crit one of LT, LE, EQ, GT, GE
984
   * @return the index of the value in the given search range that satisfies the criterion
985
   */
986
  public static int find(final long[] arr, final int low, final int high,
987
      final long v, final InequalitySearch crit) {
988
    Objects.requireNonNull(arr, "Input arr must not be null");
1✔
989
    Objects.requireNonNull(crit, "Input crit must not be null");
1✔
990
    if (arr.length == 0) { throw new SketchesArgumentException("Input array must not be empty."); }
1✔
991
    int lo = low;
1✔
992
    int hi = high;
1✔
993
    while (lo <= hi) {
1✔
994
      if (hi - lo <= 1) {
1✔
995
        return crit.resolve(arr, lo, hi, v);
1✔
996
      }
997
      final int mid = lo + (hi - lo) / 2;
1✔
998
      final int ret = crit.compare(arr, mid, mid + 1, v);
1✔
999
      if (ret == -1 ) { hi = mid; }
1✔
1000
      else if (ret == 1) { lo = mid + 1; }
1✔
1001
      else  { return crit.getIndex(arr, mid, mid + 1, v); }
1✔
1002
    }
1✔
1003
    return -1; //should never return here
×
1004
  }
1005

1006
  /**
1007
   * Binary Search for the index of the double value in the given search range that satisfies
1008
   * the given InequalitySearch criterion.
1009
   * If -1 is returned there are no values in the search range that satisfy the criterion.
1010
   *
1011
   * @param arr the given array that must be sorted.
1012
   * @param low the lowest index of the lowest value in the search range, inclusive.
1013
   * @param high the highest index of the highest value in the search range, inclusive.
1014
   * @param v the value to search for.
1015
   * @param crit one of LT, LE, EQ, GT, GE
1016
   * @return the index of the value in the given search range that satisfies the criterion
1017
   */
1018
  public static int find(final long[] arr, final int low, final int high,
1019
      final double v, final InequalitySearch crit) {
1020
    Objects.requireNonNull(arr, "Input arr must not be null");
1✔
1021
    Objects.requireNonNull(crit, "Input crit must not be null");
1✔
1022
    if (arr.length == 0) { throw new SketchesArgumentException("Input array must not be empty."); }
1✔
1023
    int lo = low;
1✔
1024
    int hi = high;
1✔
1025
    while (lo <= hi) {
1✔
1026
      if (hi - lo <= 1) {
1✔
1027
        return crit.resolve(arr, lo, hi, v);
1✔
1028
      }
1029
      final int mid = lo + (hi - lo) / 2;
1✔
1030
      final int ret = crit.compare(arr, mid, mid + 1, v);
1✔
1031
      if (ret == -1 ) { hi = mid; }
1✔
1032
      else if (ret == 1) { lo = mid + 1; }
1✔
1033
      else  { return crit.getIndex(arr, mid, mid + 1, v); }
1✔
1034
    }
1✔
1035
    return -1; //should never return here
×
1036
  }
1037

1038
} //End of enum
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