1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.primitives;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkElementIndex;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkPositionIndexes;
23 import static java.lang.Double.NEGATIVE_INFINITY;
24 import static java.lang.Double.POSITIVE_INFINITY;
25
26 import com.google.common.annotations.Beta;
27 import com.google.common.annotations.GwtCompatible;
28 import com.google.common.annotations.GwtIncompatible;
29 import com.google.common.base.Converter;
30
31 import java.io.Serializable;
32 import java.util.AbstractList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.List;
38 import java.util.RandomAccess;
39 import java.util.regex.Pattern;
40
41 import javax.annotation.Nullable;
42
43
44
45
46
47
48
49
50
51
52
53
54 @GwtCompatible(emulated = true)
55 public final class Doubles {
56 private Doubles() {}
57
58
59
60
61
62
63
64 public static final int BYTES = Double.SIZE / Byte.SIZE;
65
66
67
68
69
70
71
72
73 public static int hashCode(double value) {
74 return ((Double) value).hashCode();
75
76
77
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 public static int compare(double a, double b) {
96 return Double.compare(a, b);
97 }
98
99
100
101
102
103
104
105
106 public static boolean isFinite(double value) {
107 return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
108 }
109
110
111
112
113
114
115
116
117
118
119
120 public static boolean contains(double[] array, double target) {
121 for (double value : array) {
122 if (value == target) {
123 return true;
124 }
125 }
126 return false;
127 }
128
129
130
131
132
133
134
135
136
137
138
139 public static int indexOf(double[] array, double target) {
140 return indexOf(array, target, 0, array.length);
141 }
142
143
144 private static int indexOf(
145 double[] array, double target, int start, int end) {
146 for (int i = start; i < end; i++) {
147 if (array[i] == target) {
148 return i;
149 }
150 }
151 return -1;
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 public static int indexOf(double[] array, double[] target) {
169 checkNotNull(array, "array");
170 checkNotNull(target, "target");
171 if (target.length == 0) {
172 return 0;
173 }
174
175 outer:
176 for (int i = 0; i < array.length - target.length + 1; i++) {
177 for (int j = 0; j < target.length; j++) {
178 if (array[i + j] != target[j]) {
179 continue outer;
180 }
181 }
182 return i;
183 }
184 return -1;
185 }
186
187
188
189
190
191
192
193
194
195
196
197 public static int lastIndexOf(double[] array, double target) {
198 return lastIndexOf(array, target, 0, array.length);
199 }
200
201
202 private static int lastIndexOf(
203 double[] array, double target, int start, int end) {
204 for (int i = end - 1; i >= start; i--) {
205 if (array[i] == target) {
206 return i;
207 }
208 }
209 return -1;
210 }
211
212
213
214
215
216
217
218
219
220
221 public static double min(double... array) {
222 checkArgument(array.length > 0);
223 double min = array[0];
224 for (int i = 1; i < array.length; i++) {
225 min = Math.min(min, array[i]);
226 }
227 return min;
228 }
229
230
231
232
233
234
235
236
237
238
239 public static double max(double... array) {
240 checkArgument(array.length > 0);
241 double max = array[0];
242 for (int i = 1; i < array.length; i++) {
243 max = Math.max(max, array[i]);
244 }
245 return max;
246 }
247
248
249
250
251
252
253
254
255
256
257 public static double[] concat(double[]... arrays) {
258 int length = 0;
259 for (double[] array : arrays) {
260 length += array.length;
261 }
262 double[] result = new double[length];
263 int pos = 0;
264 for (double[] array : arrays) {
265 System.arraycopy(array, 0, result, pos, array.length);
266 pos += array.length;
267 }
268 return result;
269 }
270
271 private static final class DoubleConverter
272 extends Converter<String, Double> implements Serializable {
273 static final DoubleConverter INSTANCE = new DoubleConverter();
274
275 @Override
276 protected Double doForward(String value) {
277 return Double.valueOf(value);
278 }
279
280 @Override
281 protected String doBackward(Double value) {
282 return value.toString();
283 }
284
285 @Override
286 public String toString() {
287 return "Doubles.stringConverter()";
288 }
289
290 private Object readResolve() {
291 return INSTANCE;
292 }
293 private static final long serialVersionUID = 1;
294 }
295
296
297
298
299
300
301
302 @Beta
303 public static Converter<String, Double> stringConverter() {
304 return DoubleConverter.INSTANCE;
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 public static double[] ensureCapacity(
324 double[] array, int minLength, int padding) {
325 checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
326 checkArgument(padding >= 0, "Invalid padding: %s", padding);
327 return (array.length < minLength)
328 ? copyOf(array, minLength + padding)
329 : array;
330 }
331
332
333 private static double[] copyOf(double[] original, int length) {
334 double[] copy = new double[length];
335 System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
336 return copy;
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 public static String join(String separator, double... array) {
354 checkNotNull(separator);
355 if (array.length == 0) {
356 return "";
357 }
358
359
360 StringBuilder builder = new StringBuilder(array.length * 12);
361 builder.append(array[0]);
362 for (int i = 1; i < array.length; i++) {
363 builder.append(separator).append(array[i]);
364 }
365 return builder.toString();
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384 public static Comparator<double[]> lexicographicalComparator() {
385 return LexicographicalComparator.INSTANCE;
386 }
387
388 private enum LexicographicalComparator implements Comparator<double[]> {
389 INSTANCE;
390
391 @Override
392 public int compare(double[] left, double[] right) {
393 int minLength = Math.min(left.length, right.length);
394 for (int i = 0; i < minLength; i++) {
395 int result = Doubles.compare(left[i], right[i]);
396 if (result != 0) {
397 return result;
398 }
399 }
400 return left.length - right.length;
401 }
402 }
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419 public static double[] toArray(Collection<? extends Number> collection) {
420 if (collection instanceof DoubleArrayAsList) {
421 return ((DoubleArrayAsList) collection).toDoubleArray();
422 }
423
424 Object[] boxedArray = collection.toArray();
425 int len = boxedArray.length;
426 double[] array = new double[len];
427 for (int i = 0; i < len; i++) {
428
429 array[i] = ((Number) checkNotNull(boxedArray[i])).doubleValue();
430 }
431 return array;
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451 public static List<Double> asList(double... backingArray) {
452 if (backingArray.length == 0) {
453 return Collections.emptyList();
454 }
455 return new DoubleArrayAsList(backingArray);
456 }
457
458 @GwtCompatible
459 private static class DoubleArrayAsList extends AbstractList<Double>
460 implements RandomAccess, Serializable {
461 final double[] array;
462 final int start;
463 final int end;
464
465 DoubleArrayAsList(double[] array) {
466 this(array, 0, array.length);
467 }
468
469 DoubleArrayAsList(double[] array, int start, int end) {
470 this.array = array;
471 this.start = start;
472 this.end = end;
473 }
474
475 @Override public int size() {
476 return end - start;
477 }
478
479 @Override public boolean isEmpty() {
480 return false;
481 }
482
483 @Override public Double get(int index) {
484 checkElementIndex(index, size());
485 return array[start + index];
486 }
487
488 @Override public boolean contains(Object target) {
489
490 return (target instanceof Double)
491 && Doubles.indexOf(array, (Double) target, start, end) != -1;
492 }
493
494 @Override public int indexOf(Object target) {
495
496 if (target instanceof Double) {
497 int i = Doubles.indexOf(array, (Double) target, start, end);
498 if (i >= 0) {
499 return i - start;
500 }
501 }
502 return -1;
503 }
504
505 @Override public int lastIndexOf(Object target) {
506
507 if (target instanceof Double) {
508 int i = Doubles.lastIndexOf(array, (Double) target, start, end);
509 if (i >= 0) {
510 return i - start;
511 }
512 }
513 return -1;
514 }
515
516 @Override public Double set(int index, Double element) {
517 checkElementIndex(index, size());
518 double oldValue = array[start + index];
519
520 array[start + index] = checkNotNull(element);
521 return oldValue;
522 }
523
524 @Override public List<Double> subList(int fromIndex, int toIndex) {
525 int size = size();
526 checkPositionIndexes(fromIndex, toIndex, size);
527 if (fromIndex == toIndex) {
528 return Collections.emptyList();
529 }
530 return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
531 }
532
533 @Override public boolean equals(Object object) {
534 if (object == this) {
535 return true;
536 }
537 if (object instanceof DoubleArrayAsList) {
538 DoubleArrayAsList that = (DoubleArrayAsList) object;
539 int size = size();
540 if (that.size() != size) {
541 return false;
542 }
543 for (int i = 0; i < size; i++) {
544 if (array[start + i] != that.array[that.start + i]) {
545 return false;
546 }
547 }
548 return true;
549 }
550 return super.equals(object);
551 }
552
553 @Override public int hashCode() {
554 int result = 1;
555 for (int i = start; i < end; i++) {
556 result = 31 * result + Doubles.hashCode(array[i]);
557 }
558 return result;
559 }
560
561 @Override public String toString() {
562 StringBuilder builder = new StringBuilder(size() * 12);
563 builder.append('[').append(array[start]);
564 for (int i = start + 1; i < end; i++) {
565 builder.append(", ").append(array[i]);
566 }
567 return builder.append(']').toString();
568 }
569
570 double[] toDoubleArray() {
571
572 int size = size();
573 double[] result = new double[size];
574 System.arraycopy(array, start, result, 0, size);
575 return result;
576 }
577
578 private static final long serialVersionUID = 0;
579 }
580
581
582
583
584
585
586
587 @GwtIncompatible("regular expressions")
588 static final Pattern FLOATING_POINT_PATTERN = fpPattern();
589
590 @GwtIncompatible("regular expressions")
591 private static Pattern fpPattern() {
592 String decimal = "(?:\\d++(?:\\.\\d*+)?|\\.\\d++)";
593 String completeDec = decimal + "(?:[eE][+-]?\\d++)?[fFdD]?";
594 String hex = "(?:\\p{XDigit}++(?:\\.\\p{XDigit}*+)?|\\.\\p{XDigit}++)";
595 String completeHex = "0[xX]" + hex + "[pP][+-]?\\d++[fFdD]?";
596 String fpPattern = "[+-]?(?:NaN|Infinity|" + completeDec + "|" + completeHex + ")";
597 return Pattern.compile(fpPattern);
598 }
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619 @GwtIncompatible("regular expressions")
620 @Nullable
621 @Beta
622 public static Double tryParse(String string) {
623 if (FLOATING_POINT_PATTERN.matcher(string).matches()) {
624
625
626 try {
627 return Double.parseDouble(string);
628 } catch (NumberFormatException e) {
629
630
631 }
632 }
633 return null;
634 }
635 }