• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.primitives;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 import static java.lang.Double.NaN;
22 
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.annotations.GwtIncompatible;
25 import com.google.common.annotations.J2ktIncompatible;
26 import com.google.common.base.Converter;
27 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.testing.Helpers;
29 import com.google.common.testing.NullPointerTester;
30 import com.google.common.testing.SerializableTester;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.List;
36 import java.util.regex.Pattern;
37 import junit.framework.TestCase;
38 import org.checkerframework.checker.nullness.qual.Nullable;
39 
40 /**
41  * Unit test for {@link Doubles}.
42  *
43  * @author Kevin Bourrillion
44  */
45 @ElementTypesAreNonnullByDefault
46 @GwtCompatible(emulated = true)
47 public class DoublesTest extends TestCase {
48   private static final double[] EMPTY = {};
49   private static final double[] ARRAY1 = {(double) 1};
50   private static final double[] ARRAY234 = {(double) 2, (double) 3, (double) 4};
51 
52   private static final double LEAST = Double.NEGATIVE_INFINITY;
53   private static final double GREATEST = Double.POSITIVE_INFINITY;
54 
55   private static final double[] NUMBERS =
56       new double[] {
57         LEAST,
58         -Double.MAX_VALUE,
59         -1.0,
60         -0.5,
61         -0.1,
62         -0.0,
63         0.0,
64         0.1,
65         0.5,
66         1.0,
67         Double.MAX_VALUE,
68         GREATEST,
69         Double.MIN_NORMAL,
70         -Double.MIN_NORMAL,
71         Double.MIN_VALUE,
72         -Double.MIN_VALUE,
73         Integer.MIN_VALUE,
74         Integer.MAX_VALUE,
75         Long.MIN_VALUE,
76         Long.MAX_VALUE
77       };
78 
79   private static final double[] VALUES = Doubles.concat(NUMBERS, new double[] {NaN});
80 
testHashCode()81   public void testHashCode() {
82     for (double value : VALUES) {
83       assertThat(Doubles.hashCode(value)).isEqualTo(((Double) value).hashCode());
84     }
85   }
86 
testIsFinite()87   public void testIsFinite() {
88     for (double value : NUMBERS) {
89       assertThat(Doubles.isFinite(value))
90           .isEqualTo(!(Double.isNaN(value) || Double.isInfinite(value)));
91     }
92   }
93 
testCompare()94   public void testCompare() {
95     for (double x : VALUES) {
96       for (double y : VALUES) {
97         // note: spec requires only that the sign is the same
98         assertWithMessage(x + ", " + y)
99             .that(Doubles.compare(x, y))
100             .isEqualTo(Double.valueOf(x).compareTo(y));
101       }
102     }
103   }
104 
testContains()105   public void testContains() {
106     assertThat(Doubles.contains(EMPTY, (double) 1)).isFalse();
107     assertThat(Doubles.contains(ARRAY1, (double) 2)).isFalse();
108     assertThat(Doubles.contains(ARRAY234, (double) 1)).isFalse();
109     assertThat(Doubles.contains(new double[] {(double) -1}, (double) -1)).isTrue();
110     assertThat(Doubles.contains(ARRAY234, (double) 2)).isTrue();
111     assertThat(Doubles.contains(ARRAY234, (double) 3)).isTrue();
112     assertThat(Doubles.contains(ARRAY234, (double) 4)).isTrue();
113 
114     for (double value : NUMBERS) {
115       assertWithMessage("" + value)
116           .that(Doubles.contains(new double[] {5.0, value}, value))
117           .isTrue();
118     }
119     assertThat(Doubles.contains(new double[] {5.0, NaN}, NaN)).isFalse();
120   }
121 
testIndexOf()122   public void testIndexOf() {
123     assertThat(Doubles.indexOf(EMPTY, (double) 1)).isEqualTo(-1);
124     assertThat(Doubles.indexOf(ARRAY1, (double) 2)).isEqualTo(-1);
125     assertThat(Doubles.indexOf(ARRAY234, (double) 1)).isEqualTo(-1);
126     assertThat(Doubles.indexOf(new double[] {(double) -1}, (double) -1)).isEqualTo(0);
127     assertThat(Doubles.indexOf(ARRAY234, (double) 2)).isEqualTo(0);
128     assertThat(Doubles.indexOf(ARRAY234, (double) 3)).isEqualTo(1);
129     assertThat(Doubles.indexOf(ARRAY234, (double) 4)).isEqualTo(2);
130     assertThat(
131             Doubles.indexOf(
132                 new double[] {(double) 2, (double) 3, (double) 2, (double) 3}, (double) 3))
133         .isEqualTo(1);
134 
135     for (double value : NUMBERS) {
136       assertWithMessage("" + value)
137           .that(Doubles.indexOf(new double[] {5.0, value}, value))
138           .isEqualTo(1);
139     }
140     assertThat(Doubles.indexOf(new double[] {5.0, NaN}, NaN)).isEqualTo(-1);
141   }
142 
testIndexOf_arrayTarget()143   public void testIndexOf_arrayTarget() {
144     assertThat(Doubles.indexOf(EMPTY, EMPTY)).isEqualTo(0);
145     assertThat(Doubles.indexOf(ARRAY234, EMPTY)).isEqualTo(0);
146     assertThat(Doubles.indexOf(EMPTY, ARRAY234)).isEqualTo(-1);
147     assertThat(Doubles.indexOf(ARRAY234, ARRAY1)).isEqualTo(-1);
148     assertThat(Doubles.indexOf(ARRAY1, ARRAY234)).isEqualTo(-1);
149     assertThat(Doubles.indexOf(ARRAY1, ARRAY1)).isEqualTo(0);
150     assertThat(Doubles.indexOf(ARRAY234, ARRAY234)).isEqualTo(0);
151     assertThat(Doubles.indexOf(ARRAY234, new double[] {(double) 2, (double) 3})).isEqualTo(0);
152     assertThat(Doubles.indexOf(ARRAY234, new double[] {(double) 3, (double) 4})).isEqualTo(1);
153     assertThat(Doubles.indexOf(ARRAY234, new double[] {(double) 3})).isEqualTo(1);
154     assertThat(Doubles.indexOf(ARRAY234, new double[] {(double) 4})).isEqualTo(2);
155     assertThat(
156             Doubles.indexOf(
157                 new double[] {(double) 2, (double) 3, (double) 3, (double) 3, (double) 3},
158                 new double[] {(double) 3}))
159         .isEqualTo(1);
160     assertThat(
161             Doubles.indexOf(
162                 new double[] {
163                   (double) 2, (double) 3, (double) 2, (double) 3, (double) 4, (double) 2, (double) 3
164                 },
165                 new double[] {(double) 2, (double) 3, (double) 4}))
166         .isEqualTo(2);
167     assertThat(
168             Doubles.indexOf(
169                 new double[] {
170                   (double) 2, (double) 2, (double) 3, (double) 4, (double) 2, (double) 3, (double) 4
171                 },
172                 new double[] {(double) 2, (double) 3, (double) 4}))
173         .isEqualTo(1);
174     assertThat(
175             Doubles.indexOf(
176                 new double[] {(double) 4, (double) 3, (double) 2},
177                 new double[] {(double) 2, (double) 3, (double) 4}))
178         .isEqualTo(-1);
179 
180     for (double value : NUMBERS) {
181       assertWithMessage("" + value)
182           .that(Doubles.indexOf(new double[] {5.0, value, value, 5.0}, new double[] {value, value}))
183           .isEqualTo(1);
184     }
185     assertThat(Doubles.indexOf(new double[] {5.0, NaN, NaN, 5.0}, new double[] {NaN, NaN}))
186         .isEqualTo(-1);
187   }
188 
testLastIndexOf()189   public void testLastIndexOf() {
190     assertThat(Doubles.lastIndexOf(EMPTY, (double) 1)).isEqualTo(-1);
191     assertThat(Doubles.lastIndexOf(ARRAY1, (double) 2)).isEqualTo(-1);
192     assertThat(Doubles.lastIndexOf(ARRAY234, (double) 1)).isEqualTo(-1);
193     assertThat(Doubles.lastIndexOf(new double[] {(double) -1}, (double) -1)).isEqualTo(0);
194     assertThat(Doubles.lastIndexOf(ARRAY234, (double) 2)).isEqualTo(0);
195     assertThat(Doubles.lastIndexOf(ARRAY234, (double) 3)).isEqualTo(1);
196     assertThat(Doubles.lastIndexOf(ARRAY234, (double) 4)).isEqualTo(2);
197     assertThat(
198             Doubles.lastIndexOf(
199                 new double[] {(double) 2, (double) 3, (double) 2, (double) 3}, (double) 3))
200         .isEqualTo(3);
201 
202     for (double value : NUMBERS) {
203       assertWithMessage("" + value)
204           .that(Doubles.lastIndexOf(new double[] {value, 5.0}, value))
205           .isEqualTo(0);
206     }
207     assertThat(Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN)).isEqualTo(-1);
208   }
209 
210   @GwtIncompatible
testMax_noArgs()211   public void testMax_noArgs() {
212     try {
213       Doubles.max();
214       fail();
215     } catch (IllegalArgumentException expected) {
216     }
217   }
218 
testMax()219   public void testMax() {
220     assertThat(Doubles.max(LEAST)).isEqualTo(LEAST);
221     assertThat(Doubles.max(GREATEST)).isEqualTo(GREATEST);
222     assertThat(
223             Doubles.max(
224                 (double) 8, (double) 6, (double) 7, (double) 5, (double) 3, (double) 0, (double) 9))
225         .isEqualTo((double) 9);
226 
227     assertThat(Doubles.max(-0.0, 0.0)).isEqualTo(0.0);
228     assertThat(Doubles.max(0.0, -0.0)).isEqualTo(0.0);
229     assertThat(Doubles.max(NUMBERS)).isEqualTo(GREATEST);
230     assertThat(Double.isNaN(Doubles.max(VALUES))).isTrue();
231   }
232 
233   @GwtIncompatible
testMin_noArgs()234   public void testMin_noArgs() {
235     try {
236       Doubles.min();
237       fail();
238     } catch (IllegalArgumentException expected) {
239     }
240   }
241 
testMin()242   public void testMin() {
243     assertThat(Doubles.min(LEAST)).isEqualTo(LEAST);
244     assertThat(Doubles.min(GREATEST)).isEqualTo(GREATEST);
245     assertThat(
246             Doubles.min(
247                 (double) 8, (double) 6, (double) 7, (double) 5, (double) 3, (double) 0, (double) 9))
248         .isEqualTo((double) 0);
249 
250     assertThat(Doubles.min(-0.0, 0.0)).isEqualTo(-0.0);
251     assertThat(Doubles.min(0.0, -0.0)).isEqualTo(-0.0);
252     assertThat(Doubles.min(NUMBERS)).isEqualTo(LEAST);
253     assertThat(Double.isNaN(Doubles.min(VALUES))).isTrue();
254   }
255 
testConstrainToRange()256   public void testConstrainToRange() {
257     assertThat(Doubles.constrainToRange((double) 1, (double) 0, (double) 5)).isEqualTo((double) 1);
258     assertThat(Doubles.constrainToRange((double) 1, (double) 1, (double) 5)).isEqualTo((double) 1);
259     assertThat(Doubles.constrainToRange((double) 1, (double) 3, (double) 5)).isEqualTo((double) 3);
260     assertThat(Doubles.constrainToRange((double) 0, (double) -5, (double) -1))
261         .isEqualTo((double) -1);
262     assertThat(Doubles.constrainToRange((double) 5, (double) 2, (double) 2)).isEqualTo((double) 2);
263     try {
264       Doubles.constrainToRange((double) 1, (double) 3, (double) 2);
265       fail();
266     } catch (IllegalArgumentException expected) {
267     }
268   }
269 
testConcat()270   public void testConcat() {
271     assertThat(Doubles.concat()).isEqualTo(EMPTY);
272     assertThat(Doubles.concat(EMPTY)).isEqualTo(EMPTY);
273     assertThat(Doubles.concat(EMPTY, EMPTY, EMPTY)).isEqualTo(EMPTY);
274     assertThat(Doubles.concat(ARRAY1)).isEqualTo(ARRAY1);
275     assertThat(Doubles.concat(ARRAY1)).isNotSameInstanceAs(ARRAY1);
276     assertThat(Doubles.concat(EMPTY, ARRAY1, EMPTY)).isEqualTo(ARRAY1);
277     assertThat(Doubles.concat(ARRAY1, ARRAY1, ARRAY1))
278         .isEqualTo(new double[] {(double) 1, (double) 1, (double) 1});
279     assertThat(Doubles.concat(ARRAY1, ARRAY234))
280         .isEqualTo(new double[] {(double) 1, (double) 2, (double) 3, (double) 4});
281   }
282 
283   @GwtIncompatible // different overflow behavior; could probably be made to work by using ~~
testConcat_overflow_negative()284   public void testConcat_overflow_negative() {
285     int dim1 = 1 << 16;
286     int dim2 = 1 << 15;
287     assertThat(dim1 * dim2).isLessThan(0);
288     testConcatOverflow(dim1, dim2);
289   }
290 
291   @GwtIncompatible // different overflow behavior; could probably be made to work by using ~~
testConcat_overflow_nonNegative()292   public void testConcat_overflow_nonNegative() {
293     int dim1 = 1 << 16;
294     int dim2 = 1 << 16;
295     assertThat(dim1 * dim2).isAtLeast(0);
296     testConcatOverflow(dim1, dim2);
297   }
298 
testConcatOverflow(int arraysDim1, int arraysDim2)299   private static void testConcatOverflow(int arraysDim1, int arraysDim2) {
300     assertThat((long) arraysDim1 * arraysDim2).isNotEqualTo((long) (arraysDim1 * arraysDim2));
301 
302     double[][] arrays = new double[arraysDim1][];
303     // it's shared to avoid using too much memory in tests
304     double[] sharedArray = new double[arraysDim2];
305     Arrays.fill(arrays, sharedArray);
306 
307     try {
308       Doubles.concat(arrays);
309       fail();
310     } catch (IllegalArgumentException expected) {
311     }
312   }
313 
testEnsureCapacity()314   public void testEnsureCapacity() {
315     assertThat(Doubles.ensureCapacity(EMPTY, 0, 1)).isSameInstanceAs(EMPTY);
316     assertThat(Doubles.ensureCapacity(ARRAY1, 0, 1)).isSameInstanceAs(ARRAY1);
317     assertThat(Doubles.ensureCapacity(ARRAY1, 1, 1)).isSameInstanceAs(ARRAY1);
318     assertThat(
319             Arrays.equals(
320                 new double[] {(double) 1, (double) 0, (double) 0},
321                 Doubles.ensureCapacity(ARRAY1, 2, 1)))
322         .isTrue();
323   }
324 
testEnsureCapacity_fail()325   public void testEnsureCapacity_fail() {
326     try {
327       Doubles.ensureCapacity(ARRAY1, -1, 1);
328       fail();
329     } catch (IllegalArgumentException expected) {
330     }
331     try {
332       // notice that this should even fail when no growth was needed
333       Doubles.ensureCapacity(ARRAY1, 1, -1);
334       fail();
335     } catch (IllegalArgumentException expected) {
336     }
337   }
338 
339   @GwtIncompatible // Double.toString returns different value in GWT.
testJoin()340   public void testJoin() {
341     assertThat(Doubles.join(",", EMPTY)).isEmpty();
342     assertThat(Doubles.join(",", ARRAY1)).isEqualTo("1.0");
343     assertThat(Doubles.join(",", (double) 1, (double) 2)).isEqualTo("1.0,2.0");
344     assertThat(Doubles.join("", (double) 1, (double) 2, (double) 3)).isEqualTo("1.02.03.0");
345   }
346 
testJoinNonTrivialDoubles()347   public void testJoinNonTrivialDoubles() {
348     assertThat(Doubles.join(",", EMPTY)).isEmpty();
349     assertThat(Doubles.join(",", 1.2)).isEqualTo("1.2");
350     assertThat(Doubles.join(",", 1.3, 2.4)).isEqualTo("1.3,2.4");
351     assertThat(Doubles.join("", 1.4, 2.5, 3.6)).isEqualTo("1.42.53.6");
352   }
353 
testLexicographicalComparator()354   public void testLexicographicalComparator() {
355     List<double[]> ordered =
356         Arrays.asList(
357             new double[] {},
358             new double[] {LEAST},
359             new double[] {LEAST, LEAST},
360             new double[] {LEAST, (double) 1},
361             new double[] {(double) 1},
362             new double[] {(double) 1, LEAST},
363             new double[] {GREATEST, Double.MAX_VALUE},
364             new double[] {GREATEST, GREATEST},
365             new double[] {GREATEST, GREATEST, GREATEST});
366 
367     Comparator<double[]> comparator = Doubles.lexicographicalComparator();
368     Helpers.testComparator(comparator, ordered);
369   }
370 
testReverse()371   public void testReverse() {
372     testReverse(new double[] {}, new double[] {});
373     testReverse(new double[] {1}, new double[] {1});
374     testReverse(new double[] {1, 2}, new double[] {2, 1});
375     testReverse(new double[] {3, 1, 1}, new double[] {1, 1, 3});
376     testReverse(new double[] {-1, 1, -2, 2}, new double[] {2, -2, 1, -1});
377   }
378 
testReverse(double[] input, double[] expectedOutput)379   private static void testReverse(double[] input, double[] expectedOutput) {
380     input = Arrays.copyOf(input, input.length);
381     Doubles.reverse(input);
382     assertThat(input).isEqualTo(expectedOutput);
383   }
384 
testReverse( double[] input, int fromIndex, int toIndex, double[] expectedOutput)385   private static void testReverse(
386       double[] input, int fromIndex, int toIndex, double[] expectedOutput) {
387     input = Arrays.copyOf(input, input.length);
388     Doubles.reverse(input, fromIndex, toIndex);
389     assertThat(input).isEqualTo(expectedOutput);
390   }
391 
testReverseIndexed()392   public void testReverseIndexed() {
393     testReverse(new double[] {}, 0, 0, new double[] {});
394     testReverse(new double[] {1}, 0, 1, new double[] {1});
395     testReverse(new double[] {1, 2}, 0, 2, new double[] {2, 1});
396     testReverse(new double[] {3, 1, 1}, 0, 2, new double[] {1, 3, 1});
397     testReverse(new double[] {3, 1, 1}, 0, 1, new double[] {3, 1, 1});
398     testReverse(new double[] {-1, 1, -2, 2}, 1, 3, new double[] {-1, -2, 1, 2});
399   }
400 
testRotate(double[] input, int distance, double[] expectedOutput)401   private static void testRotate(double[] input, int distance, double[] expectedOutput) {
402     input = Arrays.copyOf(input, input.length);
403     Doubles.rotate(input, distance);
404     assertThat(input).isEqualTo(expectedOutput);
405   }
406 
testRotate( double[] input, int distance, int fromIndex, int toIndex, double[] expectedOutput)407   private static void testRotate(
408       double[] input, int distance, int fromIndex, int toIndex, double[] expectedOutput) {
409     input = Arrays.copyOf(input, input.length);
410     Doubles.rotate(input, distance, fromIndex, toIndex);
411     assertThat(input).isEqualTo(expectedOutput);
412   }
413 
testRotate()414   public void testRotate() {
415     testRotate(new double[] {}, -1, new double[] {});
416     testRotate(new double[] {}, 0, new double[] {});
417     testRotate(new double[] {}, 1, new double[] {});
418 
419     testRotate(new double[] {1}, -2, new double[] {1});
420     testRotate(new double[] {1}, -1, new double[] {1});
421     testRotate(new double[] {1}, 0, new double[] {1});
422     testRotate(new double[] {1}, 1, new double[] {1});
423     testRotate(new double[] {1}, 2, new double[] {1});
424 
425     testRotate(new double[] {1, 2}, -3, new double[] {2, 1});
426     testRotate(new double[] {1, 2}, -1, new double[] {2, 1});
427     testRotate(new double[] {1, 2}, -2, new double[] {1, 2});
428     testRotate(new double[] {1, 2}, 0, new double[] {1, 2});
429     testRotate(new double[] {1, 2}, 1, new double[] {2, 1});
430     testRotate(new double[] {1, 2}, 2, new double[] {1, 2});
431     testRotate(new double[] {1, 2}, 3, new double[] {2, 1});
432 
433     testRotate(new double[] {1, 2, 3}, -5, new double[] {3, 1, 2});
434     testRotate(new double[] {1, 2, 3}, -4, new double[] {2, 3, 1});
435     testRotate(new double[] {1, 2, 3}, -3, new double[] {1, 2, 3});
436     testRotate(new double[] {1, 2, 3}, -2, new double[] {3, 1, 2});
437     testRotate(new double[] {1, 2, 3}, -1, new double[] {2, 3, 1});
438     testRotate(new double[] {1, 2, 3}, 0, new double[] {1, 2, 3});
439     testRotate(new double[] {1, 2, 3}, 1, new double[] {3, 1, 2});
440     testRotate(new double[] {1, 2, 3}, 2, new double[] {2, 3, 1});
441     testRotate(new double[] {1, 2, 3}, 3, new double[] {1, 2, 3});
442     testRotate(new double[] {1, 2, 3}, 4, new double[] {3, 1, 2});
443     testRotate(new double[] {1, 2, 3}, 5, new double[] {2, 3, 1});
444 
445     testRotate(new double[] {1, 2, 3, 4}, -9, new double[] {2, 3, 4, 1});
446     testRotate(new double[] {1, 2, 3, 4}, -5, new double[] {2, 3, 4, 1});
447     testRotate(new double[] {1, 2, 3, 4}, -1, new double[] {2, 3, 4, 1});
448     testRotate(new double[] {1, 2, 3, 4}, 0, new double[] {1, 2, 3, 4});
449     testRotate(new double[] {1, 2, 3, 4}, 1, new double[] {4, 1, 2, 3});
450     testRotate(new double[] {1, 2, 3, 4}, 5, new double[] {4, 1, 2, 3});
451     testRotate(new double[] {1, 2, 3, 4}, 9, new double[] {4, 1, 2, 3});
452 
453     testRotate(new double[] {1, 2, 3, 4, 5}, -6, new double[] {2, 3, 4, 5, 1});
454     testRotate(new double[] {1, 2, 3, 4, 5}, -4, new double[] {5, 1, 2, 3, 4});
455     testRotate(new double[] {1, 2, 3, 4, 5}, -3, new double[] {4, 5, 1, 2, 3});
456     testRotate(new double[] {1, 2, 3, 4, 5}, -1, new double[] {2, 3, 4, 5, 1});
457     testRotate(new double[] {1, 2, 3, 4, 5}, 0, new double[] {1, 2, 3, 4, 5});
458     testRotate(new double[] {1, 2, 3, 4, 5}, 1, new double[] {5, 1, 2, 3, 4});
459     testRotate(new double[] {1, 2, 3, 4, 5}, 3, new double[] {3, 4, 5, 1, 2});
460     testRotate(new double[] {1, 2, 3, 4, 5}, 4, new double[] {2, 3, 4, 5, 1});
461     testRotate(new double[] {1, 2, 3, 4, 5}, 6, new double[] {5, 1, 2, 3, 4});
462   }
463 
testRotateIndexed()464   public void testRotateIndexed() {
465     testRotate(new double[] {}, 0, 0, 0, new double[] {});
466 
467     testRotate(new double[] {1}, 0, 0, 1, new double[] {1});
468     testRotate(new double[] {1}, 1, 0, 1, new double[] {1});
469     testRotate(new double[] {1}, 1, 1, 1, new double[] {1});
470 
471     // Rotate the central 5 elements, leaving the ends as-is
472     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -6, 1, 6, new double[] {0, 2, 3, 4, 5, 1, 6});
473     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -1, 1, 6, new double[] {0, 2, 3, 4, 5, 1, 6});
474     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 0, 1, 6, new double[] {0, 1, 2, 3, 4, 5, 6});
475     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 5, 1, 6, new double[] {0, 1, 2, 3, 4, 5, 6});
476     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 14, 1, 6, new double[] {0, 2, 3, 4, 5, 1, 6});
477 
478     // Rotate the first three elements
479     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -2, 0, 3, new double[] {2, 0, 1, 3, 4, 5, 6});
480     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -1, 0, 3, new double[] {1, 2, 0, 3, 4, 5, 6});
481     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 0, 0, 3, new double[] {0, 1, 2, 3, 4, 5, 6});
482     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 1, 0, 3, new double[] {2, 0, 1, 3, 4, 5, 6});
483     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 2, 0, 3, new double[] {1, 2, 0, 3, 4, 5, 6});
484 
485     // Rotate the last four elements
486     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -6, 3, 7, new double[] {0, 1, 2, 5, 6, 3, 4});
487     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -5, 3, 7, new double[] {0, 1, 2, 4, 5, 6, 3});
488     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -4, 3, 7, new double[] {0, 1, 2, 3, 4, 5, 6});
489     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -3, 3, 7, new double[] {0, 1, 2, 6, 3, 4, 5});
490     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -2, 3, 7, new double[] {0, 1, 2, 5, 6, 3, 4});
491     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, -1, 3, 7, new double[] {0, 1, 2, 4, 5, 6, 3});
492     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 0, 3, 7, new double[] {0, 1, 2, 3, 4, 5, 6});
493     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 1, 3, 7, new double[] {0, 1, 2, 6, 3, 4, 5});
494     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 2, 3, 7, new double[] {0, 1, 2, 5, 6, 3, 4});
495     testRotate(new double[] {0, 1, 2, 3, 4, 5, 6}, 3, 3, 7, new double[] {0, 1, 2, 4, 5, 6, 3});
496   }
497 
testSortDescending()498   public void testSortDescending() {
499     testSortDescending(new double[] {}, new double[] {});
500     testSortDescending(new double[] {1}, new double[] {1});
501     testSortDescending(new double[] {1, 2}, new double[] {2, 1});
502     testSortDescending(new double[] {1, 3, 1}, new double[] {3, 1, 1});
503     testSortDescending(new double[] {-1, 1, -2, 2}, new double[] {2, 1, -1, -2});
504     testSortDescending(
505         new double[] {-1, 1, Double.NaN, -2, -0.0, 0, 2},
506         new double[] {Double.NaN, 2, 1, 0, -0.0, -1, -2});
507   }
508 
testSortDescending(double[] input, double[] expectedOutput)509   private static void testSortDescending(double[] input, double[] expectedOutput) {
510     input = Arrays.copyOf(input, input.length);
511     Doubles.sortDescending(input);
512     for (int i = 0; i < input.length; i++) {
513       assertThat(input[i]).isEqualTo(expectedOutput[i]);
514     }
515   }
516 
testSortDescending( double[] input, int fromIndex, int toIndex, double[] expectedOutput)517   private static void testSortDescending(
518       double[] input, int fromIndex, int toIndex, double[] expectedOutput) {
519     input = Arrays.copyOf(input, input.length);
520     Doubles.sortDescending(input, fromIndex, toIndex);
521     for (int i = 0; i < input.length; i++) {
522       assertThat(input[i]).isEqualTo(expectedOutput[i]);
523     }
524   }
525 
testSortDescendingIndexed()526   public void testSortDescendingIndexed() {
527     testSortDescending(new double[] {}, 0, 0, new double[] {});
528     testSortDescending(new double[] {1}, 0, 1, new double[] {1});
529     testSortDescending(new double[] {1, 2}, 0, 2, new double[] {2, 1});
530     testSortDescending(new double[] {1, 3, 1}, 0, 2, new double[] {3, 1, 1});
531     testSortDescending(new double[] {1, 3, 1}, 0, 1, new double[] {1, 3, 1});
532     testSortDescending(new double[] {-1, -2, 1, 2}, 1, 3, new double[] {-1, 1, -2, 2});
533     testSortDescending(
534         new double[] {-1, 1, Double.NaN, -2, 2}, 1, 4, new double[] {-1, Double.NaN, 1, -2, 2});
535   }
536 
537   @J2ktIncompatible
538   @GwtIncompatible // SerializableTester
testLexicographicalComparatorSerializable()539   public void testLexicographicalComparatorSerializable() {
540     Comparator<double[]> comparator = Doubles.lexicographicalComparator();
541     assertThat(SerializableTester.reserialize(comparator)).isSameInstanceAs(comparator);
542   }
543 
544   @J2ktIncompatible
545   @GwtIncompatible // SerializableTester
testStringConverterSerialization()546   public void testStringConverterSerialization() {
547     SerializableTester.reserializeAndAssert(Doubles.stringConverter());
548   }
549 
testToArray()550   public void testToArray() {
551     // need explicit type parameter to avoid javac warning!?
552     List<Double> none = Arrays.<Double>asList();
553     assertThat(Doubles.toArray(none)).isEqualTo(EMPTY);
554 
555     List<Double> one = Arrays.asList((double) 1);
556     assertThat(Doubles.toArray(one)).isEqualTo(ARRAY1);
557 
558     double[] array = {(double) 0, (double) 1, Math.PI};
559 
560     List<Double> three = Arrays.asList((double) 0, (double) 1, Math.PI);
561     assertThat(Doubles.toArray(three)).isEqualTo(array);
562 
563     assertThat(Doubles.toArray(Doubles.asList(array))).isEqualTo(array);
564   }
565 
testToArray_threadSafe()566   public void testToArray_threadSafe() {
567     for (int delta : new int[] {+1, 0, -1}) {
568       for (int i = 0; i < VALUES.length; i++) {
569         List<Double> list = Doubles.asList(VALUES).subList(0, i);
570         Collection<Double> misleadingSize = Helpers.misleadingSizeCollection(delta);
571         misleadingSize.addAll(list);
572         double[] arr = Doubles.toArray(misleadingSize);
573         assertThat(arr.length).isEqualTo(i);
574         for (int j = 0; j < i; j++) {
575           assertThat(arr[j]).isEqualTo(VALUES[j]);
576         }
577       }
578     }
579   }
580 
testToArray_withNull()581   public void testToArray_withNull() {
582     List<@Nullable Double> list = Arrays.asList((double) 0, (double) 1, null);
583     try {
584       Doubles.toArray(list);
585       fail();
586     } catch (NullPointerException expected) {
587     }
588   }
589 
testToArray_withConversion()590   public void testToArray_withConversion() {
591     double[] array = {(double) 0, (double) 1, (double) 2};
592 
593     List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
594     List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
595     List<Integer> ints = Arrays.asList(0, 1, 2);
596     List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
597     List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
598     List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
599 
600     assertThat(Doubles.toArray(bytes)).isEqualTo(array);
601     assertThat(Doubles.toArray(shorts)).isEqualTo(array);
602     assertThat(Doubles.toArray(ints)).isEqualTo(array);
603     assertThat(Doubles.toArray(floats)).isEqualTo(array);
604     assertThat(Doubles.toArray(longs)).isEqualTo(array);
605     assertThat(Doubles.toArray(doubles)).isEqualTo(array);
606   }
607 
608   @J2ktIncompatible // b/239034072: Kotlin varargs copy parameter arrays.
testAsList_isAView()609   public void testAsList_isAView() {
610     double[] array = {(double) 0, (double) 1};
611     List<Double> list = Doubles.asList(array);
612     list.set(0, (double) 2);
613     assertThat(array).isEqualTo(new double[] {(double) 2, (double) 1});
614     array[1] = (double) 3;
615     assertThat(list).containsExactly((double) 2, (double) 3).inOrder();
616   }
617 
testAsList_toArray_roundTrip()618   public void testAsList_toArray_roundTrip() {
619     double[] array = {(double) 0, (double) 1, (double) 2};
620     List<Double> list = Doubles.asList(array);
621     double[] newArray = Doubles.toArray(list);
622 
623     // Make sure it returned a copy
624     list.set(0, (double) 4);
625     assertThat(newArray).isEqualTo(new double[] {(double) 0, (double) 1, (double) 2});
626     newArray[1] = (double) 5;
627     assertThat((double) list.get(1)).isEqualTo((double) 1);
628   }
629 
630   // This test stems from a real bug found by andrewk
testAsList_subList_toArray_roundTrip()631   public void testAsList_subList_toArray_roundTrip() {
632     double[] array = {(double) 0, (double) 1, (double) 2, (double) 3};
633     List<Double> list = Doubles.asList(array);
634     assertThat(Doubles.toArray(list.subList(1, 3)))
635         .isEqualTo(new double[] {(double) 1, (double) 2});
636     assertThat(Doubles.toArray(list.subList(2, 2))).isEmpty();
637   }
638 
testAsListEmpty()639   public void testAsListEmpty() {
640     assertThat(Doubles.asList(EMPTY)).isSameInstanceAs(Collections.emptyList());
641   }
642 
643   /**
644    * A reference implementation for {@code tryParse} that just catches the exception from {@link
645    * Double#valueOf}.
646    */
referenceTryParse(String input)647   private static @Nullable Double referenceTryParse(String input) {
648     if (input.trim().length() < input.length()) {
649       return null;
650     }
651     try {
652       return Double.valueOf(input);
653     } catch (NumberFormatException e) {
654       return null;
655     }
656   }
657 
658   @GwtIncompatible // Doubles.tryParse
checkTryParse(String input)659   private static void checkTryParse(String input) {
660     Double expected = referenceTryParse(input);
661     assertThat(Doubles.tryParse(input)).isEqualTo(expected);
662     if (expected != null && !Doubles.FLOATING_POINT_PATTERN.matcher(input).matches()) {
663       // TODO(cpovirk): Use SourceCodeEscapers if it is added to Guava.
664       StringBuilder escapedInput = new StringBuilder();
665       for (char c : input.toCharArray()) {
666         if (c >= 0x20 && c <= 0x7E) {
667           escapedInput.append(c);
668         } else {
669           escapedInput.append(String.format("\\u%04x", (int) c));
670         }
671       }
672       fail("FLOATING_POINT_PATTERN should have matched valid input <" + escapedInput + ">");
673     }
674   }
675 
676   @GwtIncompatible // Doubles.tryParse
checkTryParse(double expected, String input)677   private static void checkTryParse(double expected, String input) {
678     assertThat(Doubles.tryParse(input)).isEqualTo(Double.valueOf(expected));
679     assertThat(input)
680         .matches(
681             Pattern.compile(
682                 Doubles.FLOATING_POINT_PATTERN.pattern(), Doubles.FLOATING_POINT_PATTERN.flags()));
683   }
684 
685   @GwtIncompatible // Doubles.tryParse
testTryParseHex()686   public void testTryParseHex() {
687     for (String signChar : ImmutableList.of("", "+", "-")) {
688       for (String hexPrefix : ImmutableList.of("0x", "0X")) {
689         for (String iPart : ImmutableList.of("", "0", "1", "F", "f", "c4", "CE")) {
690           for (String fPart : ImmutableList.of("", ".", ".F", ".52", ".a")) {
691             for (String expMarker : ImmutableList.of("p", "P")) {
692               for (String exponent : ImmutableList.of("0", "-5", "+20", "52")) {
693                 for (String typePart : ImmutableList.of("", "D", "F", "d", "f")) {
694                   checkTryParse(
695                       signChar + hexPrefix + iPart + fPart + expMarker + exponent + typePart);
696                 }
697               }
698             }
699           }
700         }
701       }
702     }
703   }
704 
705   @AndroidIncompatible // slow
706   @GwtIncompatible // Doubles.tryParse
testTryParseAllCodePoints()707   public void testTryParseAllCodePoints() {
708     // Exercise non-ASCII digit test cases and the like.
709     char[] tmp = new char[2];
710     for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) {
711       Character.toChars(i, tmp, 0);
712       checkTryParse(String.copyValueOf(tmp, 0, Character.charCount(i)));
713     }
714   }
715 
716   @GwtIncompatible // Doubles.tryParse
testTryParseOfToStringIsOriginal()717   public void testTryParseOfToStringIsOriginal() {
718     for (double d : NUMBERS) {
719       checkTryParse(d, Double.toString(d));
720     }
721   }
722 
723   @J2ktIncompatible // hexadecimal doubles
724   @GwtIncompatible // Doubles.tryParse
testTryParseOfToHexStringIsOriginal()725   public void testTryParseOfToHexStringIsOriginal() {
726     for (double d : NUMBERS) {
727       checkTryParse(d, Double.toHexString(d));
728     }
729   }
730 
731   @GwtIncompatible // Doubles.tryParse
testTryParseNaN()732   public void testTryParseNaN() {
733     checkTryParse("NaN");
734     checkTryParse("+NaN");
735     checkTryParse("-NaN");
736   }
737 
738   @GwtIncompatible // Doubles.tryParse
testTryParseInfinity()739   public void testTryParseInfinity() {
740     checkTryParse(Double.POSITIVE_INFINITY, "Infinity");
741     checkTryParse(Double.POSITIVE_INFINITY, "+Infinity");
742     checkTryParse(Double.NEGATIVE_INFINITY, "-Infinity");
743   }
744 
745   private static final String[] BAD_TRY_PARSE_INPUTS = {
746     "",
747     "+-",
748     "+-0",
749     " 5",
750     "32 ",
751     " 55 ",
752     "infinity",
753     "POSITIVE_INFINITY",
754     "0x9A",
755     "0x9A.bE-5",
756     ".",
757     ".e5",
758     "NaNd",
759     "InfinityF"
760   };
761 
762   @GwtIncompatible // Doubles.tryParse
testTryParseFailures()763   public void testTryParseFailures() {
764     for (String badInput : BAD_TRY_PARSE_INPUTS) {
765       assertThat(badInput)
766           .doesNotMatch(
767               Pattern.compile(
768                   Doubles.FLOATING_POINT_PATTERN.pattern(),
769                   Doubles.FLOATING_POINT_PATTERN.flags()));
770       assertThat(Doubles.tryParse(badInput)).isEqualTo(referenceTryParse(badInput));
771       assertThat(Doubles.tryParse(badInput)).isNull();
772     }
773   }
774 
775   @J2ktIncompatible
776   @GwtIncompatible // NullPointerTester
testNulls()777   public void testNulls() {
778     new NullPointerTester().testAllPublicStaticMethods(Doubles.class);
779   }
780 
testStringConverter_convert()781   public void testStringConverter_convert() {
782     Converter<String, Double> converter = Doubles.stringConverter();
783     assertThat(converter.convert("1.0")).isEqualTo((Double) 1.0);
784     assertThat(converter.convert("0.0")).isEqualTo((Double) 0.0);
785     assertThat(converter.convert("-1.0")).isEqualTo((Double) (-1.0));
786     assertThat(converter.convert("1")).isEqualTo((Double) 1.0);
787     assertThat(converter.convert("0")).isEqualTo((Double) 0.0);
788     assertThat(converter.convert("-1")).isEqualTo((Double) (-1.0));
789     assertThat(converter.convert("1e6")).isEqualTo((Double) 1e6);
790     assertThat(converter.convert("1e-6")).isEqualTo((Double) 1e-6);
791   }
792 
testStringConverter_convertError()793   public void testStringConverter_convertError() {
794     try {
795       Doubles.stringConverter().convert("notanumber");
796       fail();
797     } catch (NumberFormatException expected) {
798     }
799   }
800 
testStringConverter_nullConversions()801   public void testStringConverter_nullConversions() {
802     assertThat(Doubles.stringConverter().convert(null)).isNull();
803     assertThat(Doubles.stringConverter().reverse().convert(null)).isNull();
804   }
805 
806   @GwtIncompatible // Double.toString returns different value in GWT.
testStringConverter_reverse()807   public void testStringConverter_reverse() {
808     Converter<String, Double> converter = Doubles.stringConverter();
809     assertThat(converter.reverse().convert(1.0)).isEqualTo("1.0");
810     assertThat(converter.reverse().convert(0.0)).isEqualTo("0.0");
811     assertThat(converter.reverse().convert(-1.0)).isEqualTo("-1.0");
812     assertThat(converter.reverse().convert(1e6)).isEqualTo("1000000.0");
813     assertThat(converter.reverse().convert(1e-6)).isEqualTo("1.0E-6");
814   }
815 
816   @J2ktIncompatible
817   @GwtIncompatible // NullPointerTester
testStringConverter_nullPointerTester()818   public void testStringConverter_nullPointerTester() throws Exception {
819     NullPointerTester tester = new NullPointerTester();
820     tester.testAllPublicInstanceMethods(Doubles.stringConverter());
821   }
822 
823   @GwtIncompatible
testTryParse_withNullNoGwt()824   public void testTryParse_withNullNoGwt() {
825     assertThat(Doubles.tryParse("null")).isNull();
826     try {
827       Doubles.tryParse(null);
828       fail("Expected NPE");
829     } catch (NullPointerException expected) {
830     }
831   }
832 }
833